diff --git a/DateToSpine/CMakeLists.txt b/DateToSpine/CMakeLists.txt index 4b63ce5..4909717 100644 --- a/DateToSpine/CMakeLists.txt +++ b/DateToSpine/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.25) project(DateToSpine VERSION 0.1.0 LANGUAGES CXX) +include(cmake/OfflineDependencies.cmake) + option(DTS_BUILD_TESTS "Build DateToSpine tests" ON) option(DTS_BUILD_GUI "Build the DateToSpine desktop application" ON) option(DTS_BUILD_RUNTIME_PLUGINS "Build bundled Spine runtime adapters" ON) diff --git a/DateToSpine/cmake/OfflineDependencies.cmake b/DateToSpine/cmake/OfflineDependencies.cmake new file mode 100644 index 0000000..7d4a5cf --- /dev/null +++ b/DateToSpine/cmake/OfflineDependencies.cmake @@ -0,0 +1,28 @@ +# DateToSpine is distributed as a source-complete offline project. Configuration +# must fail when a vendored dependency is missing; it must never fetch one. +set(FETCHCONTENT_FULLY_DISCONNECTED ON CACHE BOOL + "Never download dependencies while configuring DateToSpine" FORCE) +set(FETCHCONTENT_UPDATES_DISCONNECTED ON CACHE BOOL + "Never update dependencies while configuring DateToSpine" FORCE) + +function(dts_require_vendored_spine version_line runtime_subdirectory) + set(version_root + "${CMAKE_CURRENT_SOURCE_DIR}/third_party/spine-runtimes/${version_line}") + set(runtime_root "${version_root}/${runtime_subdirectory}") + foreach(required_file IN ITEMS + "${version_root}/LICENSE" + "${runtime_root}/include/spine/spine.h") + if(NOT EXISTS "${required_file}") + message(FATAL_ERROR + "Offline dependency is incomplete: ${required_file}\n" + "Restore the vendored files from the DateToSpine source package. " + "CMake will not download them.") + endif() + endforeach() +endfunction() + +dts_require_vendored_spine("3.8" "spine-cpp/spine-cpp") +dts_require_vendored_spine("4.0" "spine-cpp/spine-cpp") +dts_require_vendored_spine("4.1" "spine-cpp/spine-cpp") +dts_require_vendored_spine("4.2" "spine-cpp/spine-cpp") +dts_require_vendored_spine("4.3" "spine-cpp") diff --git a/DateToSpine/docs/02-系统架构.md b/DateToSpine/docs/02-系统架构.md index b877ad3..f1adaaf 100644 --- a/DateToSpine/docs/02-系统架构.md +++ b/DateToSpine/docs/02-系统架构.md @@ -18,6 +18,8 @@ CMake 只用于开发构建,不是最终用户的运行依赖。Windows 可以使用 Visual Studio Generator 或 Ninja + MSVC。 +五个版本的官方 `spine-cpp` 以普通 vendor 源码纳入主仓库,不使用 Git Submodule。CMake 配置启用完全断开模式并检查必要头文件与许可证;缺失时明确失败,绝不执行依赖下载。这样内网只需克隆一次主仓库即可构建。 + ## 2. 分层结构 ```text diff --git a/DateToSpine/docs/08-离线打包与许可.md b/DateToSpine/docs/08-离线打包与许可.md index 067166f..f068cf2 100644 --- a/DateToSpine/docs/08-离线打包与许可.md +++ b/DateToSpine/docs/08-离线打包与许可.md @@ -15,9 +15,10 @@ Spine Editor 是外部前置软件。DateToSpine 不控制 Editor 自身的授 ## 2. 构建期与运行期网络 -- 开发机可以联网取得依赖和官方测试资源。 -- 正式依赖必须锁定版本和校验值。 -- 可复现构建应支持从内部或本地依赖缓存构建。 +- 五套正式 Spine Runtime 源码直接随主仓库提供,不使用 Submodule、FetchContent 或构建期下载。 +- 内网环境克隆主仓库后即可取得完整 Runtime;若文件缺失,CMake 直接报错,不尝试联网补齐。 +- Qt、CMake 和编译器属于预先安装的构建工具,不由本项目联网安装。 +- 官方测试资源只存在于开发源码树,不进入最终安装包。 - 最终应用运行时不得使用网络。 - CI 下载的官方测试资源不进入打包阶段的输入集合。 diff --git a/DateToSpine/docs/文档索引.md b/DateToSpine/docs/文档索引.md index f59b38c..bfea483 100644 --- a/DateToSpine/docs/文档索引.md +++ b/DateToSpine/docs/文档索引.md @@ -28,6 +28,7 @@ DateToSpine 是一个面向 macOS 和 Windows 的离线桌面工具,用于扫 6. Atlas 纹理只使用 Spine 官方 Texture Unpacker 解包,不提供自研兜底。 7. 软件运行期不使用 CDN、在线 API、在线依赖下载、遥测或资源上传。 8. 官方测试资源仅用于开发和 CI 测试,不进入最终安装包。 +9. 五套官方 Runtime 源码由主仓库直接携带,不使用 Submodule 或构建期下载。 9. 最终安装包只携带 Runtime 许可、第三方许可和必要声明,不携带 Spine Editor 或官方示例资源。 10. 自研源文件按职责拆分,禁止出现数千行的业务代码文件。 11. 主界面只保留拖入资源、预览/动画切换和一键转换;仅在 Editor 自动识别失败时请求路径。 diff --git a/DateToSpine/third_party/spine-runtimes/3.8 b/DateToSpine/third_party/spine-runtimes/3.8 deleted file mode 160000 index 8b4844b..0000000 --- a/DateToSpine/third_party/spine-runtimes/3.8 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8b4844bd4b193ba9e54487ed397a777993cbad56 diff --git a/DateToSpine/third_party/spine-runtimes/3.8/.npmignore b/DateToSpine/third_party/spine-runtimes/3.8/.npmignore new file mode 100644 index 0000000..071fcd0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/.npmignore @@ -0,0 +1,19 @@ +CMakeLists.txt +examples +spine-as3 +spine-c +spine-cocos2d-objc +spine-cocos2dx +spine-corona +spine-csharp +spine-js +spine-libgdx +spine-love +spine-lua +spine-monogame +spine-sfml +spine-starling +spine-threejs +spine-tk2d +spine-unity +spine-xna diff --git a/DateToSpine/third_party/spine-runtimes/3.8/CHANGELOG.md b/DateToSpine/third_party/spine-runtimes/3.8/CHANGELOG.md new file mode 100644 index 0000000..cb4f997 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/CHANGELOG.md @@ -0,0 +1,922 @@ +# 3.8 + +## AS3 +* **Breaking changes** + * Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + * Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + * Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. + +* **Additions** + * Added `SkeletonBinary` to load binary `.skel` files. See `MixAndMatchExample.as` in `spine-startling-example`. + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin#getAttachments()`. Returns all attachments in the skin. + * Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `Skin#addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin#copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### Starling +* Added `MixAndMatchExample.as` to demonstrate the new Skin API additions and how to load binary `.skel` files. +* Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. + +## C +* **Breaking changes** + * Renamed `spSlot#attachmentVertices` to `spSlot#deform`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `spSkin_addAttachment()` to `Skin#spSkin_addAttachment()`. + * Removed `spVertexAttachment_applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `spDeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `spMeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * Added `x` and `y` coordinates for setup pose AABB in `spSkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `spSkin_getAttachments()`. Returns all attachments in the skin. + * Added `spSkin_getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `spSkin_addSkin(spSkin* skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `spSkin_copySkin(spSkin* skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `spVertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * All attachments inserted into skins are reference counted. When the last skin referencing an attachment is disposed, the attachment will also be disposed. + * Added `spAttachment_copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `spMeshAttachment_newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### Cocos2d-Objc +* Added mix-and-match example to demonstrate the new Skin API. +* Added `IKExample`. +* Added `SkeletonAnimation preUpdateWorldTransformsListener` and `SkeletonAnimation postUpdateWorldTransformsListener`. When set, these callbacks will be invokved before and after the skeleton's `updateWorldTransforms()` method is called. See the `IKExample` how it can be used. + +### SFML +* Added mix-and-match example to demonstrate the new Skin API. +* Added `IKExample`. + +## C++ +* **Breaking Changes** + * Renamed `Slot::getAttachmentVertices()` to `Slot::getDeform()`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin::addAttachment()` to `Skin::setAttachment()`. + * Removed `VertexAttachment::applyDeform()` and replaced it with `VertexAttachment::getDeformAttachment()`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `_inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * `AnimationState` and `TrackEntry` now also accept a subclass of `AnimationStateListenerObject` as a listener for animation events in the overloaded `setListener()` method. + * `SkeletonBinary` and `SkeletonJson` now parse and set all non-essential data like audio path. + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin#getAttachments()`. Returns all attachments in the skin. + * Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `Skin#addSkin(Skin &skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin#copySkin(Skin &skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * All attachments inserted into skins are reference counted. When the last skin referencing an attachment is disposed, the attachment will also be disposed. + * Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + * Exposed `x` and `y` on `SkeletonData` through getters and setters. + +* **Bug fixes** + * Fixed binary skeleton loading to stop after default skin attachment load errors, preventing corrupted reads when atlas regions are missing. + +### Cocos2d-x +* Updated to cocos2d-x 3.17.1 +* Added mix-and-match example to demonstrate the new Skin API. +* Exmaple project requires Visual Studio 2019 on Windows +* Added `IKExample`. +* Added `SkeletonAnimation::setPreUpdateWorldTransformsListener()` and `SkeletonAnimation::setPreUpdateWorldTransformsListener()`. When set, these callbacks will be invokved before and after the skeleton's `updateWorldTransforms()` method is called. See the `IKExample` how it can be used. + +### SFML +* Added mix-and-match example to demonstrate the new Skin API. + +### UE4 +* Added `bAutoPlaying` flag to `USpineSkeletonAnimationComponent`. When `false`, the component will not update the internal animation state and skeleton. +* Updated example project to UE 4.22. +* (Re-)Importing Spine assets will perform a version compatibility check and alert users about mismatches in editor mode. +* `USpineSkeletonRendererComponent` allows passing a `USpineSkeletonComponent` to update it. This way, the renderer component can be used without a skeleton component on the same actor. +* Added blueprint-callable methods to `SpineSkeletonComponent` and `SpineSkeletonAnimationComponent` to query and set skins, and enumerate bones, slots, and animations. +* Extended skeleton data editor preview. The preview now shows bones, slots, animations, and skins found in the skeleton data. See this [blog post](http://esotericsoftware.com/blog/Unreal-Engine-4-quality-of-life-improvements). +* Added preview animation and skin fields, allowing you to preview animations and skins right in the editor. See this [blog post](http://esotericsoftware.com/blog/Unreal-Engine-4-quality-of-life-improvements). +* Removed dependency on `RHI`, `RenderCore`, and `ShaderCore`. +* Re-importing atlases and their textures now works consistently in all situations. +* Added mix-and-match example to demonstrate the new Skin API. +* Materials on `SkeletonRendererComponent` are now blueprint read and writeable. This allows setting dynamic material instances at runtime. +* Added `InitialSkin` property to `USpineWidget`. This allows previewing different skins in the UMG Designer. Initial skins can still be overridden via blueprint events such as `On Initialized`. + +## C# ## +* **Breaking changes** + * **Changed `IkConstraintData.Bones` type from `List` to `ExposedList`** for unification reasons. *Note: this modification will most likely not affect user code.* + * Renamed `Slot.AttachmentVertices` to `Slot.Deform`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin.AddAttachment()` to `Skin.SetAttachment()`. + * Removed `FindAttachmentsForSlot(int slotIndex, List attachments)` and `FindNamesForSlot (int slotIndex, List names)` and replaced it with `Skin.GetAttachments(int slotIndex, List attachments)` which returns the combined `SkinEntry` object holding both name and attachment. + * Removed `VertexAttachment.ApplyDeform()` and replaced it with `VertexAttachment.DeformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin.GetAttachments()`. Returns all attachments in the skin. + * Added `Skin.GetAttachments(int slotIndex, List attachments)`. Returns all attachements in the skin for the given slot index. This method replaces `FindAttachmentsForSlot` and `FindNamesForSlot`. + * Added `Skin.AddSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin.CopySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment.Copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment.NewLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### Unity + +* **Breaking changes** + * **Officially supported Unity versions are 2017.1-2020.2**. + * **Spine `.asmdef` files are again active by default**. They have previously been deactivated to `.txt` extension which is now no longer necessary. + * **Removed PoseSkeleton() and PoseWithAnimation()** extension methods to prevent issues where animations are not mixed out. Problem was that these methods did not set AnimationState, leaving incorrect state at e.g. attachments enabled at slots when starting subsequent animations. As a replacement you can use `AnimationState.ClearTrack(0);` followed by `var entry = AnimationState.SetAnimation(0, animation, loop); entry.TrackTime = time` to achieve similar behaviour. + * **The `Shadow alpha cutoff` shader parameter is now respecting slot-color alpha** values at all Spine shaders. A fragment's texture color alpha is multiplied with slot-color alpha before the result is tested against the `Shadow alpha cutoff` threshold. + * **Removed redundant `Attachment.GetClone()` and `MeshAttachment.GetLinkedClone()` extension methods**. Use methods `Attachment.Copy` and `MeshAttachment.NewLinkedMesh()` instead. + * **Renamed extension method `Attachment.GetClone(bool cloneMeshesAsLinked)` to `Attachment.GetCopy(bool cloneMeshesAsLinked)`** to follow the naming scheme of the Spine API. + * `SkeletonDataAsset.atlasAssets` is now an array of the base class `AtlasAssetBase` instead of `SpineAtlasAsset`, which provides `IEnumerable<> Materials` instead of `List<> materials`. Replace any access via `atlasAsset.materials[0]` with `atlasAsset.Materials.First()` and add a `using System.Linq;` statement. + * **Changed `MeshAttachment.GetLinkedMesh()` method signatures:** removed optional parameters `bool inheritDeform = true, bool copyOriginalProperties = false`. + * Changed namespace `Spine.Unity.Modules` to `Spine.Unity` and `Spine.Unity.Examples` after restructuring (see section below) in respective classes: + * When receiving namespace related errors, replace using statements of `using Spine.Unity.Modules.AttachmentTools;` with `using Spine.Unity.AttachmentTools;`. You can remove `using Spine.Unity.Modules;` statements when a `using Spine.Unity` statement is already present in the file. + * `AttachmentTools`, `SkeletonPartsRenderer`, `SkeletonRenderSeparator`, `SkeletonRendererCustomMaterials` changed to namespace `Spine.Unity`. + * `SkeletonGhost`, `SkeletonGhostRenderer`, `AtlasRegionAttacher`, `SkeletonGraphicMirror`, `SkeletonRagdoll`, `SkeletonRagdoll2D`, `SkeletonUtilityEyeConstraint`, `SkeletonUtilityGroundConstraint`, `SkeletonUtilityKinematicShadow` changed to namespace `Spine.Unity.Examples`. + * Split `Editor/Utility/SpineEditorUtilities` class into multiple files with partial class qualifier. + * Nested classes `SpineEditorUtilities.AssetUtility` and `SpineEditorUtilities.EditorInstantiation` are now no longer nested. If you receive namespace related errors, replace any occurrance of + * `SpineEditorUtilities.AssetUtility` with `AssetUtility` and + * `SpineEditorUtilities.EditorInstantiation` with `EditorInstantiation`. + * **Timeline Support has been moved to a separate UPM Package** Previously the Spine Timeline integration was located in the `Modules/Timeline` directory and was deactivated by default, making it necessary to activate it via the Spine Preferences. Now the Timeline integration has been moved to an additional UPM package which can be found under `Modules/com.esotericsoftware.spine.timeline`. + * **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + a) the `Packages` directory in your project where it will automatically be loaded, or + b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + The Project panel should now show an entry `Spine Timeline Extensions` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + * `SkeletonMecanim`'s `Layer Mix Mode` enum name `MixMode.SpineStyle` has been renamed to `MixMode.Hard`. This is most likely not set via code and thus unlikely to be a problem. Serialized scenes and prefabs are unaffected. + * `SkeletonRootMotion` and `SkeletonMecanimRootMotion` components now support arbitrary bones in the hierarchy as `Root Motion Bone`. Previously there were problems when selecting a non-root bone as `Root Motion Bone`. `Skeleton.ScaleX` and `.ScaleY` and parent bone scale is now respected as well. + +* **Additions** + * **Spine Preferences stored in Assets/Editor/SpineSettings.asset** Now Spine uses the new `SettingsProvider` API, storing settings in a SpineSettings.asset file which can be shared with team members. Your old preferences are automatically migrated to the new system. + * Added support for Unity's SpriteMask to `SkeletonAnimation` and `SkeletonMecanim`. All mask interaction modes are supported. See this [blog post](http://esotericsoftware.com/blog/Unity-SpriteMask-and-RectMask2D-support). + * Added support for Unity's RectMask2D to SkeletonGraphics. See this [blog post](http://esotericsoftware.com/blog/Unity-SpriteMask-and-RectMask2D-support). + * Added `Create 2D Hinge Chain` button at `SkeletonUtilityBone` inspector, previously only `Create 3D Hinge Chain` was available. + * **Now supporting Lightweight Render Pipeline (LWRP) through an additional UPM package.** + * **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + * a) the `Packages` directory in your project where it will automatically be loaded, or + * b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + > If you are using git and Unity 2019.2 or newer versions and receive an error that dependencies could not be resolved by the package manager (only higher versions of Unity's `Lightweight RP` package are available, e.g. `6.9.0` and up), please copy the prepared package-UNITYVERSION.json file for your Unity version (e.g. `package-2019.2.json`) over the existing package.json file to change the dependency accordingly. Unfortunately Unity's Package Manager does not provide a way to specify a version range for a dependency like "5.7.2 - 6.9.0" yet, so this manual step is necessary for git users. + + The Project panel should now show an entry `Spine Lightweight RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + * **Usage:** The package provides two shaders specifically built for the lightweight render pipeline: + * `Lightweight Render Pipeline/Spine/Skeleton`, as a lightweight variant of the `Spine/Skeleton` shader, + * `Lightweight Render Pipeline/Spine/Skeleton Lit`, as a lightweight variant of the `Spine/Skeleton Lit` shader and + * `Lightweight Render Pipeline/Spine/Sprite`, as a lightweight variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the lightweight render pipeline. The shaders can be assigned to materials as usual and will respect your settings of the assigned `LightweightRenderPipelineAsset` under `Project Settings - Graphics`. + * **Restrictions** As all Spine shaders, the LWRP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + * **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.lwrp-shaders-3.8/Examples/LWRP Shaders.unity` that demonstrates usage of the LWRP shaders. + * Added `Spine/Skeleton Lit ZWrite` shader. This variant of the `Spine/Skeleton Lit` shader writes to the depth buffer with configurable depth alpha threshold. Apart from that it is identical to `Spine/Skeleton Lit`. + * Additional yield instructions to wait for animation track events `End`, `Complete` and `Interrupt`. + * `WaitForSpineAnimationComplete` now proves an additional `bool includeEndEvent` parameter, defaults to `false` (previous behaviour). + * Added a new `WaitForSpineAnimationEnd` yield instruction. + * Added a new generic `WaitForSpineAnimation` yield instruction which can be configured to wait for any combination of animation track events. It is now used as base class for `WaitForSpineAnimationComplete` and `WaitForSpineAnimationEnd`. + * Additional **Fix Draw Order** parameter at SkeletonRenderer, defaults to `disabled` (previous behaviour). + Applies only when 3+ submeshes are used (2+ materials with alternating order, e.g. "A B A"). + If true, MaterialPropertyBlocks are assigned at each material to prevent aggressive batching of submeshes + by e.g. the LWRP renderer, leading to incorrect draw order (e.g. "A1 B A2" changed to "A1A2 B"). + You can leave this parameter disabled when everything is drawn correctly to save the additional performance cost. + * **Additional Timeline features.** SpineAnimationStateClip now provides a `Speed Multiplier`, a start time offset parameter `Clip In`, support for blending successive animations by overlapping tracks. An additional `Use Blend Duration` parameter *(defaults to true)* allows for automatic synchronisation of MixDuration with the current overlap blend duration. An additional Spine preferences parameter `Use Blend Duration` has been added which can be disabled to default to the previous behaviour before this update. + * Additional `SpriteMask and RectMask2D` example scene added for demonstration of mask setup and interaction. + * `Real physics hinge chains` for both 2D and 3D physics. The [SkeletonUtilityBone](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) Inspector provides an interface to create 2D and 3D hinge chains. Previously created chains have only been respecting gravity, but not momentum of the skeleton or parent bones. The new physics rig created when pressing `Create 3D Hinge Chain` and `Create 2D Hinge Chain` creates a more complex setup that also works when flipping the skeleton. Note that the chain root node is no longer parented to bones of the skeleton. This is a requirement in Unity to have momentum applied properly - do not reparent the chain root to bones of your skeleton, or you will loose any momentum applied by the skeleton's movement. + * `Outline rendering functionality for all shaders.` Every shader now provides an additional set of `Outline` parameters to enable custom outline rendering. When outline rendering is enabled via the `Material` inspector, it automatically switches the shader to the respective `Spine/Outline` shader variant. Outlines are generated by sampling neighbour pixels, so be sure to add enough transparent padding when exporting your atlas textures to fit the desired outline width. In order to enable outline rendering at a skeleton, it is recommended to first prepare an additional outline material copy and then switch the material of the target skeleton to this material. This prevents unnecessary additional runtime material copies and drawcalls. Material switching can be prepared via a [SkeletonRendererCustomMaterials](http://esotericsoftware.com/spine-unity#SkeletonRendererCustomMaterials) component and then enabled or disabled at runtime. Alternatively, you can also directly modify the `SkeletonRenderer.CustomMaterialOverride` property. + Outline rendering is fully supported on `SkeletonGraphic` shaders as well. + * Added `SkeletonRenderer.EditorSkipSkinSync` scripting API property to be able to set custom skins in editor scripts. Enable this property when overwriting the Skeleton's skin from an editor script. Without setting this parameter, changes will be overwritten by the next inspector update. Only affects Inspector synchronisation of skin with `initialSkinName`, not startup initialization. + * All `Spine/SkeletonGraphic` shaders now provide a parameter `CanvasGroup Compatible` which can be enabled to support `CanvasGroup` alpha blending. For correct results, you should then disable `Pma Vertex Colors` in the `SkeletonGraphic` Inspector, in section `Advanced` (otherwise Slot alpha will be applied twice). + * **Now supporting Universal Render Pipeline (URP), including the 2D Renderer pipeline, through an additional UPM package.** + * **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + * a) the `Packages` directory in your project where it will automatically be loaded, or + * b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + The Project panel should now show an entry `Spine Universal RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + * **Usage:** The package provides two shaders specifically built for the universal render pipeline: + * `Universal Render Pipeline/Spine/Skeleton`, as a universal variant of the `Spine/Skeleton` shader, + * `Universal Render Pipeline/Spine/Skeleton Lit`, as a universal variant of the `Spine/Skeleton Lit` shader, + * `Universal Render Pipeline/Spine/Sprite`, as a universal variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the universal render pipeline, + * `Universal Render Pipeline/2D/Spine/Skeleton Lit`, as a universal 2D Renderer variant of the `Spine/Skeleton Lit` shader, and + * `Universal Render Pipeline/2D/Spine/Sprite`, as a universal 2D Renderer variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders. + The shaders can be assigned to materials as usual and will respect your settings of the assigned `UniversalRenderPipelineAsset` under `Project Settings - Graphics`. + * **Restrictions** As all Spine shaders, the URP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + * **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.urp-shaders-3.8/Examples/URP Shaders.unity` that demonstrates usage of the URP shaders. + * Spine Preferences now provide an **`Atlas Texture Settings`** parameter for applying customizable texture import settings at all newly imported Spine atlas textures. + When exporting atlas textures from Spine with `Premultiply alpha` enabled (the default), you can leave it at `PMATexturePreset`. If you have disabled `Premultiply alpha`, set it to the included `StraightAlphaTexturePreset` asset. You can also create your own `TextureImporter` `Preset` asset and assign it here (include `PMA` or `Straight` in the name). In Unity versions before 2018.3 you can use `Texture2D` template assets instead of the newer `Preset` assets. Materials created for imported textures will also have the `Straight Alpha Texture` parameter configured accordingly. + * All `Sprite` shaders (including URP and LWRP extension packages) now provide an additional `Fixed Normal Space` option `World-Space`. PReviously options were limited to `View-Space` and `Model-Space`. + * `SkeletonGraphic` now fully supports [`SkeletonUtility`](http://esotericsoftware.com/spine-unity#SkeletonUtility) for generating a hierarchy of [`SkeletonUtilityBones`](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) in both modes `Follow` and `Override`. This also enables creating hinge chain physics rigs and using `SkeletonUtilityConstraints` such as `SkeletonUtilityGroundConstraint` and `SkeletonUtilityEyeConstraint` on `SkeletonGraphic`. + * Added `OnMeshAndMaterialsUpdated` callback event to `SkeletonRenderer` and `SkeletonGraphic`. It is issued at the end of `LateUpdate`, before rendering. + * Added `Skeleton-OutlineOnly` single pass shader to LWRP and URP extension modules. It can be assigned to materials as `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly`. This allows for separate outline child *GameObjects* that reference the existing Mesh of their parent, and re-draw the mesh using this outline shader. + * Added example component `RenderExistingMesh` to render a mesh again with different materials, as required by the new `Skeleton-OutlineOnly` shaders. + In URP the outline has to be rendered via a separate GameObject as URP does not allow multiple render passes. To add an outline to your SkeletenRenderer: + 1) Add a child GameObject and move it a bit back (e.g. position Z = 0.01). + 2) Add a `RenderExistingMesh` component, provided in the `Spine Examples/Scripts/Sample Components` directory. + 3) Copy the original material, add *_Outline* to its name and set the shader to `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly`. + 4) Assign this *_Outline* material at the `RenderExistingMesh` component under *Replacement Materials*. + * Added `Outline Shaders URP` example scene to URP extension module to demonstrate the above additions. + * Added support for Unity's [`SpriteAtlas`](https://docs.unity3d.com/Manual/class-SpriteAtlas.html) as atlas provider (as an alternative to `.atlas.txt` and `.png` files) alongside a skeleton data file. There is now an additional `Spine SpriteAtlas Import` tool window accessible via `Window - Spine - SpriteAtlas Import`. Additional information can be found in a new section on the [spine-unity documentation page](http://esotericsoftware.com/spine-unity#Advanced---Using-Unity-SpriteAtlas-as-Atlas-Provider). + * Added support for **multiple atlas textures at `SkeletonGraphic`**. You can enable this feature by enabling the parameter `Multiple CanvasRenders` in the `Advanced` section of the `SkeletonGraphic` Inspector. This automatically creates the required number of child `CanvasRenderer` GameObjects for each required draw call (submesh). + * Added support for **Render Separator Slots** at `SkeletonGraphic`. Render separation can be enabled directly in the `Advanced` section of the `SkeletonGraphic` Inspector, it does not require any additional components (like `SkeletonRenderSeparator` or `SkeletonPartsRenderer` for `SkeletonRenderer` components). When enabled, additional separator GameObjects will be created automatically for each separation part, and `CanvasRenderer` GameObjects re-parented to them accordingly. The separator GameObjects can be moved around and re-parented in the hierarchy according to your requirements to achieve the desired draw order within your `Canvas`. A usage example can be found in the updated `Spine Examples/Other Examples/SkeletonRenderSeparator` scene. + * Added `SkeletonGraphicCustomMaterials` component, providing functionality to override materials and textures of a `SkeletonGraphic`, similar to `SkeletonRendererCustomMaterials`. Note: overriding materials or textures per slot is not provided due to structural limitations. + * Added **Root Motion support** for `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic` via new components `SkeletonRootMotion` and `SkeletonMecanimRootMotion`. The `SkeletonAnimation` and `SkeletonGraphic` component Inspector now provides a line `Root Motion` with `Add Component` and `Remove Component` buttons to add/remove the new `SkeletonRootMotion` component to your GameObject. The `SkeletonMecanim` Inspector detects whether root motion is enabled at the `Animator` component and adds a `SkeletonMecanimRootMotion` component automatically. + * `SkeletonMecanim` now provides an additional `Custom MixMode` parameter under `Mecanim Translator`. It is enabled by default in version 3.8 to maintain current behaviour, using the set `Mix Mode` for each Mecanim layer. When disabled, `SkeletonMecanim` will use the recommended `MixMode` according to the layer blend mode. Additional information can be found in the [Mecanim Translator section](http://esotericsoftware.com/spine-unity#Parameters-for-animation-blending-control) on the spine-unity documentation pages. + * Added **SkeletonGraphic Timeline support**. Added supprot for multi-track Timeline preview in the Editor outside of play mode (multi-track scrubbing). See the [Timeline-Extension-UPM-Package](http://esotericsoftware.com/spine-unity#Timeline-Extension-UPM-Package) section of the spine-unity documentation for more information. + * Added support for double-sided lighting at all `SkeletonLit` shaders (including URP and LWRP packages). + * Added frustum culling update mode parameters `Update When Invisible` (Inspector parameter) and `UpdateMode` (available via code) to all Skeleton components. This provides a simple way to disable certain updates when the `Renderer` is no longer visible (outside all cameras, culled in frustum culling). The new `UpdateMode` property allows disabling updates at a finer granularity level than disabling the whole component. Available modes are: `Nothing`, `OnlyAnimationStatus`, `EverythingExceptMesh` and `FullUpdate`. + * Added a new `Spine/Outline/OutlineOnly-ZWrite` shader to provide correct outline-only rendering. Note: the shader requires two render passes and is therefore not compatible with URP. The `Spine Examples/Other Examples/Outline Shaders` example scene has been updated to demonstrate the new shader. + * Added `OnMeshAndMaterialsUpdated` callback event to `SkeletonRenderSeparator` and `SkeletonPartsRenderer`. It is issued at the end of `LateUpdate`, before rendering. + * Added `Root Motion Scale X/Y` parameters to `SkeletonRootMotionBase` subclasses (`SkeletonRootMotion` and `SkeletonMecanimRootMotion`). Also providing `AdjustRootMotionToDistance()` and other methods to allow for easy delta compensation. Delta compensation can be used to e.g. stretch a jump to a given distance. Root motion can be adjusted at the start of an animation or every frame via `skeletonRootMotion.AdjustRootMotionToDistance(targetPosition - transform.position, trackIndex);`. + * Now providing a `Canvas Group Tint Black` parameter at the `SkeletonGraphic` Inspector in the `Advanced` section. When using the `Spine/SkeletonGraphic Tint Black` shader you can enable this parameter to receive proper blending results when using `Additive` blend mode under a `CanvasGroup`. Be sure to also have the parameter `CanvasGroup Compatible` enabled at the shader. Note that the normal `Spine/SkeletonGraphic` does not support `Additive` blend mode at a `CanvasGroup`, as it requires additional shader channels to work. + * Added `Mix and Match Skins` example scene to demonstrate how the 3.8 Skin API and combining skins can be used for a wardrobe and equipment use case. + * Spine Timeline Extensions: Added `Hold Previous` parameter at `SpineAnimationStateClip`. + * Added more warning messages at incompatible SkeletonRenderer/SkeletonGraphic Component vs Material settings. They appear both as an info box in the Inspector as well as upon initialization in the Console log window. The Inspector box warnings can be disabled via `Edit - Preferences - Spine`. + * Now providing `BeforeApply` update callbacks at all skeleton animation components (`SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic`). + * Added `BoundingBoxFollowerGraphic` component. This class is a counterpart of `BoundingBoxFollower` that can be used with `SkeletonGraphic`. + * Added Inspector context menu functions `SkeletonRenderer - Add all BoundingBoxFollower GameObjects` and `SkeletonGraphic - Add all BoundingBoxFollowerGraphic GameObjects` that automatically generate bounding box follower GameObjects for every `BoundingBoxAttachment` for all skins of a skeleton. + * `GetRemappedClone()` now provides an additional parameter `pivotShiftsMeshUVCoords` for `MeshAttachment` to prevent uv shifts at a non-central Sprite pivot. This parameter defaults to `true` to maintain previous behaviour. + * `SkeletonRenderer` components now provide an additional update mode `Only Event Timelines` at the `Update When Invisible` property. This mode saves additional timeline updates compared to update mode `Everything Except Mesh`. + * Now all URP (Universal Render Pipeline) and LWRP (Lightweight Render Pipeline) shaders support SRP (Scriptable Render Pipeline) batching. See [Unity SRPBatcher documentation pages](https://docs.unity3d.com/Manual/SRPBatcher.html) for additional information. + * Sprite shaders now provide four `Diffuse Ramp` modes as an Inspector Material parameter: `Hard`, `Soft`, `Old Hard` and `Old Soft`. In spine-unity 3.8 it defaults to `Old Hard` to keep the behaviour of existing projects unchanged. Note that `Old Hard` and `Old Soft` ramp versions were using only the right half of the ramp texture, and additionally multiplying the light intensity by 2, both leading to brighter lighting than without a ramp texture active. The new ramp modes `Hard` and `Soft` use the full ramp texture and do not modify light intensity, being consistent with lighting without a ramp texture active. + * Added **native support for slot blend modes** `Additive`, `Multiply` and `Screen` with automatic assignment at newly imported skeleton assets. `BlendModeMaterialAssets` are now obsolete and replaced by the native properties at `SkeletonDataAsset`. The `SkeletonDataAsset` Inspector provides a new `Blend Modes - Upgrade` button to upgrade an obsolete `BlendModeMaterialAsset` to the native blend modes properties. This upgrade will be performed automatically on imported and re-imported assets in Unity 2020.1 and newer to prevent reported `BlendModeMaterialAsset` issues in these Unity versions. spine-unity 4.0 and newer will automatically perform this upgrade regardless of the Unity version. + * `BoneFollower` and `BoneFollowerGraphic` components now provide better support for following bones when the skeleton's Transform is not the parent of the follower's Transform. Previously e.g. rotating a common parent Transform did not lead to the desired result, as well as negatively scaling a skeleton's Transform when it is not a parent of the follower's Transform. + * URP and LWRP `Sprite` and `SkeletonLit` shaders no longer require `Advanced - Add Normals` enabled to properly cast and receive shadows. It is recommended to disable `Add Normals` if normals are otherwise not needed. + * Added an example component `RootMotionDeltaCompensation` located in `Spine Examples/Scripts/Sample Components` which can be used for applying simple delta compensation. You can enable and disable the component to toggle delta compensation of the currently playing animation on and off. + * Root motion delta compensation now allows to only adjust X or Y components instead of both. Adds two parameters to `SkeletonRootMotionBase.AdjustRootMotionToDistance()` which default to adjusting both X and Y as before. The `RootMotionDeltaCompensation` example component exposes these parameters as public attributes. + * Root motion delta compensation now allows to also add translation root motion to e.g. adjust a horizontal jump upwards or downwards over time. This is necessary because a Y root motion of zero cannot be scaled to become non-zero. + * `Attachment.GetRemappedClone(Sprite)` method now provides an additional optional parameter `useOriginalRegionScale`. When set to `true`, the replaced attachment's scale is used instead of the Sprite's `Pixel per Unity` setting, allowing for more consistent scaling. *Note:* When remapping Sprites, be sure to set the Sprite's `Mesh Type` to `Full Rect` and not `Tight`, otherwise the scale will be wrong. + +* **Changes of default values** + * `SkeletonMecanim`'s `Layer Mix Mode` now defaults to `MixMode.MixNext` instead of `MixMode.MixAlways`. + * `BlendModeMaterialAsset` and it's instance `Default BlendModeMaterials.asset` now have `Apply Additive Material` set to `true` by default in order to apply all blend modes by default. + +* **Deprecated** + * Deprecated `Modules/SlotBlendModes/SlotBlendModes` component. Changed namespace from `Spine.Unity.Modules` to `Spine.Unity.Deprecated`. Moved to `Deprecated/SlotBlendModes`. + +* **Restructuring (Non-Breaking)** + + Note: The following changes will most likely not affect users of the Spine-Unity runtime as the API remains unchanged and no references are invalidated. + * Removed duplicates of `.cginc` files in `Modules/Shaders/Sprite` that were also present in the `Modules/Shaders/Sprite/CGIncludes` directory. + * Moved shaders from `Modules/Shaders` to `Shaders` directory. + * Moved shaders from `Modules/SkeletonGraphic/Shaders` to `Shaders/SkeletonGraphic`. + * Renamed shader `Shaders/Spine-SkeletonLit.shader` to `Shaders/Spine-Skeleton-Lit.shader`. + * Moved components from `SkeletonGraphic` to `Components` and `Components/Following` except for `SkeletonGraphicMirror` which was moved to `Spine Examples/Scripts/Sample Components`. + * Moved `BoneFollower`, `BoneFollowerGraphic` and `PointFollower` from `Components` directory to `Components/Following`. + * Moved `BoundingBoxFollower` component from `Modules/BoundingBoxFollower` to `Components/Following`. + * Moved `Modules/SkeletonRenderSeparator` directory to `Components/SkeletonRenderSeparator`. + * Moved `Modules/CustomMaterials` directory to `Components/SkeletonRendererCustomMaterials`. + * Moved `Asset Types/BlendModeMaterialsAsset.cs` class, `Shaders/BlendModes/Default BlendModeMaterials.asset` and materials from `Shaders/BlendModes` to `SkeletonDataModifierAssets/BlendModeMaterials` directory. + * Moved `Modules/Ghost` directory to `Spine Examples/Scripts/Sample Components/Ghost`. + * Moved `Modules/SkeletonUtility Modules` directory to `Spine Examples/Scripts/Sample Components/SkeletonUtility Modules`. + * Moved `Modules/AnimationMatchModifier` directory to `Spine Examples/Scripts/MecanimAnimationMatchModifier`. + * Moved `SkeletonRagdoll` and `SkeletonRagdoll2D` components from `Modules/Ragdoll` directory to `Spine Examples/Scripts/Sample Components/SkeletonUtility Modules`. + * Moved `AttachmentTools.cs` to `Utility` directory. + * Split the file `AttachmentTools` into 5 separate files for each contained class. No namespace or other API changes performed. + * Split the file `Mesh Generation/SpineMesh` into 4 separate files for each contained class. No namespace or other API changes performed. + * Moved `SkeletonExtensions.cs` to `Utility` directory. + * Moved `Modules/YieldInstructions` directory to `Utility/YieldInstructions`. + * Moved corresponding editor scripts of the above components to restructured directories as well. + * Renamed inspector editor class `PointFollowerEditor` to `PointFollowerInspector` for consistency reasons. + +### XNA/MonoGame +* Updated to latest MonoGame version 3.7.1 +* Rewrote example project to be cleaner and better demonstrate basic Spine features. +* Added mix-and-match example to demonstrate the new Skin API. +* Added normalmap support via `SpineEffectNormalmap` and support for loading multiple texture layers following a suffix-pattern. Please see the example code on how to use them. + +## Java +* **Breaking changes** + * Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + * Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * `JsonRollback` tool now converts from 3.8 JSON to 3.7. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin#getAttachments()`. Returns all attachments in the skin. + * Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `Skin#addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin#copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### libGDX +* `SkeletonViewer` can load a skeleton by specifying it as the first argument on the command line. +* Added mix-and-match example to demonstrate the new Skin API. + +## Lua +* **Breaking changes** + * Renamed `Slot:getAttachmentVertices()` to `Slot#deform`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin:addAttachment()` to `Skin#setAttachment()`. + * Removed `VertexAttachment:applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed the `.json` file format to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin:getAttachments()`. Returns all attachments in the skin. + * Added `Skin:getAttachments(slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `Skin:addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin:copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment:copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment:newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### Love2D +* Added support for 0-1 RGBA color component range change in Löve 0.11+. Older Löve versions using the 0-255 range are still supported! +* Added mix-and-match example to demonstrate the new Skin API. + +### Corona +* Added mix-and-match example to demonstrate the new Skin API. + +## Typescript/Javascript +* **Breaking changes** + * Renamed `MixDirection.in/out` to `MixDirection.mixIn/mixOut` as it was crashing a JS compressor. + * Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + * Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + * Updated runtime to be compatible with TypeScript 3.6.3. + +* **Additions** + * Added support for loading binary data via `AssetManager#loadBinary()`. `AssetManager#get()` will return a `Uint8Array` for such assets. + * Added support for loading binaries via new `SkeletonBinary`. Parses a `Uint8Array`. + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin#getAttachments()`. Returns all attachments in the skin. + * Added `Skin#getAttachments(slotIndex: number)`. Returns all attachements in the skin for the given slot index. + * Added `Skin#addSkin(skin: Skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin#copySkin(skin: Skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + * Added `AssetManager.setRawDataURI(path, data)`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. + +### WebGL backend +* `Input` can now take a partially defined implementation of `InputListener`. +* Added mix-and-match example to demonstrate the new Skin API. + +### Canvas backend + +### Three.js backend +* `SkeletonMesh` now takes an optional `SkeletonMeshMaterialParametersCustomizer` function that allows you to modify the `ShaderMaterialParameters` before the material is finalized. Use it to modify things like THREEJS' `Material.depthTest` etc. See #1590. + +### Player +* `SpinePlayer#setAnimation()` can now be called directly to set the animation being displayed. +* The player supports loading `.skel` binary skeleton files by setting the `SpinePlayerConfig#skelUrl` field instead of `SpinePlayerConfig#jsonUrl`. +* Added `SpinePlayerConfig#rawDataURIs`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. See the example for a demonstration. + +# 3.7 + +## AS3 +* **Breaking changes** + * The completion event will fire for looped 0 duration animations every frame. + * `MixPose` is now called `MixBlend` + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Starling +* Added support for vertex effects. See `RaptorExample.as` +* Added 'getTexture()' method to 'StarlingTextureAtlasAttachmentLoader' +* Breaking change: if a skeleton requires two color tinting, you have to enable it via `SkeletonSprite.twoColorTint = true`. In this case the skeleton will use the `TwoColorMeshStyle`, which internally uses a different vertex layout and shader. This means that skeletons with two color tinting enabled will break batching and hence increase the number of draw calls in your app. +* Added `VertexEffect` and implementations `JitterEffect` and `SwirlEffect`. Allows you to modify vertices before they are submitted for drawing. See Starling changes. +* Fix issues with StarlingAtlasAttachmentLoader, see https://github.com/EsotericSoftware/spine-runtimes/issues/939 +* Fix issues with region trimming support, see https://github.com/EsotericSoftware/spine-runtimes/commit/262bc26c64d4111002d80e201cb1a3345e6727df +* Added support for overriding `StarlingAtlasAttachmentLoader#getTexture()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/ea7dbecb98edc74e439aa9ef90dcf6eed865f718 +* Texture atlas operations are no longer handled in `Starling#newRegionAttachment` and `Starling#newMeshAttachment` but delegated to the atlas. +* Added sample for additive animation blending, see https://github.com/EsotericSoftware/spine-runtimes/blob/6a556de01429878df47bb276a97959a8bdbbe32f/spine-starling/spine-starling-example/src/spine/examples/OwlExample.as +* Added sample on how to use bounding box attachment vertices https://github.com/EsotericSoftware/spine-runtimes/commit/e20428b02699226164fa73ba4b12f7d029ae6f4d +* Fully transparent meshes are not submitted for rendering. +* No hit-tests are performed when a skeleton is invisible. + +## C +* **Breaking changes** + * Listeners on `spAnimationState` and `spTrackEntry` will now also be called if a track entry gets disposed as part of disposing an animation state. + * The completion event will fire for looped 0 duration animations every frame. + * The spine-cocos2dx and spine-ue4 runtimes are now based on spine-cpp. See below for changes. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 + * `spMeshAttachment` has two new fields `regionTextureWith` and `regionTextureHeight`. These must be set in custom attachment loader. See `AtlasAttachmentLoader`. +* **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `spTransformConstraintData`. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `spVertexEffect` and corresponding implementations `spJitterVertexEffect` and `spSwirlVertexEffect`. Create/dispose through the corresponding `spXXXVertexEffect_create()/dispose()` functions. Set on framework/engine specific renderer. + * Functions in `extension.h` are not prefixed with `_sp` instead of just `_` to avoid interference with other libraries. + * Introduced `SP_API` macro. Every spine-c function is prefixed with this macro. By default, it is an empty string. Can be used to markup spine-c functions with e.g. ``__declspec` when compiling to a dll or linking to that dll. + * Added `void *userData` to `spAnimationState`to be consumed in callbacks. + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `spTrackEntry->mixBlend = SP_MIXBLEND_ADD)` on each track. To specify the blend percentage, set `spTrackEntry->alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Optimized attachment lookup to give a 40x speed-up. See https://github.com/EsotericSoftware/spine-runtimes/commit/cab81276263890b65d07fa2329ace16db1e365ff + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `spTrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Cocos2d-Objc +* Added vertex effect support to modify vertices of skeletons on the CPU. See `RaptorExample.m`. +* Explanation how to handle ARC, see https://github.com/EsotericSoftware/spine-runtimes/commit/a4f122b08c5e2a51d6aad6fc5a947f7ec31f2eb8 +* The super class `::update()` method of `SkeletonRenderer` is now called, see https://github.com/EsotericSoftware/spine-runtimes/commit/f7bb98185236a6d8f35bfefc70afe4f31e9ec9d2 +* Added improved tint-black shader. + +### SFML +* `spine-sfml.h` no longer defines `SPINE_SHORT_NAMES` to avoid collisions with other APIs. See #1058. +* Added support for vertex effects. See raptor example. +* Added premultiplied alpha support to `SkeletonDrawable`. Use `SkeletonDrawable::setUsePremultipliedAlpha()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/34086c1f41415309b2ecce86055f6656fcba2950 +* Added additive animation blending sample, see https://github.com/EsotericSoftware/spine-runtimes/blob/b7e712d3ca1d6be3ebcfe3254dc2cea9c44dda71/spine-sfml/example/main.cpp#L369 + +## C++ +* ** Additions ** + * Added C++ Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. + * Added parsing of non-essential data (fps, images path, audio path) to for `.json`/`.skel` parsers. + +### Cocos2d-x +* Added ETC1 alpha support, thanks @halx99! Does not work when two color tint is enabled. +* Added `spAtlasPage_setCustomTextureLoader()` which let's you do texture loading manually. Thanks @jareguo. +* Added `SkeletonRenderer:setSlotsRange()` and `SkeletonRenderer::createWithSkeleton()`. This allows you to split rendering of a skeleton up into multiple parts, and render other nodes in between. See `SkeletonRendererSeparatorExample.cpp` for an example. +* Fully transparent attachments will not be rendered, improving rendering performance. +* Added improved tint-black shader. +* Updated to cocos2d-x 3.16 +* The skeleton setup pose and world transform are now calculated on initialization to avoid flickering on start-up. +* Updated to cocos2d-x 3.17.1 +* **Breaking change**: Switched from [spine-c](spine-c) to [spine-cpp](spine-cpp) as the underlying Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. + * Added `Cocos2dAttachmentLoader` to be used when constructing an `Atlas`. Used by default by `SkeletonAnimation` and `SkeletonRenderer` when creating instances via the `createXXX` methods. + * All C structs and enums `spXXX` have been replaced with their C++ equivalents `spine::XXX` in all public interfaces. + * All instantiations via `new` of C++ classes from spine-cpp should contain `(__FILE__, __LINE__)`. This allows the tracking of instantations and detection of memory leaks via the `spine::DebugExtension`. + +### SFML +* Create a second SFML backend using [spine-cpp](spine-cpp/). See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. +* Added support for vertex effects. See raptor example. +* Added premultiplied alpha support to `SkeletonDrawable`. Use `SkeletonDrawable::setUsePremultipliedAlpha()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/34086c1f41415309b2ecce86055f6656fcba2950 +* Added additive animation blending sample, see https://github.com/EsotericSoftware/spine-runtimes/blob/b7e712d3ca1d6be3ebcfe3254dc2cea9c44dda71/spine-sfml/example/main.cpp#L369 + +### UE4 + * spine-c is now exposed from the plugin shared library on Windows via __declspec. + * Updated to Unreal Engine 4.18 + * Added C++ example, see https://github.com/EsotericSoftware/spine-runtimes/commit/15011e81b7061495dba45e28b4d3f4efb10d7f40 + * `SkeletonRendererComponent` generates collision meshes by default. + * Disabled generation of collision meshes by `SkeletonRendererComponent`. Both `ProceduralMeshComponent` and `RuntimeMeshComponent` have a bug that generates a new PhysiX file every frame per component. Users are advised to add a separate collision shape to the root scene component of an actor instead. + * Using UE4 `FMemory` allocator by default. This should fix issues on some consoles. + * **Breaking change** moved away from `RuntimeMeshComponent`, as its maintainance has seized, back to `ProceduralMeshComponent`. Existing projects should just work. However, if you run into issues, you may have to remove the old `SpineSkeletonRendererComponent` and add a new one to your existing actors. + * **Breaking change** due to the removal of `RuntimeMeshComponent` and reversal to `ProceduralMeshComponent`, two color tinting is currently not supported. `ProceduralMeshComponent` does not support enough vertex attributes for us to encode the second color in the vertex stream. You can remove the `RuntimeMeshComponent/` directory from your plugins directory and remove the component from any `build.cs` files that may reference it. + * **Breaking change**: Switched from [spine-c](spine-c) to [spine-cpp](spine-cpp) as the underlying Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. + * All C structs and enums `spXXX` have been replaced with their C++ equivalents `spine::XXX` in all public interfaces. + * All instantiations via `new` of C++ classes from spine-cpp should contain `(__FILE__, __LINE__)`. This allows the tracking of instantations and detection of memory leaks via the `spine::DebugExtension`. +* Updated to Unreal Engine 4.20 (samples require 4.17+), see the `spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.build.cs` file on how to compile in 4.20 with the latest UBT API changes. +* Updated to Unreal Engine 4.21 (samples require 4.21). +* **Breaking change**: `UBoneDriverComponent` and `UBoneFollowerComponent` are now `USceneComponent` instead of `UActorComponent`. They either update only themselves, or also the owning `UActor`, depending on whether the new flag `UseComponentTransform` is set. See https://github.com/EsotericSoftware/spine-runtimes/pull/1175 +* Added query methods for slots, bones, skins and animations to `SpineSkeletonComponent` and `UTrackEntry`. These allow you to query these objects by name in both C++ and blueprints. +* Added `Preview Animation` and `Preview Skin` properties to `SpineSkeletonAnimationComponent`. Enter an animation or skin name to live-preview it in the editor. Enter an empty string to reset the animation or skin. + +## C# ## +* **Breaking changes** + * The completion event will fire for looped 0 duration animations every frame. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#MixBlend = MixBlend.add` on each track. To specify the blend percentage, set `TrackEntry#Alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Unity +* **Runtime and Editor, and Assembly Definition** Files and folders have been reorganized into "Runtime" and "Editor". Each of these have an `.asmdef` file that defines these separately as their own assembly in Unity *(Note: Spine `.asmdef` files are currently deactivated to `.txt` extension, see below)*. For projects not using assembly definition, you may delete the `.asmdef` files. These assembly definitions will be ignored by older versions of Unity that don't support it. + * In this scheme, the entirety of the base spine-csharp runtime is inside the "Runtime" folder, to be compiled in the same assembly as spine-unity so they can continue to share internal members. +* **Spine `.asmdef` files are now deactivated (using `.txt` extension) by default** This prevents problems when updating Spine through unitypackages, overwriting the Timeline reference entry in `spine-unity.asmdef` (added automatically when enabling Unity 2019 Timeline support, see `Timeline Support for Unity 2019`), causing compile errors. In case you want to enable the `.asmdef` files, rename the files: + `Spine/Runtime/spine-unity.txt` to `Spine/Runtime/spine-unity.asmdef` and + `Spine/Editor/spine-unity-editor.txt` to `Spine/Editor/spine-unity-editor.asmdef`. +* **SkeletonAnimator is now SkeletonMecanim** The Spine-Unity Mecanim-driven component `SkeletonAnimator` has been renamed `SkeletonMecanim` to make it more autocomplete-friendly and more obvious at human-glance. The .meta files and guids should remain intact so existing projects and prefabs should not break. However, user code needs to be updated to use `SkeletonMecanim`. +* **SpineAtlasAsset** The existing `AtlasAsset` type has been renamed to `SpineAtlasAsset` to signify that it specifically uses a Spine/libGDX atlas as its source. Serialization should be intact but user code will need to be updated to refer to existing atlases as `SpineAtlasAsset`. + * **AtlasAssetBase** `SpineAtlasAsset` now has an abstract base class called `SpineAtlasAsset`. This is the base class to derive when using alternate atlas sources. Existing SkeletonDataAsset field "atlasAssets" now have the "AtlasAssetBase" type. Serialization should be intact, but user code will need to be updated to refer to the atlas assets accordingly. + * This change is in preparation for alternate atlas options such as Unity's SpriteAtlas. +* **Optional Straight Alpha for shaders** Spine-Unity's included Unity shaders now have a `_STRAIGHT_ALPHA_INPUT` shader_feature, toggled as a checkbox in the Material's inspector. This allows the Material to use a non-premultiplied alpha/straight alpha input texture. + * The following shaders now have the "Straight Alpha Texture" checkbox when used on a material: + * `Spine/Skeleton` + * `Spine/Skeleton Tint Black` + * `Spine/Skeleton Lit` + * `Spine/Skeleton Tint` + * `Spine/Skeleton Fill` + * `Spine/SkeletonGraphic (Premultiply Alpha)` was renamed to `Spine/SkeletonGraphic` + * `Spine/SkeletonGraphic Tint Black (Premultiply Alpha)` was renamed to `Spine/SkeletonGraphic Tint Black` + * `Spine/Skeleton PMA Multiply` + * `Spine/Skeleton PMA Screen` + * Dedicated straight alpha shaders were removed from the runtime. + * `Spine/Straight Alpha/Skeleton Fill` + * `Spine/Straight Alpha/Skeleton Tint` +* **Detection of Incorrect Texture Settings** Especially when atlas textures are exported with setting `Premultiply alpha` enabled, it is important to configure Unity's texture import settings correctly. By default, you will now receive warnings where texture settings are expected to cause incorrect rendering. + * The following rules apply: + * `sRGB (Color Texture)` shall be disabled when `Generate Mip Maps` is enabled, otherwise you will receive white border outlines. + * `Alpha Is Transparency` shall be disabled on `Premultiply alpha` textures, otherwise you will receive light ghosting artifacts in transparent areas. + * These warnings can be disabled in `Edit - Preferences - Spine`. +* **Sprite Mask Support for all Included Shaders** The `Skeleton Animation` and `Skeleton Mecanim` components now provide an additional `Mask Interaction` field in the Inspector, covering identical functionality as Unity's built in `Sprite Renderer` component: + * `Mask Interaction` modes: + * `None` - The sprite will not interact with the masking system. Default behavior. + * `Visible Inside Mask` - The sprite will be visible only in areas where a mask is present. + * `Visible Outside Mask` - The sprite will be visible only in areas where no mask is present. + * `Automatically Generated Materials` When switching `Mask Interaction` modes in the Inspector outside of Play mode, the required additional material assets are generated for the respective `Stencil Compare` parameters - with file suffixes `'_InsideMask'` and `'_OutsideMask'`, placed in the same folder as the original materials. By default all generated materials are kept as references by the `Skeleton Animation` component for switching at runtime. + These materials can be managed and optimized via the `SkeletonAnimation`'s `Advanced` section: + * Using the `Clear` button you can clear the reference to unneeded materials, + * Using the `Delete` button the respective assets are deleted as well as references cleared. Note that other `Skeleton Animation` GameObjects might still reference the materials, so use with caution! + * With the `Set` button you can again assign a link to the respective materials to prepare them for runtime use. If the materials were not present or have been deleted, they are generated again based on the default materials. + * When switching `Mask Interaction` mode at runtime, the previously prepared materials are switched active automatically. When the respective materials have not been prepared, material copies of the default materials are created on the fly. Note that these materials are not shared between similar `Skeleton Animation` GameObjects, so it is recommended to use the generated material assets where possible. + * **Every shader now exposes the `Stencil Compare` parameter** for further customization. This way you have maximum flexibility to use custom mechanisms to switch materials at runtime if you should ever need more than the three materials generated by `Skeleton Animation`'s `Mask Interaction` parameter. Reference `Stencil Compare` values are: + * `CompareFunction.Disabled` for `Mask Interaction - None` + * `CompareFunction.LessEqual` for `Mask Interaction - Visible Inside Mask` + * `CompareFunction.Greater` for `Mask Interaction - Visible Outside Mask` +* **RectMask2D Support for SkeletonGraphic** Both `SkeletonGraphic` shaders '`Spine/SkeletonGraphic`' and '`Spine/SkeletonGraphic Tint Black`' now respect masking areas defined via Unity's `RectMask2D` component. +* **Timeline Support for Unity 2019** using the existing Timeline components. By default, all Spine Timeline components are deactivated in Unity 2019 and **can be activated via the Spine Preferences menu**. This step became necessary because in Unity 2019, Timeline has been moved to a separate Package and is no longer included in the Unity core. Please visit `Edit - Preferences - Spine` and at `Timeline Package Support` hit `Enable` to automatically perform all necessary steps to activate the Timeline components. +This will automatically: + 1. download the Unity Timeline package + 2. activate the Spine Timeline components by setting the compile definition `SPINE_TIMELINE_PACKAGE_DOWNLOADED` for all platforms + 3. modify the `spine-unity.asmdef` file by adding the reference to the Unity Timeline library. +* Added `Create 2D Hinge Chain` functionality at `SkeletonUtilityBone` inspector, previously only `Create 3D Hinge Chain` was available. + +### XNA/MonoGame +* Added support for any `Effect` to be used by `SkeletonRenderer` +* Added support for `IVertexEffect` to modify vertices of skeletons on the CPU. `IVertexEffect` instances can be set on the `SkeletonRenderer`. See example project. +* Added `SkeletonDebugRenderer` +* Made `MeshBatcher` of SkeletonRenderer accessible via a getter. Allows user to batch their own geometry together with skeleton meshes for maximum batching instead of using XNA SpriteBatcher. + +## Java +* **Breaking changes** + * Skeleton attachments: Moved update of attached skeleton out of libGDX `SkeletonRenderer`, added overloaded method `Skeleton#updateWorldTransform(Bone)`, used for `SkeletonAttachment`. You now MUST call this new method with the bone of the parent skeleton to which the child skeleton is attached. See `SkeletonAttachmentTest` for and example. + * The completion event will fire for looped 0 duration animations every frame. + * `MixPose` is now called `MixBlend`. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added `EventData#audioPath` field. This field contains the file name of the audio file used for the event. + * Added convenience method to add all attachments from one skin to another, see https://github.com/EsotericSoftware/spine-runtimes/commit/a0b7bb6c445efdfac12b0cdee2057afa3eff3ead + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### libGDX +* Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect` and `VertexEffectTest`. +* Added improved tint-black shader. +* Improved performance by avoiding batch flush when not switching between normal and additive rendering with PMA +* Improvements to skeleton viewer. +* `TwoColorPolygonBatch` implements the `Batch` interface, allowing to the be used with other libGDX classes that require a batcher for drawing, potentially improving performance. See https://github.com/EsotericSoftware/spine-runtimes/commit/a46b3d1d0c135d51f9bef9ca17a5f8e5dda69927 +* Added `SkeletonDrawable` to render skeletons in scene2d UI https://github.com/EsotericSoftware/spine-runtimes/commit/b93686c185e2c9d5466969a8e07eee573ebe4b97 + +## Lua +* **Breaking changes** + * The completion event will fire for looped 0 duration animations every frame. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added `JitterEffect` and `SwirlEffect` and support for vertex effects in Corona and Love + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry:setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry.alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Love2D +* Added support for vertex effects. Set an implementation like "JitterEffect" on `Skeleton.vertexEffect`. See `main.lua` for an example. + +### Corona +* Added support for vertex effects. Set an implementation like "JitterEffect" on `SkeletonRenderer.vertexEffect`. See `main.lua` for an example + +## Typescript/Javascript +* **Breaking changes** + * The completion event will fire for looped 0 duration animations every frame. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added `AssetManager.loadTextureAtlas`. Instead of loading the `.atlas` and corresponding image files manually, you can simply specify the location of the `.atlas` file and AssetManager will load the atlas and all its images automatically. `AssetManager.get("atlasname.atlas")` will then return an instance of `spine.TextureAtlas`. + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. See https://github.com/EsotericSoftware/spine-runtimes/blob/f045d221836fa56191ccda73dd42ae884d4731b8/spine-ts/webgl/tests/test-additive-animation-blending.html for an example. + * Added work-around for iOS WebKit JIT bug, see https://github.com/EsotericSoftware/spine-runtimes/commit/c28bbebf804980f55cdd773fed9ff145e0e7e76c + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + * Added `AssetManager#setRawDataURI(path, data)`. Allows to set raw data URIs for a specific path, which in turn enables embedding assets into JavaScript/HTML. + +### WebGL backend +* Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`, and the example which allows to set effects. +* Added `slotRangeStart` and `slotRangeEnd` parameters to `SkeletonRenderer#draw` and `SceneRenderer#drawSkeleton`. This allows you to render only a range of slots in the draw order. See `spine-ts/webgl/tests/test-slot-range.html` for an example. +* Added improved tint-black shader. +* Added `SceneRenderer#drawTextureUV()`, allowing to draw a texture with manually specified texture coordinates. +* Exposed all renderers in `SceneRenderer`. + +### Canvas backend +* Added support for shearing and non-uniform scaling inherited from parent bones. +* Added support for alpha tinting. + +### Three.js backend +* Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`. +* Added support for multi-page atlases + +### Widget backend + * Added fields `atlasContent`, `atlasPagesContent`, and `jsonContent` to `WidgetConfiguration` allowing you to directly pass the contents of the `.atlas`, atlas page `.png` files, and the `.json` file without having to do a request. See `README.md` and the example for details. + * `SpineWidget.setAnimation()` now takes an additional optional parameter for callbacks when animations are completed/interrupted/etc. + +# 3.6 + +## AS3 +* **Breaking changes** + * Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Made `Bone` fields `_a`, `_b`, `_c`, `_d`, `_worldX` and `_worldY` public, removed underscore prefix. + * Removed `VertexAttachment.computeWorldVertices` overload, changed `VertexAttachment.computeWorldVertices2` to `VertexAttachment.computeWorldVertices`, added `stride` parameter. + * Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + * Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + * Replaced `r`, `g`, `b`, `a` fields with instances of new `Color` class in `RegionAttachment`, `MeshAttachment`, `Skeleton`, `SkeletonData`, `Slot` and `SlotData`. + * The completion event will fire for looped 0 duration animations every frame. + +* **Additions** + * Added `Skeleton.getBounds` from reference implementation. + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `VertexEffect` and implementations `JitterEffect` and `SwirlEffect`. Allows you to modify vertices before they are submitted for drawing. See Starling changes. + +### Starling + * Fixed renderer to work with 3.6 changes. + * Added support for two color tinting. + * Added support for clipping. + * Added support for rotated regions in texture atlas loaded via StarlingAtlasAttachmentLoader. + * Added support for vertex effects. See `RaptorExample.as` + * Added 'getTexture()' method to 'StarlingTextureAtlasAttachmentLoader' + * Breaking change: if a skeleton requires two color tinting, you have to enable it via `SkeletonSprite.twoColorTint = true`. In this case the skeleton will use the `TwoColorMeshStyle`, which internally uses a different vertex layout and shader. This means that skeletons with two color tinting enabled will break batching and hence increase the number of draw calls in your app. + +## C +* **Breaking changes** + * `spVertexAttachment_computeWorldVertices` and `spRegionAttachment_computeWorldVerticeS` now take new parameters to make it possible to directly output the calculated vertex positions to a vertex buffer. Removes the need for additional copies in the backends' respective renderers. + * Removed `spBoundingBoxAttachment_computeWorldVertices`, superseded by `spVertexAttachment_computeWorldVertices`. + * Removed `spPathAttachment_computeWorldVertices` and `spPathAttachment_computeWorldVertices1`, superseded by `spVertexAttachment_computeWorldVertices`. + * Removed `sp_MeshAttachment_computeWorldVertices`, superseded by `spVertexAttachment_computeWorldVertices`. + * Removed `spBone_worldToLocalRotationX` and `spBone_worldToLocalRotationY`. Replaced by `spBone_worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Replaced `r`, `g`, `b`, `a` fields with instances of new `spColor` struct in `spRegionAttachment`, `spMeshAttachment`, `spSkeleton`, `spSkeletonData`, `spSlot` and `spSlotData`. + * Removed `spVertexIndex`from public API. + * Listeners on `spAnimationState` or `spTrackEntry` will now be also called in case a track entry is disposed as part of dispoing the `spAnimationState`. + * The completion event will fire for looped 0 duration animations every frame. +* **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `spTransformConstraintData`. + * Added `spPointAttachment`, additional method `spAtlasAttachmentLoadeR_newPointAttachment`. + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `spBone_localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `spTwoColorTimeline` and additional fields on `spSlot` and `spSlotData`. + * Added `userData` field to `spTrackEntry`, so users can expose data in `spAnimationState` callbacks. + * Modified kvec.h used by SkeletonBinary.c to use Spine's MALLOC/FREE macros. That way there's only one place to inject custom allocators ([extension.h](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-c/spine-c/include/spine/extension.h)) [commit](https://github.com/EsotericSoftware/spine-runtimes/commit/c2cfbc6cb8709daa082726222d558188d75a004f) + * Added macros to define typed dynamic arrays, see `Array.h/.c` + * Added `spClippingAttachment` and respective enum. + * Added `spSkeletonClipper` and `spTriangulator`, used to implement software clipping of attachments. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `spVertexEffect` and corresponding implementations `spJitterVertexEffect` and `spSwirlVertexEffect`. Create/dispose through the corresponding `spXXXVertexEffect_create()/dispose()` functions. Set on framework/engine specific renderer. See changes for spine-c based frameworks/engines below. + * Functions in `extension.h` are not prefixed with `_sp` instead of just `_` to avoid interference with other libraries. + * Introduced `SP_API` macro. Every spine-c function is prefixed with this macro. By default, it is an empty string. Can be used to markup spine-c functions with e.g. ``__declspec` when compiling to a dll or linking to that dll. + +### Cocos2d-X + * Fixed renderer to work with 3.6 changes + * Optimized rendering by removing all per-frame allocation in `SkeletonRenderer`, resulting in 15% performance increase for large numbers of skeletons being rendered per frame. + * Added support for two color tinting. Tinting is enabled/disabled per `SkeletonRenderer`/`SkeletonAnimation` instance. Use `SkeletonRenderer::setTwoColorTint()`. Note that two color tinting requires the use of a non-standard shader and vertex format. This means that skeletons rendered with two color tinting will break batching. However, skeletons with two color tinting enabled and rendered after each other will be batched. + * Updated example to use Cocos2d-x 3.14.1. + * Added mesh debug rendering. Enable/Disable via `SkeletonRenderer::setDebugMeshesEnabled()`. + * Added support for clipping. + * SkeletonRenderer now combines the displayed color of the Node (cascaded from all parents) with the skeleton color for tinting. + * Added support for vertex effects. See `RaptorExample.cpp`. + * Added ETC1 alpha support, thanks @halx99! Does not work when two color tint is enabled. + * Added `spAtlasPage_setCustomTextureLoader()` which let's you do texture loading manually. Thanks @jareguo. + * Added `SkeletonRenderer:setSlotsRange()` and `SkeletonRenderer::createWithSkeleton()`. This allows you to split rendering of a skeleton up into multiple parts, and render other nodes in between. See `SkeletonRendererSeparatorExample.cpp` for an example. + +### Cocos2d-Objc + * Fixed renderer to work with 3.6 changes + * Added support for two color tinting. Tinting is enabled/disabled per `SkeletonRenderer/SkeletonAnimation.twoColorTint = true`. Note that two color tinted skeletons do not batch with other nodes. + * Added support for clipping. + +### SFML + * Fixed renderer to work with 3.6 changes. Sadly, two color tinting does not work, as the vertex format in SFML is fixed. + * Added support for clipping. + * Added support for vertex effects. See raptor example. + * Added premultiplied alpha support to `SkeletonDrawable`. + +### Unreal Engine 4 + * Fixed renderer to work with 3.6 changes + * Added new UPROPERTY to SpineSkeletonRendererComponent called `Color`. This allows to set the tint color of the skeleton in the editor, C++ and Blueprints. Under the hood, the `spSkeleton->color` will be set on every tick of the renderer component. + * Added support for clipping. + * Switched from built-in ProceduralMeshComponent to RuntimeMeshComponent by Koderz (https://github.com/Koderz/UE4RuntimeMeshComponent, MIT). Needed for more flexibility regarding vertex format, should not have an impact on existing code/assets. You need to copy the RuntimeMeshComponentPlugin from our repository in `spine-ue4\Plugins\` to your project as well! + * Added support for two color tinting. All base materials, e.g. SpineUnlitNormalMaterial, now do proper two color tinting. No material parameters have changed. + * Updated to Unreal Engine 4.16.1. Note that 4.16 has a regression which will make it impossible to compile plain .c files! + * spine-c is now exposed from the plugin shared library on Windows via __declspec. + +## C# +* **Breaking changes** + * `MeshAttachment.parentMesh` is now a private field to enforce using the `.ParentMesh` setter property in external code. The `MeshAttachment.ParentMesh` property is an appropriate replacement wherever `.parentMesh` was used. + * `Skeleton.GetBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + * Removed `Bone.WorldToLocalRotationX` and `Bone.WorldToLocalRotationY`. Replaced by `Bone.WorldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Added `stride` parameter to `VertexAttachment.ComputeWorldVertices`. + * Removed `RegionAttachment.Vertices` field. The vertices array is provided to `RegionAttachment.ComputeWorldVertices` by the API user now. + * Removed `RegionAttachment.UpdateWorldVertices`, added `RegionAttachment.ComputeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + * The completion event will fire for looped 0 duration animations every frame. + + * **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `NewPointAttachment` in `AttachmentLoader` interface. + * Added `ClippingAttachment`, additional method `NewClippingAttachment` in `AttachmentLoader` interface. + * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + * `AnimationState.Apply` returns a bool indicating if any timeline was applied or not. + * `Animation.Apply` and `Timeline.Apply`` now take enums `MixPose` and `MixDirection` instead of bools. + +### Unity + * Refactored renderer to work with new 3.6 features. + * **Two color tinting** is currently supported via extra UV2 and UV3 mesh vertex streams. To use Two color tinting, you need to: + * switch on "Tint Black" under "Advanced...", + * use the new `Spine/Skeleton Tint Black` shader, or your own shader that treats the UV2 and UV3 streams similarly. + * Additionally, for SkeletonGraphic, you can use `Spine/SkeletonGraphic Tint Black` (or the bundled SkeletonGraphicTintBlack material) or your own shader that uses UV2 and UV3 streams similarly. **Additional Shader Channels** TexCoord1 and TexCoord2 will need to be enabled from the Canvas component's inspector. These correspond to UV2 and UV3. + * **Clipping** is now supported. Caution: The SkeletonAnimation switches to slightly slower mesh generation code when clipping so limit your use of `ClippingAttachment`s when using on large numbers of skeletons. + * **SkeletonRenderer.initialFlip** Spine components such as SkeletonRenderer, SkeletonAnimation, SkeletonAnimator now has `initialFlipX` and `initialFlipY` fields which are also visible in the inspector under "Advanced...". It will allow you to set and preview a starting flip value for your skeleton component. This is applied immediately when the internal skeleton object is instantiated. + * **[SpineAttribute] Improvements** + * **Icons have been added to SpineAttributeDrawers**. This should make your default inspectors easier to understand at a glance. + * **Added Constraint Attributes** You can now use `[SpineIkConstraint]` `[SpineTransformConstraint]` `[SpinePathConstraint]` + * **SpineAttribute dataField** parameter can also now detect sibling fields within arrays and serializable structs/classes. + * **[SpineAttribute(includeNone:false)]** SpineAttributes now have an `includeNone` optional parameter to specify if you want to include or exclude a none ("") value option in the dropdown menu. Default is `includeNone:true`. + * **[SpineAttachment(skinField:"mySkin")]** The SpineAttachment attribute now has a skinField optional parameter to limit the dropdown items to attachments in a specific skin instead of the just default skin or all the skins in SkeletonData. + * **SkeletonDebugWindow**. Debugging tools have been moved from the SkeletonAnimation and SkeletonUtility component inspectors into its own utility window. You can access "Skeleton Debug" under the `Advanced...` foldout in the SkeletonAnimation inspector, or in SkeletonAnimation's right-click/context menu. + * **Skeleton Baking Window** The old Skeleton Baking feature is also now accessible through the SkeletonDataAsset's right-click/context menu. + * **AttachmentTools source material**. `AttachmentTools` methods can now accept a `sourceMaterial` argument to copy material properties from. + * **AttachmentTools Skin Extensions**. Using AttachmentTools, you can now add entries by slot name by also providing a skeleton argument. Also `Append(Skin)`, `RemoveAttachment` and `Clear` have been added. + * **BoneFollower and SkeletonUtilityBone Add RigidBody Button**. The BoneFollower and SkeletonUtilityBone component inspectors will now offer to add a `Rigidbody` or `Rigidbody2D` if it detects a collider of the appropriate type. Having a rigidbody on a moving transform with a collider fits better with the Unity physics systems and prevents excess calculations. It will not detect colliders on child objects so you have to add Rigidbody components manually accordingly. + * **SkeletonRenderer.OnPostProcessVertices** is a new callback that gives you a reference to the MeshGenerator after it has generated a mesh from the current skeleton pose. You can access `meshGenerator.VertexBuffer` or `meshGenerator.ColorBuffer` to modify these before they get pushed into the UnityEngine.Mesh for rendering. This can be useful for non-shader vertex effects. + * **Examples** + * **Examples now use properties**. The code in the example scripts have been switched over to using properties instead of fields to encourage their use for consistency. This is in anticipation of both users who want to move the Spine folders to the Unity Plugins folder (compiled as a different assembly), and of Unity 2017's ability to manually define different assemblies for shorter compilation times. + * **Mix And Match**. The mix-and-match example scene, code and data have been updated to reflect the current recommended setup for animation-compatible custom equip systems The underlying API has changed since 3.5 and the new API calls in MixAndMatch.cs is recommended. Documentation is in progress. + * **Sample Components**. `AtasRegionAttacher` and `SpriteAttacher` are now part of `Sample Components`, to reflect that they are meant to be used as sample code rather than production. A few other sample components have also been added. New imports of the unitypackage Examples folder will see a "Legacy" folder comprised of old sample components that no longer contain the most up-to-date and recommended workflows, but are kept in case old setups used them for production. + * **Spine folder**. In the unitypackage, the "spine-csharp" and "spine-unity" folders are now inside a "Spine" folder. This change will only affect fresh imports. Importing the unitypackage to update Spine-Unity in your existing project will update the appropriate files however you chose to arrange them, as long as the meta files are intact. + * **Breaking changes** + * The Sprite shaders module was updated to the latest version from the [source](https://github.com/traggett/UnitySpriteShaders/commits/master). Some changes were made to the underlying keyword structure. You may need to review the settings of your lit materials. Particularly, your Fixed Normals settings. + * The `Spine/Skeleton Lit` shader was switched over to non-fixed-function code. It now no longer requires mesh normals and has fixed normals at the shader level. + * The old MeshGenerator classes, interfaces and code in `Spine.Unity.MeshGeneration` are now deprecated. All mesh-generating components now share the class `Spine.Unity.MeshGenerator` defined in `SpineMesh.cs`. MeshGenerator is a serializable class. + * The `SkeletonRenderer.renderMeshes` optimization is currently non-functional. + * Old triangle-winding code has been removed from `SkeletonRenderer`. Please use shaders that have backface culling off. + * Render settings in `SkeletonGraphic` can now be accessed under `SkeletonGraphic.MeshGenerator.settings`. This is visible in the SkeletonGraphic inspector as `Advanced...` + * We will continue to bundle the unitypackage with the empty .cs files of deprecated classes until Spine 3.7 to ensure the upgrade process does not break. + * The [SpineAttachment(slotField:)] optional parameter found property value now acts as a Find(slotName) argument rather than Contains(slotName). + * `SkeletonAnimator` now uses a `SkeletonAnimator.MecanimTranslator` class to translate an Animator's Mecanim State Machine into skeleton poses. This makes code reuse possible for a Mecanim version of SkeletonGraphic. + * `SkeletonAnimator` `autoreset` and the `mixModes` array are now a part of SkeletonAnimator's MecanimTranslator `.Translator`. `autoReset` is set to true by default. Old prefabs and scene objects with Skeleton Animator may no longer have correct values set. + * Warnings and conditionals checking for specific Unity 5.2-and-below incompatibility have been removed. + +## XNA/MonoGame + * Added support for clipping + * Removed `RegionBatcher` and `SkeletonRegionRenderer`, renamed `SkeletonMeshRenderer` to `SkeletonRenderer` + * Added support for two color tint. For it to work, you need to add the `SpineEffect.fx` file to your content project, then load it via `var effect = Content.Load("SpineEffect");`, and set it on the `SkeletonRenderer`. See the example project for code. + * Added support for any `Effect` to be used by `SkeletonRenderer` + * Added support for `IVertexEffect` to modify vertices of skeletons on the CPU. `IVertexEffect` instances can be set on the `SkeletonRenderer`. See example project. + * Added `SkeletonDebugRenderer` + * Made `MeshBatcher` of SkeletonRenderer accessible via a getter. Allows user to batch their own geometry together with skeleton meshes for maximum batching instead of using XNA SpriteBatcher. + +## Java +* **Breaking changes** + * `Skeleton.getBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + * Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Added `stride` parameter to `VertexAttachment.computeWorldVertices`. + * Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + * Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + * Skeleton attachments: Moved update of attached skeleton out of libGDX `SkeletonRenderer`, added overloaded method `Skeleton#updateWorldTransform(Bone), used for `SkeletonAttachment`. You now MUST call this new method + with the bone of the parent skeleton to which the child skeleton is attached. See `SkeletonAttachmentTest` for and example. + * The completion event will fire for looped 0 duration animations every frame. + +* **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + +### libGDX + * Fixed renderer to work with 3.6 changes + * Added support for two color tinting. Use the new `TwoColorPolygonBatch` together with `SkeletonRenderer` + * Added support for clipping. See `SkeletonClipper`. Used automatically by `SkeletonRenderer`. Does not work when using a `SpriteBatch` with `SkeletonRenderer`. Use `PolygonSpriteBatch` or `TwoColorPolygonBatch` instead. + * Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect` and `VertexEffectTest`. + +## Lua +* **Breaking changes** + * Removed `Bone:worldToLocalRotationX` and `Bone:worldToLocalRotationY`. Replaced by `Bone:worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * `VertexAttachment:computeWorldVertices` now takes offsets and stride to allow compositing vertices directly in a vertex buffer to be send to the GPU. The compositing is now performed in the backends' respective renderers. This also affects the subclasses `MeshAttachment`, `BoundingBoxAttachment` and `PathAttachment`. + * Removed `RegionAttachment:updateWorldVertices`, added `RegionAttachment:computeWorldVertices`, which takes offsets and stride to allow compositing vertices directly in a vertex buffer to be send to the GPU. The compositing is now performed in the backends' respective renderers. + * Removed `MeshAttachment.worldVertices` field. Computation is now performed in each backends' respective renderer. The `uv` coordinates are now stored in `MeshAttachment.uvs`. + * Removed `RegionAttachment.vertices` field. Computation is now performed in each backends respective renderer. The `uv` coordinates for each vertex are now stored in the `RegionAttachment.uvs` field. + * The completion event will fire for looped 0 duration animations every frame. + * **Additions** + * Added `Bone:localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `JitterEffect` and `SwirlEffect` and support for vertex effects in Corona and Love + +### Love2D + * Fixed renderer to work with 3.6 changes + * Added support for two color tinting. Enable it via `SkeletonRenderer.new(true)`. + * Added clipping support. + * Added support for vertex effects. Set an implementation like "JitterEffect" on `Skeleton.vertexEffect`. See `main.lua` for an example. + +### Corona + * Fixed renderer to work with 3.6 changes. Sadly, two color tinting is not supported, as Corona doesn't let us change the vertex format needed and its doesn't allow to modify shaders in the way needed for two color tinting + * Added clipping support. + * Added support for vertex effects. Set an implementation like "JitterEffect" on `SkeletonRenderer.vertexEffect`. See `main.lua` for an example + +## Typescript/Javascript +* **Breaking changes** + * `Skeleton.getBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + * Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Removed `VertexAttachment.computeWorldVertices` overload, changed `VertexAttachment.computeWorldVerticesWith` to `VertexAttachment.computeWorldVertices`, added `stride` parameter. + * Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + * Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + * The completion event will fire for looped 0 duration animations every frame. + * Removed the Spine Widget in favor of [Spine Web Player](https://esotericsoftware.com/spine-player). + +* **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `AssetManager.loadTextureAtlas`. Instead of loading the `.atlas` and corresponding image files manually, you can simply specify the location of the `.atlas` file and AssetManager will load the atlas and all its images automatically. `AssetManager.get("atlasname.atlas")` will then return an instance of `spine.TextureAtlas`. + * Added the [Spine Web Player](https://esotericsoftware.com/spine-player) + + +### WebGL backend + * Fixed WebGL context loss + * Added `Restorable` interface, implemented by any WebGL resource that needs restoration after a context loss. All WebGL resource classes (`Shader`, `Mesh`, `GLTexture`) implement this interface. + * Added `ManagedWebGLRenderingContext`. Handles setup of a `WebGLRenderingContext` given a canvas element and restoration of WebGL resources (`Shader`, `Mesh`, `GLTexture`) on WebGL context loss. WebGL resources register themselves with the `ManagedWebGLRenderingContext`. If the context is informed of a context loss and restoration, the registered WebGL resources' `restore()` method is called. The `restore()` method implementation on each resource type will recreate the GPU side objects. + * All classes that previously took a `WebGLRenderingContext` in the constructor now also allow a `ManagedWebGLRenderingContext`. This ensures existing applications do not break. + * To use automatic context restauration: + 1. Create or fetch a canvas element from the DOM + 2. Instantiate a `ManagedWebGLRenderingContext`, passing the canvas to the constructor. This will setup a `WebGLRenderingContext` internally and manage context loss/restoration. + 3. Pass the `ManagedWebGLRenderingContext` to the constructors of classes that you previously passed a `WebGLRenderingContext` to (`AssetManager`, `GLTexture`, `Mesh`, `Shader`, `PolygonBatcher`, `SceneRenderer`, `ShapeRenderer`, `SkeletonRenderer`, `SkeletonDebugRenderer`). + * Fixed renderer to work with 3.6 changes. + * Added support for two color tinting. + * Improved performance by using `DYNAMIC_DRAW` for vertex buffer objects and fixing bug that copied to much data to the GPU each frame in `PolygonBatcher`/`Mesh`. + * Added two color tinting support, enabled by default. You can disable it via the constructors of `SceneRenderer`, `SkeletonRenderer`and `PolygonBatcher`. Note that you will need to use a shader created via `Shader.newTwoColoredTexturedShader` shader with `SkeletonRenderer` and `PolygonBatcher` if two color tinting is enabled. + * Added clipping support + * Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`, and the example which allows to set effects. + * Added `slotRangeStart` and `slotRangeEnd` parameters to `SkeletonRenderer#draw` and `SceneRenderer#drawSkeleton`. This allows you to render only a range of slots in the draw order. See `spine-ts/webgl/tests/test-slot-range.html` for an example. + +### Canvas backend + * Fixed renderer to work for 3.6 changes. Sadly, we can't support two color tinting via the Canvas API. + * Added support for shearing and non-uniform scaling inherited from parent bones. + * Added support for alpha tinting. + +### Three.js backend + * Fixed renderer to work with 3.6 changes. Two color tinting is not supported. + * Added clipping support + * Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`. + * Added support for multi-page atlases + +### Widget backend + * Fixed WebGL context loss (see WebGL backend changes). Enabled automatically. + * Fixed renderer to work for 3.6 changes. Supports two color tinting & clipping (see WebGL backend changes for details). + * Added fields `atlasContent`, `atlasPagesContent`, and `jsonContent` to `WidgetConfiguration` allowing you to directly pass the contents of the `.atlas`, atlas page `.png` files, and the `.json` file without having to do a request. See `README.md` and the example for details. + * `SpineWidget.setAnimation()` now takes an additional optional parameter for callbacks when animations are completed/interrupted/etc. diff --git a/DateToSpine/third_party/spine-runtimes/3.8/CMakeLists.txt b/DateToSpine/third_party/spine-runtimes/3.8/CMakeLists.txt new file mode 100644 index 0000000..17d8657 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 2.8.9) +project(spine) + +if(MSVC) + message("MSCV detected") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + set (CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}") +else() + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wunused-value -Wno-c++11-long-long -Wno-variadic-macros -Werror -Wextra -pedantic -Wnonportable-include-path -Wshadow -std=c89") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunused-value -Wno-c++11-long-long -Wno-variadic-macros -Werror -Wextra -Wnon-virtual-dtor -pedantic -Wnonportable-include-path -Wshadow -std=c++03 -fno-exceptions -fno-rtti") +endif() + +set(CMAKE_INSTALL_PREFIX "./") +set(CMAKE_VERBOSE_MAKEFILE ON) +set(SPINE_SFML FALSE CACHE BOOL FALSE) +set(SPINE_COCOS2D_OBJC FALSE CACHE BOOL FALSE) +set(SPINE_COCOS2D_X FALSE CACHE BOOL FALSE) + +if((${SPINE_SFML}) OR (${CMAKE_CURRENT_BINARY_DIR} MATCHES "spine-sfml")) + add_subdirectory(spine-c) + add_subdirectory(spine-sfml/c) + add_subdirectory(spine-cpp) + add_subdirectory(spine-sfml/cpp) +endif() + +if((${SPINE_COCOS2D_OBJC}) OR (${CMAKE_CURRENT_BINARY_DIR} MATCHES "spine-cocos2d-objc")) + if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + add_subdirectory(spine-cocos2d-objc) + endif() +endif() + +if((${SPINE_COCOS2D_X}) OR (${CMAKE_CURRENT_BINARY_DIR} MATCHES "spine-cocos2dx")) + add_subdirectory(spine-cocos2dx) +endif() + +add_subdirectory(spine-c/spine-c-unit-tests) +add_subdirectory(spine-cpp/spine-cpp-unit-tests) \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/3.8/LICENSE b/DateToSpine/third_party/spine-runtimes/3.8/LICENSE new file mode 100644 index 0000000..4501a61 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/LICENSE @@ -0,0 +1,26 @@ +Spine Runtimes License Agreement +Last updated May 1, 2019. Replaces all prior versions. + +Copyright (c) 2013-2019, Esoteric Software LLC + +Integration of the Spine Runtimes into software or otherwise creating +derivative works of the Spine Runtimes is permitted under the terms and +conditions of Section 2 of the Spine Editor License Agreement: +http://esotericsoftware.com/spine-editor-license + +Otherwise, it is permitted to integrate the Spine Runtimes into software +or otherwise create derivative works of the Spine Runtimes (collectively, +"Products"), provided that each user of the Products must obtain their own +Spine Editor license and redistribution of the Products in any form must +include this license and copyright notice. + +THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS +INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/3.8/README.md b/DateToSpine/third_party/spine-runtimes/3.8/README.md new file mode 100644 index 0000000..3245185 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/README.md @@ -0,0 +1,33 @@ +# Spine Runtimes + +This GitHub project hosts the Spine Runtimes which are needed to use [Spine](http://esotericsoftware.com/) 2D skeletal animation data with various game toolkits. + +## Licensing + +You are welcome to evaluate the Spine Runtimes and the examples we provide in this repository free of charge. + +You can integrate the Spine Runtimes into your software free of charge, but users of your software must have their own [Spine license](https://esotericsoftware.com/spine-purchase). Please make your users aware of this requirement! This option is often chosen by those making development tools, such as an SDK, game toolkit, or software library. + +In order to distribute your software containing the Spine Runtimes to others that don't have a Spine license, you need a [Spine license](https://esotericsoftware.com/spine-purchase) at the time of integration. Then you can distribute your software containing the Spine Runtimes however you like, provided others don't modify it or use it to create new software. If others want to do that, they'll need their own Spine license. + +For the official legal terms governing the Spine Runtimes, please read the [Spine Runtimes License Agreement](http://esotericsoftware.com/spine-runtimes-license) and Section 2 of the [Spine Editor License Agreement](http://esotericsoftware.com/spine-editor-license#s2). + +## Documentation + +See the [Spine Runtimes Guide](http://esotericsoftware.com/spine-runtimes-guide) for detailed information about using the Spine Runtimes. The Spine [documentation page](http://esotericsoftware.com/spine-documentation#runtimesTitle) provides further information about tools and data formats. For runtime specific documentation, refer to the `README.md` file in each runtime directory. + +## Bugs, enhancements, and tasks + +Review our backlog of bugs, enhancements, and tasks in the [spine-runtimes](https://github.com/EsotericSoftware/spine-runtimes/issues) and [spine-editor](https://github.com/EsotericSoftware/spine-editor/issues) issue trackers. Our [roadmap](http://esotericsoftware.com/spine-roadmap) provides a more convenient view of the same issue tracker information. + +## Versioning + +The default branch on GitHub is stable and works with data exported from the latest, non-beta version of the Spine editor. New development is done in an `X.X-beta` branch, which may be a work in progress. Important changes to the runtimes can be reviewed in the [CHANGELOG.md file](CHANGELOG.md). Occasionally the Spine Runtimes are [tagged](https://github.com/EsotericSoftware/spine-runtimes/releases) with the specific Spine editor version they work with. + +It is highly suggested to [freeze](http://esotericsoftware.com/spine-settings#Version) the Spine editor version to match the Spine Runtimes source being used and to update them in lock step. See the [Spine Runtimes Guide](http://esotericsoftware.com/spine-runtime-architecture#Versioning) for more information. + +## Contributing + +In order to merge your contributions, we need a signed [contributor license agreement (CLA)](http://esotericsoftware.com/licenses/cla.txt) from you. You can send a copy of the CLA to contact@esotericsoftware.com. + +When possible, it is best to base your contributions on the current beta branch (`X.X-beta`). Please be sure to follow the style and formatting you find in the respective runtime code to which you are contributing. diff --git a/DateToSpine/third_party/spine-runtimes/3.8/examples/readme.txt b/DateToSpine/third_party/spine-runtimes/3.8/examples/readme.txt new file mode 100644 index 0000000..8b54b06 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/examples/readme.txt @@ -0,0 +1,21 @@ +These example projects show off many of Spine's features. Below are a number +of other example resources that may prove useful. + +See our online demos, which render Spine animations right in your browser: +http://esotericsoftware.com/spine-demos/ + +Many companies around the world are doing great things with Spine: +http://esotericsoftware.com/spine-showcase + +Tag your tweets using #madewithspine to show up on our Twitter page: +http://esotericsoftware.com/madewithspine + +Learn how to use Spine with the Spine User Guide: +http://esotericsoftware.com/spine-user-guide +And the accompanying Spine User Guide videos: +https://www.youtube.com/playlist?list=PLwGl7Ikd_6GRFo7d0uRu_fN2RIlvkxW7b +And our other videos: +https://www.youtube.com/user/EsotericSoftware/videos + +Super Spineboy is a full example game using Spine and libgdx: +https://github.com/EsotericSoftware/spine-superspineboy diff --git a/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-ess.json b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-ess.json new file mode 100644 index 0000000..3bbb7cb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-ess.json @@ -0,0 +1,1557 @@ +{ +"skeleton": { + "hash": "MOhkPvw8nLOrjuLm/U98aFMannI", + "spine": "3.8.55", + "x": -221.27, + "y": -8.57, + "width": 470.72, + "height": 731.57, + "images": "./images/", + "audio": "" +}, +"bones": [ + { "name": "root" }, + { "name": "hip", "parent": "root", "y": 247.47 }, + { + "name": "torso", + "parent": "hip", + "length": 127.56, + "rotation": 103.82, + "x": -1.62, + "y": 4.9, + "color": "e0da19ff" + }, + { + "name": "front-upper-arm", + "parent": "torso", + "length": 69.45, + "rotation": 168.38, + "x": 103.76, + "y": 19.33, + "color": "00ff04ff" + }, + { + "name": "front-bracer", + "parent": "front-upper-arm", + "length": 40.57, + "rotation": 18.3, + "x": 68.8, + "y": -0.68, + "color": "00ff04ff" + }, + { + "name": "front-fist", + "parent": "front-bracer", + "length": 65.39, + "rotation": 12.43, + "x": 40.57, + "y": 0.2, + "color": "00ff04ff" + }, + { + "name": "front-thigh", + "parent": "hip", + "length": 74.81, + "rotation": -95.51, + "x": -17.46, + "y": -11.64, + "color": "00ff04ff" + }, + { + "name": "front-shin", + "parent": "front-thigh", + "length": 128.77, + "rotation": -2.21, + "x": 78.69, + "y": 1.6, + "color": "00ff04ff" + }, + { + "name": "front-foot", + "parent": "front-shin", + "length": 91.34, + "rotation": 77.91, + "x": 128.76, + "y": -0.34, + "color": "00ff04ff" + }, + { + "name": "rear-upper-arm", + "parent": "torso", + "length": 51.94, + "rotation": -169.56, + "x": 92.36, + "y": -19.22, + "color": "ff000dff" + }, + { "name": "rear-bracer", "parent": "rear-upper-arm", "length": 34.56, "rotation": 23.15, "x": 51.36, "color": "ff000dff" }, + { + "name": "gun", + "parent": "rear-bracer", + "length": 43.11, + "rotation": 5.35, + "x": 34.42, + "y": -0.45, + "color": "ff000dff" + }, + { "name": "gun-tip", "parent": "gun", "rotation": 6.83, "x": 201.05, "y": 52.14, "color": "ff000dff" }, + { + "name": "neck", + "parent": "torso", + "length": 25.45, + "rotation": -31.54, + "x": 127.5, + "y": -0.31, + "color": "e0da19ff" + }, + { + "name": "head", + "parent": "neck", + "length": 263.58, + "rotation": 23.18, + "x": 27.66, + "y": -0.26, + "color": "e0da19ff" + }, + { + "name": "rear-thigh", + "parent": "hip", + "length": 85.72, + "rotation": -72.54, + "x": 8.91, + "y": -5.63, + "color": "ff000dff" + }, + { + "name": "rear-shin", + "parent": "rear-thigh", + "length": 121.88, + "rotation": -19.83, + "x": 86.1, + "y": -1.33, + "color": "ff000dff" + }, + { + "name": "rear-foot", + "parent": "rear-shin", + "length": 82.57, + "rotation": 69.3, + "x": 121.46, + "y": -0.76, + "color": "ff000dff" + } +], +"slots": [ + { "name": "rear-upper-arm", "bone": "rear-upper-arm", "attachment": "rear-upper-arm" }, + { "name": "rear-bracer", "bone": "rear-bracer", "attachment": "rear-bracer" }, + { "name": "gun", "bone": "gun", "attachment": "gun" }, + { "name": "rear-foot", "bone": "rear-foot", "attachment": "rear-foot" }, + { "name": "rear-thigh", "bone": "rear-thigh", "attachment": "rear-thigh" }, + { "name": "rear-shin", "bone": "rear-shin", "attachment": "rear-shin" }, + { "name": "neck", "bone": "neck", "attachment": "neck" }, + { "name": "torso", "bone": "torso", "attachment": "torso" }, + { "name": "front-upper-arm", "bone": "front-upper-arm", "attachment": "front-upper-arm" }, + { "name": "head", "bone": "head", "attachment": "head" }, + { "name": "eye", "bone": "head", "attachment": "eye-indifferent" }, + { "name": "front-thigh", "bone": "front-thigh", "attachment": "front-thigh" }, + { "name": "front-foot", "bone": "front-foot", "attachment": "front-foot" }, + { "name": "front-shin", "bone": "front-shin", "attachment": "front-shin" }, + { "name": "mouth", "bone": "head", "attachment": "mouth-smile" }, + { "name": "goggles", "bone": "head", "attachment": "goggles" }, + { "name": "front-bracer", "bone": "front-bracer", "attachment": "front-bracer" }, + { "name": "front-fist", "bone": "front-fist", "attachment": "front-fist-closed" }, + { "name": "muzzle", "bone": "gun-tip", "blend": "additive" }, + { "name": "head-bb", "bone": "head" } +], +"skins": [ + { + "name": "default", + "attachments": { + "gun": { + "gun": { "x": 77.3, "y": 16.4, "rotation": 60.83, "width": 210, "height": 203 } + }, + "rear-shin": { + "rear-shin": { "x": 58.29, "y": -2.75, "rotation": 92.37, "width": 75, "height": 178 } + }, + "head-bb": { + "head": { + "type": "boundingbox", + "vertexCount": 6, + "vertices": [ -19.14, -70.3, 40.8, -118.07, 257.77, -115.62, 285.16, 57.18, 120.77, 164.95, -5.07, 76.95 ] + } + }, + "mouth": { + "mouth-grind": { "x": 23.69, "y": -32.24, "rotation": -70.63, "width": 93, "height": 59 }, + "mouth-oooo": { "x": 23.69, "y": -32.24, "rotation": -70.63, "width": 93, "height": 59 }, + "mouth-smile": { "x": 23.69, "y": -32.24, "rotation": -70.63, "width": 93, "height": 59 } + }, + "rear-upper-arm": { + "rear-upper-arm": { "x": 21.13, "y": 4.09, "rotation": 89.33, "width": 40, "height": 87 } + }, + "front-upper-arm": { + "front-upper-arm": { "x": 25.2, "y": 1.17, "rotation": 97.9, "width": 46, "height": 97 } + }, + "front-bracer": { + "front-bracer": { "x": 12.03, "y": -1.68, "rotation": 79.6, "width": 58, "height": 80 } + }, + "front-foot": { + "front-foot": { "x": 29.52, "y": 7.84, "rotation": 18.69, "width": 126, "height": 69 } + }, + "goggles": { + "goggles": { "x": 97.08, "y": 6.54, "rotation": -70.63, "width": 261, "height": 166 } + }, + "front-shin": { + "front-shin": { "x": 55.12, "y": -3.54, "rotation": 96.59, "width": 82, "height": 184 } + }, + "neck": { + "neck": { "x": 9.77, "y": -3.01, "rotation": -55.22, "width": 36, "height": 41 } + }, + "head": { + "head": { "x": 128.96, "y": 0.3, "rotation": -70.63, "width": 271, "height": 298 } + }, + "muzzle": { + "muzzle01": { + "x": 159.26, + "y": 5.83, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 133, + "height": 79 + }, + "muzzle02": { + "x": 191.23, + "y": 5.91, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 135, + "height": 84 + }, + "muzzle03": { + "x": 230.67, + "y": 6.02, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 166, + "height": 106 + }, + "muzzle04": { + "x": 218.54, + "y": 5.99, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 149, + "height": 90 + } + }, + "rear-bracer": { + "rear-bracer": { "x": 11.15, "y": -2.2, "rotation": 66.17, "width": 56, "height": 72 } + }, + "rear-thigh": { + "rear-thigh": { "x": 33.11, "y": -4.11, "rotation": 72.54, "width": 55, "height": 94 } + }, + "front-fist": { + "front-fist-closed": { "x": 35.5, "y": 6, "rotation": 67.16, "width": 75, "height": 82 }, + "front-fist-open": { "x": 39.57, "y": 7.76, "rotation": 67.16, "width": 86, "height": 87 } + }, + "eye": { + "eye-indifferent": { "x": 85.72, "y": -28.18, "rotation": -70.63, "width": 93, "height": 89 }, + "eye-surprised": { "x": 85.72, "y": -28.18, "rotation": -70.63, "width": 93, "height": 89 } + }, + "front-thigh": { + "front-thigh": { "x": 42.48, "y": 4.45, "rotation": 84.87, "width": 45, "height": 112 } + }, + "torso": { + "torso": { "x": 63.61, "y": 7.12, "rotation": -94.54, "width": 98, "height": 180 } + }, + "rear-foot": { + "rear-foot": { "x": 31.51, "y": 3.58, "rotation": 23.07, "width": 113, "height": 60 } + } + } + } +], +"events": { + "footstep": {} +}, +"animations": { + "death": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-oooo" }, + { "time": 2.2333, "name": "mouth-grind" }, + { "time": 4.5333, "name": "mouth-oooo" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "eye": { + "attachment": [ + { "name": "eye-surprised" }, + { "time": 0.4667, "name": "eye-indifferent" }, + { "time": 2.2333, "name": "eye-surprised" }, + { "time": 4.5333, "name": "eye-indifferent" } + ] + } + }, + "bones": { + "head": { + "rotate": [ + { "angle": -2.83 }, + { "time": 0.1333, "angle": -28.74 }, + { "time": 0.2333, "angle": 11.43 }, + { "time": 0.3333, "angle": -50.25 }, + { "time": 0.4, "angle": -72.67, "curve": "stepped" }, + { "time": 0.4333, "angle": -72.67 }, + { "time": 0.5, "angle": -20.25 }, + { "time": 0.5667, "angle": -85.29, "curve": "stepped" }, + { "time": 2.2333, "angle": -85.29 }, + { "time": 2.5, "angle": -51.96, "curve": "stepped" }, + { "time": 4.5333, "angle": -51.96 }, + { "time": 4.6667, "angle": -85.29 } + ] + }, + "neck": { + "rotate": [ + { "angle": -2.83 }, + { "time": 0.1333, "angle": 12.35 }, + { "time": 0.2333, "angle": 29.89 }, + { "time": 0.3, "angle": 70.36 }, + { "time": 0.4, "angle": -10.22, "curve": "stepped" }, + { "time": 0.4333, "angle": -10.22 }, + { "time": 0.5, "angle": 2.93 }, + { "time": 0.5667, "angle": 47.95, "curve": "stepped" }, + { "time": 2.2333, "angle": 47.95 }, + { "time": 2.5, "angle": 18.51, "curve": "stepped" }, + { "time": 4.5333, "angle": 18.51 }, + { "time": 4.6667, "angle": 47.95 } + ] + }, + "torso": { + "rotate": [ + { "angle": -8.62 }, + { "time": 0.1333, "angle": 28.2 }, + { "time": 0.2667, "angle": -280.19 }, + { "time": 0.4, "angle": -237.23, "curve": "stepped" }, + { "time": 0.4333, "angle": -237.23 }, + { "time": 0.5, "angle": 76.03 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "angle": -38.86 }, + { "time": 0.1333, "angle": -299.59 }, + { "time": 0.2667, "angle": -244.75 }, + { "time": 0.4, "angle": -292.36 }, + { "time": 0.4333, "angle": -315.85 }, + { "time": 0.5, "angle": -347.94 }, + { "time": 0.7, "angle": -347.33, "curve": "stepped" }, + { "time": 2.2333, "angle": -347.33 }, + { "time": 2.7, "angle": -290.68 }, + { "time": 2.7667, "angle": -285.11 }, + { "time": 4.6667, "angle": -290.68 }, + { "time": 4.8, "angle": 8.61 }, + { "time": 4.8667, "angle": 10.94 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": -44.7 }, + { "time": 0.1333, "angle": 112.26 }, + { "time": 0.2667, "angle": 129.08 }, + { "time": 0.4, "angle": 134.94, "curve": "stepped" }, + { "time": 0.4333, "angle": 134.94 }, + { "time": 0.5667, "angle": 172.6 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": 21.88 }, + { "time": 0.1333, "angle": 11.49 }, + { "time": 0.2667, "angle": -18.82 }, + { "time": 0.4, "angle": -18.93 }, + { "time": 0.4333, "angle": -18.28 }, + { "time": 0.5, "angle": 60.62 }, + { "time": 0.7, "angle": -18.88, "curve": "stepped" }, + { "time": 2.2333, "angle": -18.88 }, + { "time": 2.7, "angle": -1.96, "curve": "stepped" }, + { "time": 4.6667, "angle": -1.96 }, + { "time": 4.8, "angle": 34.55 }, + { "time": 4.9333, "angle": -18.75 } + ] + }, + "front-fist": { + "rotate": [ + { "angle": -2.33 }, + { "time": 0.2667, "angle": 26.35 }, + { "time": 0.7, "angle": -6.08, "curve": "stepped" }, + { "time": 2.2333, "angle": -6.08 }, + { "time": 2.7, "angle": 5.73, "curve": "stepped" }, + { "time": 4.6667, "angle": 5.73 }, + { "time": 4.8667, "angle": -6.52 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": 10.36 }, + { "time": 0.1333, "angle": -23.12 }, + { "time": 0.2667, "angle": -23.12 }, + { "time": 0.4, "angle": -23.16, "curve": "stepped" }, + { "time": 0.4333, "angle": -23.16 }, + { "time": 0.5667, "angle": -23.2 } + ] + }, + "gun": { + "rotate": [ + { "angle": -2.79 }, + { "time": 0.1333, "angle": -24.58 } + ] + }, + "front-thigh": { + "rotate": [ + {}, + { "time": 0.1333, "angle": 8.47 }, + { "time": 0.2667, "angle": 115.96 }, + { "time": 0.4, "angle": 180.66, "curve": "stepped" }, + { "time": 0.4333, "angle": 180.66 }, + { "time": 0.5, "angle": 155.22 }, + { "time": 0.6, "angle": 97.74 } + ] + }, + "front-shin": { + "rotate": [ + {}, + { "time": 0.1333, "angle": -27.37 }, + { "time": 0.2667, "angle": -35.1 }, + { "time": 0.4, "angle": -37.73, "curve": "stepped" }, + { "time": 0.4333, "angle": -37.73 }, + { "time": 0.5, "angle": -40.07 }, + { "time": 0.6, "angle": 2.76 } + ] + }, + "rear-thigh": { + "rotate": [ + {}, + { "time": 0.1333, "angle": 70.45 }, + { "time": 0.2667, "angle": 155.35 }, + { "time": 0.4, "angle": 214.31, "curve": "stepped" }, + { "time": 0.4333, "angle": 214.31 }, + { "time": 0.5, "angle": 169.67 }, + { "time": 0.8, "angle": 83.27 } + ] + }, + "rear-shin": { + "rotate": [ + {}, + { "time": 0.1333, "angle": 18.94 }, + { "time": 0.2667, "angle": -21.04 }, + { "time": 0.4, "angle": -29.94, "curve": "stepped" }, + { "time": 0.4333, "angle": -29.94 }, + { "time": 0.5, "angle": -16.79 }, + { "time": 0.8, "angle": 7.78 } + ] + }, + "rear-foot": { + "rotate": [ + {}, + { "time": 0.1333, "angle": -11.63 }, + { "time": 0.4, "angle": -45.6 } + ] + }, + "front-foot": { + "rotate": [ + {}, + { "time": 0.4, "angle": -48.75 } + ] + }, + "hip": { + "translate": [ + {}, + { "time": 0.2, "x": 50.35, "y": 151.73 }, + { "time": 0.4, "x": 5.17, "y": -119.65, "curve": "stepped" }, + { "time": 0.4333, "x": 5.17, "y": -119.65 }, + { "time": 0.5, "x": 50.35, "y": -205.19 } + ] + } + } + }, + "hit": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" }, + { "time": 0.3333, "name": "mouth-smile" } + ] + }, + "front-fist": { + "attachment": [ + { "time": 0.1667, "name": "front-fist-open" } + ] + } + }, + "bones": { + "torso": { + "rotate": [ + { "angle": 56.42 }, + { "time": 0.3333, "angle": 8.89 } + ] + }, + "neck": { + "rotate": [ + { "angle": 35.39 }, + { "time": 0.2333, "angle": 24.95 } + ] + }, + "head": { + "rotate": [ + { "angle": 10.22 }, + { "time": 0.3333, "angle": -41.3 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "angle": -310.93, "curve": 0.38, "c2": 0.53, "c3": 0.745 }, + { "time": 0.3333, "angle": -112.6 } + ], + "translate": [ + { "x": 7.23, "y": -13.13 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": 36.99 }, + { "time": 0.3333, "angle": -28.65 } + ] + }, + "front-fist": { + "rotate": [ + { "angle": 13.59 }, + { "time": 0.3333, "angle": 7.56 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 271.02, "curve": 0.343, "c2": 0.36, "c3": 0.68, "c4": 0.71 }, + { "time": 0.3333, "angle": -15.84 } + ], + "translate": [ + { "time": 0.3333, "x": -0.1, "y": -0.46 } + ] + }, + "rear-bracer": { + "rotate": [ + {}, + { "time": 0.3333, "angle": 40.03 } + ] + }, + "gun": { + "rotate": [ + { "angle": 14.98 }, + { "time": 0.3333, "angle": 39.76 } + ] + }, + "front-thigh": { + "rotate": [ + { "angle": 90.94, "curve": 0.227, "c2": 0.27, "c3": 0.433 }, + { "time": 0.3333, "angle": 32.03 } + ], + "translate": [ + { "x": 7.21, "y": -4 } + ] + }, + "rear-thigh": { + "rotate": [ + { "angle": 40.52, "curve": 0.296, "c2": 0.3, "c3": 0.59 }, + { "time": 0.3333, "angle": 90.77 } + ], + "translate": [ + { "x": -1.96, "y": -0.32 } + ] + }, + "front-shin": { + "rotate": [ + { "angle": -96.63 }, + { "time": 0.3333, "angle": -15.13 } + ] + }, + "rear-shin": { + "rotate": [ + { "angle": 8 }, + { "time": 0.3333, "angle": -67.54 } + ] + }, + "front-foot": { + "rotate": [ + { "angle": 5.4 }, + { "time": 0.3333, "angle": -16.27 } + ] + }, + "rear-foot": { + "rotate": [ + { "angle": 2.67 }, + { "time": 0.3333, "angle": -10.31 } + ] + }, + "hip": { + "translate": [ + { "x": -75.55, "y": -78.04 }, + { "time": 0.2333, "x": -36.48, "y": 12.42 }, + { "time": 0.3333, "x": -36.48, "y": -3 } + ] + } + } + }, + "idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "torso": { + "rotate": [ + { "angle": -5.62, "curve": 0.25, "c3": 0.75 }, + { "time": 0.8333, "angle": -9.66, "curve": 0.25, "c3": 0.75 }, + { "time": 1.6667, "angle": -5.62 } + ], + "translate": [ + { "x": -6.5 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "angle": -59.85, "curve": 0.493, "c3": 0.75 }, + { "time": 0.6667, "angle": -54.32, "curve": 0.324, "c2": 0.11, "c3": 0.75 }, + { "time": 1.6667, "angle": -59.85 } + ], + "translate": [ + { "x": -7.12, "y": -8.24 }, + { "time": 0.6667, "x": -6.32, "y": -8.31 }, + { "time": 1.6667, "x": -7.12, "y": -8.24 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 62.42, "curve": 0.504, "c2": 0.02, "c3": 0.75 }, + { "time": 0.7333, "angle": 43.83, "curve": 0.25, "c3": 0.75 }, + { "time": 1.6667, "angle": 62.42 } + ], + "translate": [ + { "x": -1.83, "y": -16.79 }, + { "time": 0.6667, "x": 0.35, "y": -15.23 }, + { "time": 1.6667, "x": -1.83, "y": -16.79 } + ] + }, + "neck": { + "rotate": [ + {}, + { "time": 0.6667, "angle": 2.39 }, + { "time": 1.6667 } + ], + "translate": [ + { "x": -1.89, "y": -4.76 } + ] + }, + "front-thigh": { + "rotate": [ + { "angle": 0.65, "curve": 0.236, "c2": 0.01, "c3": 0.559, "c4": 0.99 }, + { "time": 0.6667, "angle": -4.34, "curve": 0.595, "c3": 0.653 }, + { "time": 1.6667, "angle": 0.65 } + ], + "translate": [ + { "x": -13.4, "y": 6.7 } + ], + "scale": [ + { "x": 0.945, "curve": 0.236, "c2": 0.01, "c3": 0.559, "c4": 0.99 }, + { "time": 0.6667, "x": 0.917, "curve": 0.595, "c3": 0.653 }, + { "time": 1.6667, "x": 0.945 } + ] + }, + "front-shin": { + "rotate": [ + { "angle": -19.29 } + ], + "scale": [ + { "curve": 0.236, "c2": 0.01, "c3": 0.559, "c4": 0.99 }, + { "time": 0.6667, "x": 0.994, "curve": 0.595, "c3": 0.653 }, + { "time": 1.6667 } + ] + }, + "rear-thigh": { + "rotate": [ + { "angle": 30.51, "curve": 0.236, "c2": 0.01, "c3": 0.559, "c4": 0.99 }, + { "time": 0.6667, "angle": 40.15, "curve": 0.595, "c3": 0.653 }, + { "time": 1.6667, "angle": 30.51 } + ] + }, + "rear-shin": { + "rotate": [ + { "angle": -23.83, "curve": 0.236, "c2": 0.01, "c3": 0.559, "c4": 0.99 }, + { "time": 0.6667, "angle": -43.77, "curve": 0.595, "c3": 0.653 }, + { "time": 1.6667, "angle": -23.83 } + ] + }, + "front-foot": { + "rotate": [ + { "angle": 5.14, "curve": 0.236, "c2": 0.01, "c3": 0.559, "c4": 0.99 }, + { "time": 0.6667, "angle": 10.05, "curve": 0.595, "c3": 0.653 }, + { "time": 1.6667, "angle": 5.14 } + ], + "scale": [ + { "x": 0.755, "y": 1.31 } + ] + }, + "rear-foot": { + "rotate": [ + { "angle": -7.34, "curve": 0.236, "c2": 0.01, "c3": 0.559, "c4": 0.99 }, + { "time": 0.6667, "angle": 3.85, "curve": 0.595, "c3": 0.653 }, + { "time": 1.6667, "angle": -7.34 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": -17.16, "curve": 0.25, "c3": 0.75 }, + { "time": 0.6667, "angle": 12.53, "curve": 0.25, "c3": 0.75 }, + { "time": 1.6667, "angle": -17.16 } + ] + }, + "head": { + "rotate": [ + { "angle": -5.51, "curve": 0.25, "c3": 0.75 }, + { "time": 0.6667, "angle": -3.12, "curve": 0.25, "c3": 0.75 }, + { "time": 1.6667, "angle": -5.51 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": 45.47, "curve": 0.493, "c3": 0.75 }, + { "time": 0.6667, "angle": 41.34, "curve": 0.321, "c2": 0.11, "c3": 0.736, "c4": 0.92 }, + { "time": 1.6667, "angle": 45.47 } + ] + }, + "gun": { + "rotate": [ + { "curve": 0.25, "c3": 0.75 }, + { "time": 0.6667, "angle": -15.59, "curve": 0.733, "c3": 0.77, "c4": 0.99 }, + { "time": 1.6667 } + ] + }, + "front-fist": { + "rotate": [ + { "angle": -6.85, "curve": 0.493, "c3": 0.75 }, + { "time": 0.6667, "angle": -14.63, "curve": 0.324, "c2": 0.11, "c3": 0.75 }, + { "time": 1.6667, "angle": -6.85 } + ], + "scale": [ + { "curve": 0.25, "c3": 0.75 }, + { "time": 0.6667, "x": 0.689, "y": 1.101, "curve": 0.25, "c3": 0.75 }, + { "time": 1.6667 } + ] + }, + "hip": { + "translate": [ + { "x": -6.64, "y": -23.02, "curve": 0.236, "c2": 0.01, "c3": 0.559, "c4": 0.99 }, + { "time": 0.6667, "x": 6.28, "y": -35.01, "curve": 0.595, "c3": 0.653 }, + { "time": 1.6667, "x": -6.64, "y": -23.02 } + ] + } + } + }, + "jump": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" }, + { "time": 0.2, "name": "front-fist-closed" }, + { "time": 0.6667, "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { "angle": 91.53, "curve": 0.278, "c2": 0.46, "c3": 0.764 }, + { "time": 0.2, "angle": -35.84, "curve": 0.761, "c3": 0.75 }, + { "time": 0.4333, "angle": 127.74 }, + { "time": 0.7333, "angle": 48.18, "curve": 0.227, "c2": 0.27, "c3": 0.433 }, + { "time": 0.8333, "angle": 25.35 }, + { "time": 0.9333, "angle": 45.38 }, + { "time": 1.0333, "angle": 38.12 }, + { "time": 1.1333, "angle": 25.35 }, + { "time": 1.3333, "angle": 91.53 } + ], + "translate": [ + { "x": -2.57, "y": 5.78 }, + { "time": 0.4333, "x": 8.3, "y": 7.99 }, + { "time": 0.7333, "x": 7.21, "y": -4 }, + { "time": 1.3333, "x": -2.57, "y": 5.78 } + ] + }, + "torso": { + "rotate": [ + { "angle": -42.64 }, + { "time": 0.2, "angle": -5.74 }, + { "time": 0.4333, "angle": -50.76 }, + { "time": 0.7333, "angle": 1.9 }, + { "time": 0.8333, "angle": 11.59 }, + { "time": 0.9667, "angle": -1.9 }, + { "time": 1.1333, "angle": 11.59 }, + { "time": 1.3333, "angle": -42.64 } + ] + }, + "rear-thigh": { + "rotate": [ + { "angle": -26.32 }, + { "time": 0.2, "angle": 121.44 }, + { "time": 0.4333, "angle": 70.55 }, + { "time": 0.7333, "angle": 79.9, "curve": 0.296, "c2": 0.3, "c3": 0.59 }, + { "time": 0.8333, "angle": 99.12 }, + { "time": 0.9333, "angle": 74.06 }, + { "time": 1.0333, "angle": 98.05 }, + { "time": 1.1333, "angle": 99.12 }, + { "time": 1.3333, "angle": -26.32 } + ], + "translate": [ + { "x": -0.56, "y": -0.32 }, + { "time": 0.4333, "x": -8.5, "y": 10.58 }, + { "time": 0.7333, "x": -1.96, "y": -0.32 }, + { "time": 1.3333, "x": -0.56, "y": -0.32 } + ] + }, + "rear-shin": { + "rotate": [ + { "angle": -78.69 }, + { "time": 0.4333, "angle": -55.56 }, + { "time": 0.7333, "angle": -62.84 }, + { "time": 0.8333, "angle": -80.75 }, + { "time": 0.9333, "angle": -41.13 }, + { "time": 1.0333, "angle": -77.4 }, + { "time": 1.1333, "angle": -80.75 }, + { "time": 1.3333, "angle": -78.69 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "angle": -22.62 }, + { "time": 0.2, "angle": -246.69 }, + { "time": 0.6, "angle": 11.28, "curve": 0.246, "c3": 0.633, "c4": 0.54 }, + { "time": 0.7333, "angle": -57.46, "curve": 0.38, "c2": 0.53, "c3": 0.745 }, + { "time": 0.8667, "angle": -112.6 }, + { "time": 0.9333, "angle": -102.17 }, + { "time": 1.0333, "angle": -108.61 }, + { "time": 1.1333, "angle": -112.6 }, + { "time": 1.3333, "angle": -22.62 } + ], + "translate": [ + { "x": 6.08, "y": 7.15 }, + { "time": 0.2, "x": 7.23, "y": -13.13, "curve": "stepped" }, + { "time": 0.7333, "x": 7.23, "y": -13.13 }, + { "time": 1.3333, "x": 6.08, "y": 7.15 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": 66.47 }, + { "time": 0.2, "angle": 42.4 }, + { "time": 0.4333, "angle": 26.06 }, + { "time": 0.7333, "angle": 13.28 }, + { "time": 0.8667, "angle": -28.65 }, + { "time": 0.9333, "angle": -22.31 }, + { "time": 1.0333, "angle": -35.39 }, + { "time": 1.1333, "angle": -28.65 }, + { "time": 1.3333, "angle": 66.47 } + ] + }, + "front-fist": { + "rotate": [ + { "angle": -28.43 }, + { "time": 0.4333, "angle": -45.61 }, + { "time": 0.7333, "angle": -53.66 }, + { "time": 0.8667, "angle": 7.56 }, + { "time": 0.9333, "angle": 31.16 }, + { "time": 1.0333, "angle": -32.59 }, + { "time": 1.1333, "angle": 7.56 }, + { "time": 1.3333, "angle": -28.43 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 39.69 }, + { "time": 0.2, "angle": 276.58 }, + { "time": 0.3, "angle": 17.74 }, + { "time": 0.4333, "angle": 83.38 }, + { "time": 0.6, "angle": -4.72, "curve": 0.246, "c3": 0.633, "c4": 0.54 }, + { "time": 0.7333, "angle": -69.63, "curve": 0.343, "c2": 0.36, "c3": 0.68, "c4": 0.71 }, + { "time": 0.7667, "angle": 321.47, "curve": 0.334, "c2": 0.33, "c3": 0.667, "c4": 0.67 }, + { "time": 0.8, "angle": 33.71, "curve": 0.359, "c2": 0.64, "c3": 0.694 }, + { "time": 0.8667, "angle": 34.56 }, + { "time": 1.0333, "angle": 71.97 }, + { "time": 1.1333, "angle": 34.56 }, + { "time": 1.3333, "angle": 39.69 } + ], + "translate": [ + { "x": -3.1, "y": -4.87 }, + { "time": 0.2, "x": 23.33, "y": 49.07 }, + { "time": 0.4333, "x": 20.78, "y": 40.21 }, + { "time": 1.3333, "x": -3.1, "y": -4.87 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": 29.67 }, + { "time": 0.2, "angle": 45.07 }, + { "time": 0.4333, "angle": -4.35 }, + { "time": 0.7667, "angle": 61.69 }, + { "time": 0.8, "angle": 82.6 }, + { "time": 0.8667, "angle": 80.06 }, + { "time": 1.0333, "angle": 57.56 }, + { "time": 1.1333, "angle": 80.06 }, + { "time": 1.3333, "angle": 29.67 } + ] + }, + "neck": { + "rotate": [ + { "angle": 24.91 }, + { "time": 0.2, "angle": 16.32 }, + { "time": 0.4333, "angle": 7.45 }, + { "time": 0.7333, "angle": -20.35 }, + { "time": 0.8333, "angle": -0.69, "curve": "stepped" }, + { "time": 1.1333, "angle": -0.69 }, + { "time": 1.3333, "angle": 24.91 } + ] + }, + "head": { + "rotate": [ + { "angle": 24.92 }, + { "time": 0.2, "angle": 10.36 }, + { "time": 0.4333, "angle": 28.65 }, + { "time": 0.7333, "angle": -2.66 }, + { "time": 0.8333, "angle": -28.94, "curve": "stepped" }, + { "time": 1.1333, "angle": -28.94 }, + { "time": 1.3333, "angle": 24.92 } + ] + }, + "front-shin": { + "rotate": [ + { "angle": -90.63, "curve": 0.416, "c2": 0.55, "c3": 0.743 }, + { "time": 0.2, "angle": -10.52, "curve": 0.644, "c2": 0.01, "c3": 0.75 }, + { "time": 0.4333, "angle": -127.72 }, + { "time": 0.7333, "angle": -19.92 }, + { "time": 0.8333, "angle": -5.17 }, + { "time": 0.9333, "angle": -35.06 }, + { "time": 1.0333, "angle": -43.97 }, + { "time": 1.1333, "angle": -5.17 }, + { "time": 1.3333, "angle": -90.63 } + ] + }, + "front-foot": { + "rotate": [ + { "angle": -0.8 }, + { "time": 0.0333, "angle": 16.28 }, + { "time": 0.0667, "angle": 23.52 }, + { "time": 0.1, "angle": 21.02 }, + { "time": 0.1333, "angle": 10.93 }, + { "time": 0.2, "angle": -38.46 }, + { "time": 0.4333, "angle": 6.62 }, + { "time": 0.7333, "angle": -11.52 }, + { "time": 1.0333, "angle": -22.92 }, + { "time": 1.3333, "angle": -0.8 } + ] + }, + "rear-foot": { + "rotate": [ + { "angle": -12.78 }, + { "time": 0.2, "angle": 17.06 }, + { "time": 0.4333, "angle": 19.45 }, + { "time": 0.7333, "angle": 2.67 }, + { "time": 1.0333, "angle": -28.5 }, + { "time": 1.3333, "angle": -12.78 } + ] + }, + "gun": { + "rotate": [ + { "angle": 6.18 }, + { "time": 0.2, "angle": 30.81 }, + { "time": 0.4333, "angle": 13.26 }, + { "time": 0.7333, "angle": 14.98 }, + { "time": 0.7667, "angle": 25.65 }, + { "time": 0.8, "angle": 20.62 }, + { "time": 0.8667, "angle": 64.53 }, + { "time": 1.0333, "angle": 8.6 }, + { "time": 1.1333, "angle": 64.53 }, + { "time": 1.3333, "angle": 6.18 } + ] + }, + "hip": { + "translate": [ + { "x": -34.52, "y": -78.63, "curve": 0.233, "c2": 1.01, "c3": 0.75 }, + { + "time": 0.2, + "x": -34.52, + "y": 182.51, + "curve": 0.232, + "c2": 0.48, + "c3": 0.599, + "c4": 0.79 + }, + { + "time": 0.7667, + "x": -34.52, + "y": 596.22, + "curve": 0.33, + "c2": 0.17, + "c3": 0.661, + "c4": 0.22 + }, + { "time": 1.1333, "x": -34.52, "y": 2.5 }, + { "time": 1.3333, "x": -34.52, "y": -78.63 } + ] + } + } + }, + "run": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { "angle": 42.05, "curve": 0.196, "c2": 0.86, "c3": 0.75 }, + { "time": 0.0667, "angle": 46.08 }, + { "time": 0.1333, "angle": -20.29 }, + { "time": 0.2, "angle": -27.24 }, + { "time": 0.2667, "angle": -47.17 }, + { "time": 0.3333, "angle": -39.79 }, + { "time": 0.4, "angle": -25.86 }, + { "time": 0.4667, "angle": 14.35 }, + { "time": 0.5333, "angle": 55.63 }, + { "time": 0.6, "angle": 69.65 }, + { "time": 0.6667, "angle": 86.41 }, + { "time": 0.7333, "angle": 65.88 }, + { "time": 0.8, "angle": 42.05 } + ], + "translate": [ + {}, + { "time": 0.0333, "x": -5.8, "y": 11.16 }, + { "time": 0.0667, "x": -5.13, "y": 11.55 }, + { "time": 0.1333, "x": -7.7, "y": 8.99 }, + { "time": 0.5333, "x": -1.26, "y": 3.83 }, + { "time": 0.8 } + ] + }, + "torso": { + "rotate": [ + { "angle": -39.71 }, + { "time": 0.2, "angle": -57.29 }, + { "time": 0.4, "angle": -39.71 }, + { "time": 0.6, "angle": -57.29 }, + { "time": 0.8, "angle": -39.71 } + ] + }, + "rear-thigh": { + "rotate": [ + { "angle": -56.59 }, + { "time": 0.0667, "angle": -21.57 }, + { "time": 0.1333, "angle": 27.95 }, + { "time": 0.2, "angle": 42.43 }, + { "time": 0.2667, "angle": 62.37 }, + { "time": 0.3333, "angle": 45.43 }, + { "time": 0.4, "angle": 15.67 }, + { "time": 0.4667, "angle": 28.22 }, + { "time": 0.5333, "angle": -38.62 }, + { "time": 0.6, "angle": -53.27 }, + { "time": 0.6667, "angle": -79.31 }, + { "time": 0.7333, "angle": -86.47 }, + { "time": 0.8, "angle": -56.59 } + ], + "translate": [ + {}, + { "time": 0.4, "x": -6.76, "y": -3.86 }, + { "time": 0.4333, "x": -15.85, "y": 7.28 }, + { "time": 0.4667, "x": -13.05, "y": 4.05 }, + { "time": 0.5, "x": -10.25, "y": 7.11 }, + { "time": 0.5333, "x": -9.02, "y": -5.15 }, + { "time": 0.6667, "x": -23.18, "y": -2.58 }, + { "time": 0.8 } + ] + }, + "rear-shin": { + "rotate": [ + { "angle": -74 }, + { "time": 0.0667, "angle": -83.38 }, + { "time": 0.1333, "angle": -106.7 }, + { "time": 0.2, "angle": -66.01 }, + { "time": 0.2667, "angle": -55.22 }, + { "time": 0.3333, "angle": -24.8 }, + { "time": 0.4, "angle": 18.44, "curve": 0.25, "c3": 0.75 }, + { "time": 0.4667, "angle": -56.65 }, + { "time": 0.5333, "angle": -11.95, "curve": 0.25, "c3": 0.75 }, + { "time": 0.6667, "angle": -41.27 }, + { "time": 0.7333, "angle": -43.61 }, + { "time": 0.8, "angle": -74 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "angle": -89.37 }, + { "time": 0.0667, "angle": -95.67 }, + { "time": 0.1333, "angle": -22.01 }, + { "time": 0.2, "angle": -316.04 }, + { "time": 0.2667, "angle": -274.94 }, + { "time": 0.3333, "angle": -273.74 }, + { "time": 0.4, "angle": -272.09 }, + { "time": 0.4667, "angle": -264.9 }, + { "time": 0.5333, "angle": -320.1 }, + { "time": 0.6, "angle": -50.84 }, + { "time": 0.6667, "angle": -81.73 }, + { "time": 0.7333, "angle": -83.92 }, + { "time": 0.8, "angle": -89.37 } + ], + "translate": [ + { "x": 6.25, "y": 10.05 }, + { "time": 0.2667, "x": 4.96, "y": -13.13 }, + { "time": 0.6, "x": -2.43, "y": 1.95 }, + { "time": 0.8, "x": 6.25, "y": 10.05 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": 33.44 }, + { "time": 0.0667, "angle": 20.54 }, + { "time": 0.1333, "angle": 15.26 }, + { "time": 0.2, "angle": 19.29 }, + { "time": 0.2667, "angle": 22.62 }, + { "time": 0.3333, "angle": 37.29 }, + { "time": 0.4, "angle": 41.53 }, + { "time": 0.4667, "angle": 31.74 }, + { "time": 0.5333, "angle": 67.45 }, + { "time": 0.6667, "angle": 39.77 }, + { "time": 0.7333, "angle": 30.95 }, + { "time": 0.8, "angle": 33.44 } + ] + }, + "front-fist": { + "rotate": [ + { "angle": -19.76 }, + { "time": 0.0667, "angle": -37.11 }, + { "time": 0.1333, "angle": -50.8 }, + { "time": 0.2667, "angle": -12.69 }, + { "time": 0.3333, "angle": 3.01 }, + { "time": 0.4333, "angle": 12.06 }, + { "time": 0.5333, "angle": 13.26 }, + { "time": 0.8, "angle": -19.76 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 68.68 }, + { "time": 0.0667, "angle": 73.89 }, + { "time": 0.1333, "angle": -9.64 }, + { "time": 0.2, "angle": 284.28 }, + { "time": 0.2667, "angle": 283.29 }, + { "time": 0.3333, "angle": 278.29 }, + { "time": 0.4, "angle": 271.03 }, + { "time": 0.4667, "angle": 263.2 }, + { "time": 0.5333, "angle": 314.26 }, + { "time": 0.6, "angle": 16.83 }, + { "time": 0.6667, "angle": 70.35 }, + { "time": 0.7333, "angle": 73.54 }, + { "time": 0.8, "angle": 68.68 } + ], + "translate": [ + { "x": -2.57, "y": -8.89 }, + { "time": 0.1333, "x": -4.68, "y": 7.21 }, + { "time": 0.2, "x": 21.73, "y": 51.18 }, + { "time": 0.6, "x": 4.33, "y": 2.06 }, + { "time": 0.8, "x": -2.57, "y": -8.89 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": 31.05 }, + { "time": 0.0667, "angle": 28.28 }, + { "time": 0.1333, "angle": 49.36 }, + { "time": 0.2, "angle": 59.37 }, + { "time": 0.2667, "angle": 8.56 }, + { "time": 0.3333, "angle": 9.39 }, + { "time": 0.4, "angle": 11.51 }, + { "time": 0.4667, "angle": 7.22 }, + { "time": 0.5333, "angle": -18.44 }, + { "time": 0.6, "angle": 11.45 }, + { "time": 0.6667, "angle": 9.99 }, + { "time": 0.7333, "angle": 8.29 }, + { "time": 0.8, "angle": 31.05 } + ] + }, + "neck": { + "rotate": [ + { "angle": 11.03 }, + { "time": 0.2, "angle": 13.59 }, + { "time": 0.4, "angle": 11.03 }, + { "time": 0.6, "angle": 13.59 }, + { "time": 0.8, "angle": 11.03 } + ] + }, + "head": { + "rotate": [ + { "angle": 11.03 }, + { "time": 0.1, "angle": 12.35 }, + { "time": 0.2, "angle": 25.55 }, + { "time": 0.4, "angle": 11.03 }, + { "time": 0.5, "angle": 12.35 }, + { "time": 0.6, "angle": 25.55 }, + { "time": 0.8, "angle": 11.03 } + ] + }, + "front-shin": { + "rotate": [ + { "curve": 0.481, "c2": 0.01, "c3": 0.75 }, + { "time": 0.0667, "angle": -64.42 }, + { "time": 0.1333, "angle": -20.6, "curve": 0.25, "c3": 0.75 }, + { "time": 0.2667, "angle": -62.52 }, + { "time": 0.3333, "angle": -79.75 }, + { "time": 0.4, "angle": -78.28 }, + { "time": 0.4667, "angle": -118.96, "curve": 0.93, "c2": 0.01, "c3": 0.953, "c4": 0.95 }, + { "time": 0.6, "angle": -88.96 }, + { "time": 0.6667, "angle": -79.1 }, + { "time": 0.7333, "angle": -47.78 }, + { "time": 0.8 } + ] + }, + "front-foot": { + "rotate": [ + {}, + { "time": 0.0333, "angle": -21.13, "curve": 0.121, "c2": 0.24, "c3": 0.75 }, + { "time": 0.0667, "angle": 17.64 }, + { "time": 0.1, "angle": 29.93 }, + { "time": 0.1333, "angle": 16.45 }, + { "time": 0.2, "angle": -29.23 }, + { "time": 0.2667, "angle": -1.62 }, + { "time": 0.3333, "angle": -10.23 }, + { "time": 0.4667, "angle": -15.99 }, + { "time": 0.6, "angle": 9.03 }, + { "time": 0.7333, "angle": 17.33 }, + { "time": 0.8 } + ] + }, + "rear-foot": { + "rotate": [ + {}, + { "time": 0.0667, "angle": -12.04 }, + { "time": 0.1333, "angle": -0.87 }, + { "time": 0.2, "angle": 25.81 }, + { "time": 0.2667, "angle": 4.71 }, + { "time": 0.4, "angle": 18.09, "curve": 0.281, "c2": 0.74, "c3": 0.75 }, + { "time": 0.4333, "angle": -1.71 }, + { "time": 0.4667, "angle": 27.13 }, + { "time": 0.5, "angle": 38.84 }, + { "time": 0.5333, "angle": 30.77 }, + { "time": 0.5667, "angle": -20.49 }, + { "time": 0.6, "angle": -30.81 }, + { "time": 0.6667, "angle": -1.32 }, + { "time": 0.8 } + ] + }, + "gun": { + "rotate": [ + {}, + { "time": 0.1333, "angle": 24.73 }, + { "time": 0.5, "angle": -11.88 }, + { "time": 0.8 } + ] + }, + "hip": { + "translate": [ + { "x": -62.48, "y": -23.11 }, + { "time": 0.0667, "x": -62.48, "y": -38.51, "curve": 0.244, "c2": 0.04, "c3": 0.75 }, + { "time": 0.2667, "x": -62.48, "y": 22.29, "curve": 0.17, "c2": 0.53, "c3": 0.75 }, + { "time": 0.4, "x": -62.48, "y": -23.11 }, + { "time": 0.4333, "x": -62.48, "y": -24.59 }, + { "time": 0.4667, "x": -62.48, "y": -43.29, "curve": 0.25, "c3": 0.75 }, + { "time": 0.6667, "x": -62.48, "y": 22.29 }, + { "time": 0.8, "x": -62.48, "y": -23.11 } + ] + } + }, + "events": [ + { "name": "footstep" }, + { "time": 0.4333, "name": "footstep", "int": 1 } + ] + }, + "shoot": { + "slots": { + "muzzle": { + "color": [ + { "time": 0.3667, "color": "ffffff00" } + ], + "attachment": [ + { "time": 0.1333, "name": "muzzle01" }, + { "time": 0.2, "name": "muzzle02" }, + { "time": 0.2667, "name": "muzzle03" }, + { "time": 0.3333, "name": "muzzle04" }, + { "time": 0.3667, "name": null } + ] + } + }, + "bones": { + "gun-tip": { + "translate": [ + { "time": 0.1333 }, + { "time": 0.2333, "x": 32.31, "y": 2.94 } + ] + }, + "gun": { + "rotate": [ + { "angle": 1.91 } + ], + "translate": [ + { "x": 7.95, "y": 5.85, "curve": 0, "c2": 0.3, "c3": 0.679 }, + { "time": 0.3, "x": -9.3, "y": -1.41 }, + { "time": 0.4 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": -30.47 } + ], + "translate": [ + { "curve": 0, "c2": 0.3, "c3": 0.679 }, + { "time": 0.3, "x": -6, "y": -3.72 }, + { "time": 0.4 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 62.31 } + ], + "translate": [ + { "curve": 0, "c2": 0.3, "c3": 0.679 }, + { "time": 0.3, "x": 2.81, "y": 11.42 }, + { "time": 0.4 } + ] + } + } + }, + "walk": { + "bones": { + "front-thigh": { + "rotate": [ + { "angle": 15.79 }, + { "time": 0.1, "angle": 27.4 }, + { "time": 0.2, "angle": -7.95 }, + { "time": 0.3, "angle": -16.95 }, + { "time": 0.4, "angle": -28.62 }, + { "time": 0.5, "angle": -19.31 }, + { "time": 0.6, "angle": -3.09 }, + { "time": 0.7, "angle": 29.52 }, + { "time": 0.8, "angle": 15.79 } + ], + "translate": [ + {}, + { "time": 0.4, "x": -1.19, "y": 0.55 }, + { "time": 0.5, "x": 0.12, "y": 0.41 }, + { "time": 0.6, "x": 9.49, "y": 0.27 }, + { "time": 0.8 } + ] + }, + "front-shin": { + "rotate": [ + { "angle": 5.13 }, + { "time": 0.1, "angle": -20.88 }, + { "time": 0.2, "angle": 13.37 }, + { "time": 0.3, "angle": 15.99 }, + { "time": 0.4, "angle": 5.95 }, + { "time": 0.5, "angle": -26.77 }, + { "time": 0.7, "angle": -55.44 }, + { "time": 0.8, "angle": 5.13 } + ] + }, + "rear-thigh": { + "rotate": [ + { "angle": -34.38 }, + { "time": 0.1, "angle": -30.33 }, + { "time": 0.2, "angle": -37.22 }, + { "time": 0.3, "angle": 20.73 }, + { "time": 0.4, "angle": 8.69 }, + { "time": 0.5, "angle": 12.16 }, + { "time": 0.6, "angle": -24.62 }, + { "time": 0.7, "angle": -27.27 }, + { "time": 0.8, "angle": -34.38 } + ], + "translate": [ + {}, + { "time": 0.4, "x": 4.09, "y": -9.53 }, + { "time": 0.5 }, + { "time": 0.7, "x": -21.14, "y": -9.61 }, + { "time": 0.8 } + ] + }, + "rear-shin": { + "rotate": [ + { "angle": 14.26 }, + { "time": 0.1, "angle": -17.3 }, + { "time": 0.2, "angle": -12.68 }, + { "time": 0.3, "angle": -58.9 }, + { "time": 0.4, "angle": 15.95 }, + { "time": 0.5, "angle": -9.01 }, + { "time": 0.6, "angle": 26.07 }, + { "time": 0.7, "angle": 21.86 }, + { "time": 0.8, "angle": 14.26 } + ], + "scale": [ + {}, + { "time": 0.1, "x": 0.952 }, + { "time": 0.5, "x": 0.976 }, + { "time": 0.8 } + ] + }, + "rear-foot": { + "rotate": [ + { "angle": 10.13 }, + { "time": 0.1, "angle": 12.28 }, + { "time": 0.2, "angle": -2.95 }, + { "time": 0.3, "angle": 6.29 }, + { "time": 0.4, "angle": 13.46 }, + { "time": 0.5, "angle": -3.57 }, + { "time": 0.6, "angle": -0.97 }, + { "time": 0.7, "angle": 2.98 }, + { "time": 0.8, "angle": 10.13 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "angle": -23.74 }, + { "time": 0.4, "angle": -320.57 }, + { "time": 0.8, "angle": -23.74 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 11.63 }, + { "time": 0.1, "angle": 19.37 }, + { "time": 0.4, "angle": 345.27 }, + { "time": 0.5, "angle": 343.44 }, + { "time": 0.8, "angle": 11.63 } + ] + }, + "torso": { + "rotate": [ + { "angle": -12.11 }, + { "time": 0.1667, "angle": -17.16 }, + { "time": 0.4, "angle": -12.11 }, + { "time": 0.5667, "angle": -15.81 }, + { "time": 0.8, "angle": -12.11 } + ] + }, + "neck": { + "rotate": [ + { "angle": 1.41 }, + { "time": 0.2333, "angle": -3.04 }, + { "time": 0.4, "angle": 1.41 }, + { "time": 0.6333, "angle": -3.04 }, + { "time": 0.8, "angle": 1.41 } + ] + }, + "head": { + "rotate": [ + { "angle": 6.98 }, + { "time": 0.1667, "angle": 8.02 }, + { "time": 0.2667, "angle": 12.65 }, + { "time": 0.4, "angle": 6.98 }, + { "time": 0.5667, "angle": 8.02 }, + { "time": 0.6667, "angle": 12.65 }, + { "time": 0.8, "angle": 6.98 } + ] + }, + "front-bracer": { + "rotate": [ + {}, + { "time": 0.4, "angle": 20.6 }, + { "time": 0.8 } + ] + }, + "front-foot": { + "rotate": [ + { "angle": 12.49 }, + { "time": 0.1, "angle": -6.36 }, + { "time": 0.2, "angle": -6.18 }, + { "time": 0.3, "angle": -0.76 }, + { "time": 0.3333, "angle": 3.89 }, + { "time": 0.4, "angle": 10.22 }, + { "time": 0.5, "angle": 11.44 }, + { "time": 0.6, "angle": -0.34 }, + { "time": 0.7, "angle": 0.15 }, + { "time": 0.8, "angle": 12.49 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": 3.59 }, + { "time": 0.1, "angle": 5.51 }, + { "time": 0.4, "angle": -22.78 }, + { "time": 0.5, "angle": -9.65 }, + { "time": 0.8, "angle": 3.59 } + ] + }, + "front-fist": { + "rotate": [ + { "angle": -15.22 }, + { "time": 0.1, "angle": -51.4 }, + { "time": 0.4, "angle": -39.4 }, + { "time": 0.5, "angle": 19.26 }, + { "time": 0.8, "angle": -15.22 } + ] + }, + "gun": { + "rotate": [ + { "angle": -24.07, "curve": 0.25, "c3": 0.75 }, + { "time": 0.1, "angle": -10.95, "curve": 0.381, "c2": 0.55, "c3": 0.742 }, + { "time": 0.4, "angle": 25.34, "curve": 0.25, "c3": 0.75 }, + { "time": 0.6667, "angle": -27.48, "curve": 0.25, "c3": 0.75 }, + { "time": 0.8, "angle": -24.07 } + ] + }, + "hip": { + "translate": [ + { "x": -23.93, "y": 3.22, "curve": 0.519, "c2": 0.04, "c3": 0.807, "c4": 0.61 }, + { "time": 0.1, "x": -23.93, "y": -3.36 }, + { "time": 0.1333, "x": -23.93, "y": 1.44 }, + { "time": 0.1667, "x": -23.93, "y": 2.88 }, + { "time": 0.2, "x": -23.93, "y": 0.99 }, + { "time": 0.3, "x": -23.93, "y": -3.5, "curve": 0.25, "c3": 0.75 }, + { "time": 0.4, "x": -23.93, "y": -2.5, "curve": 0.693, "c2": 0.02, "c3": 0.75 }, + { "time": 0.5, "x": -23.93, "y": -10.32, "curve": 0.236, "c2": 0.78, "c3": 0.75 }, + { + "time": 0.6, + "x": -23.93, + "y": 4.36, + "curve": 0.287, + "c2": 0.38, + "c3": 0.719, + "c4": 0.77 + }, + { "time": 0.7, "x": -23.93, "y": 10.35, "curve": 0.616, "c3": 0.75 }, + { "time": 0.8, "x": -23.93, "y": 3.22 } + ] + } + } + } +} +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-ess.skel b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-ess.skel new file mode 100644 index 0000000..c420c3d Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-ess.skel differ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-pma.atlas b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-pma.atlas new file mode 100644 index 0000000..513c074 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-pma.atlas @@ -0,0 +1,286 @@ + +spineboy-pma.png +size: 1024,256 +format: RGBA8888 +filter: Linear,Linear +repeat: none +crosshair + rotate: false + xy: 352, 7 + size: 45, 45 + orig: 45, 45 + offset: 0, 0 + index: -1 +eye-indifferent + rotate: false + xy: 862, 105 + size: 47, 45 + orig: 47, 45 + offset: 0, 0 + index: -1 +eye-surprised + rotate: false + xy: 505, 79 + size: 47, 45 + orig: 47, 45 + offset: 0, 0 + index: -1 +front-bracer + rotate: false + xy: 826, 66 + size: 29, 40 + orig: 29, 40 + offset: 0, 0 + index: -1 +front-fist-closed + rotate: false + xy: 786, 65 + size: 38, 41 + orig: 38, 41 + offset: 0, 0 + index: -1 +front-fist-open + rotate: true + xy: 710, 51 + size: 43, 44 + orig: 43, 44 + offset: 0, 0 + index: -1 +front-foot + rotate: false + xy: 210, 6 + size: 63, 35 + orig: 63, 35 + offset: 0, 0 + index: -1 +front-shin + rotate: true + xy: 665, 128 + size: 41, 92 + orig: 41, 92 + offset: 0, 0 + index: -1 +front-thigh + rotate: true + xy: 2, 2 + size: 23, 56 + orig: 23, 56 + offset: 0, 0 + index: -1 +front-upper-arm + rotate: false + xy: 250, 205 + size: 23, 49 + orig: 23, 49 + offset: 0, 0 + index: -1 +goggles + rotate: false + xy: 665, 171 + size: 131, 83 + orig: 131, 83 + offset: 0, 0 + index: -1 +gun + rotate: false + xy: 798, 152 + size: 105, 102 + orig: 105, 102 + offset: 0, 0 + index: -1 +head + rotate: false + xy: 2, 27 + size: 136, 149 + orig: 136, 149 + offset: 0, 0 + index: -1 +hoverboard-board + rotate: false + xy: 2, 178 + size: 246, 76 + orig: 246, 76 + offset: 0, 0 + index: -1 +hoverboard-thruster + rotate: true + xy: 722, 96 + size: 30, 32 + orig: 30, 32 + offset: 0, 0 + index: -1 +hoverglow-small + rotate: false + xy: 275, 81 + size: 137, 38 + orig: 137, 38 + offset: 0, 0 + index: -1 +mouth-grind + rotate: false + xy: 614, 97 + size: 47, 30 + orig: 47, 30 + offset: 0, 0 + index: -1 +mouth-oooo + rotate: false + xy: 612, 65 + size: 47, 30 + orig: 47, 30 + offset: 0, 0 + index: -1 +mouth-smile + rotate: false + xy: 661, 64 + size: 47, 30 + orig: 47, 30 + offset: 0, 0 + index: -1 +muzzle-glow + rotate: false + xy: 382, 54 + size: 25, 25 + orig: 25, 25 + offset: 0, 0 + index: -1 +muzzle-ring + rotate: true + xy: 275, 54 + size: 25, 105 + orig: 25, 105 + offset: 0, 0 + index: -1 +muzzle01 + rotate: true + xy: 911, 95 + size: 67, 40 + orig: 67, 40 + offset: 0, 0 + index: -1 +muzzle02 + rotate: false + xy: 792, 108 + size: 68, 42 + orig: 68, 42 + offset: 0, 0 + index: -1 +muzzle03 + rotate: true + xy: 956, 171 + size: 83, 53 + orig: 83, 53 + offset: 0, 0 + index: -1 +muzzle04 + rotate: false + xy: 275, 7 + size: 75, 45 + orig: 75, 45 + offset: 0, 0 + index: -1 +muzzle05 + rotate: false + xy: 140, 3 + size: 68, 38 + orig: 68, 38 + offset: 0, 0 + index: -1 +neck + rotate: false + xy: 250, 182 + size: 18, 21 + orig: 18, 21 + offset: 0, 0 + index: -1 +portal-bg + rotate: false + xy: 140, 43 + size: 133, 133 + orig: 133, 133 + offset: 0, 0 + index: -1 +portal-flare1 + rotate: false + xy: 554, 65 + size: 56, 30 + orig: 56, 30 + offset: 0, 0 + index: -1 +portal-flare2 + rotate: true + xy: 759, 112 + size: 57, 31 + orig: 57, 31 + offset: 0, 0 + index: -1 +portal-flare3 + rotate: false + xy: 554, 97 + size: 58, 30 + orig: 58, 30 + offset: 0, 0 + index: -1 +portal-shade + rotate: false + xy: 275, 121 + size: 133, 133 + orig: 133, 133 + offset: 0, 0 + index: -1 +portal-streaks1 + rotate: false + xy: 410, 126 + size: 126, 128 + orig: 126, 128 + offset: 0, 0 + index: -1 +portal-streaks2 + rotate: false + xy: 538, 129 + size: 125, 125 + orig: 125, 125 + offset: 0, 0 + index: -1 +rear-bracer + rotate: false + xy: 857, 67 + size: 28, 36 + orig: 28, 36 + offset: 0, 0 + index: -1 +rear-foot + rotate: false + xy: 663, 96 + size: 57, 30 + orig: 57, 30 + offset: 0, 0 + index: -1 +rear-shin + rotate: true + xy: 414, 86 + size: 38, 89 + orig: 38, 89 + offset: 0, 0 + index: -1 +rear-thigh + rotate: false + xy: 756, 63 + size: 28, 47 + orig: 28, 47 + offset: 0, 0 + index: -1 +rear-upper-arm + rotate: true + xy: 60, 5 + size: 20, 44 + orig: 20, 44 + offset: 0, 0 + index: -1 +torso + rotate: false + xy: 905, 164 + size: 49, 90 + orig: 49, 90 + offset: 0, 0 + index: -1 diff --git a/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-pma.png b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-pma.png new file mode 100644 index 0000000..067ea69 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-pma.png differ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-pro.json b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-pro.json new file mode 100644 index 0000000..aae987d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-pro.json @@ -0,0 +1,4304 @@ +{ +"skeleton": { + "hash": "LJppLyc3KtS7PVpP29XhA0jM8Lo", + "spine": "3.8.55", + "x": -190.66, + "y": -8, + "width": 419.84, + "height": 686.08, + "images": "./images/", + "audio": "" +}, +"bones": [ + { "name": "root", "rotation": 0.28 }, + { "name": "hip", "parent": "root", "y": 247.27 }, + { "name": "crosshair", "parent": "root", "x": 302.83, "y": 569.45, "color": "ff3f00ff" }, + { + "name": "aim-constraint-target", + "parent": "hip", + "length": 26.24, + "rotation": 19.61, + "x": 1.02, + "y": 5.62, + "color": "abe323ff" + }, + { "name": "rear-foot-target", "parent": "root", "x": 61.91, "y": 0.42, "color": "ff3f00ff" }, + { "name": "rear-leg-target", "parent": "rear-foot-target", "x": -33.91, "y": 37.34, "color": "ff3f00ff" }, + { + "name": "rear-thigh", + "parent": "hip", + "length": 85.72, + "rotation": -72.54, + "x": 8.91, + "y": -5.63, + "color": "ff000dff" + }, + { + "name": "rear-shin", + "parent": "rear-thigh", + "length": 121.88, + "rotation": -19.83, + "x": 86.1, + "y": -1.33, + "color": "ff000dff" + }, + { + "name": "rear-foot", + "parent": "rear-shin", + "length": 51.58, + "rotation": 45.78, + "x": 121.46, + "y": -0.76, + "color": "ff000dff" + }, + { + "name": "back-foot-tip", + "parent": "rear-foot", + "length": 50.3, + "rotation": -0.85, + "x": 51.17, + "y": 0.24, + "transform": "noRotationOrReflection", + "color": "ff000dff" + }, + { "name": "board-ik", "parent": "root", "x": -131.78, "y": 69.09, "color": "4c56ffff" }, + { "name": "clipping", "parent": "root" }, + { "name": "hoverboard-controller", "parent": "root", "rotation": -0.28, "x": -329.69, "y": 69.82, "color": "ff0004ff" }, + { "name": "exhaust1", "parent": "hoverboard-controller", "rotation": 3.02, "x": -249.68, "y": 53.39 }, + { "name": "exhaust2", "parent": "hoverboard-controller", "rotation": 26.34, "x": -191.6, "y": -22.92 }, + { + "name": "exhaust3", + "parent": "hoverboard-controller", + "rotation": -12.34, + "x": -236.03, + "y": 80.54, + "scaleX": 0.7847, + "scaleY": 0.7847 + }, + { "name": "portal-root", "parent": "root", "x": 12.9, "y": 328.54, "scaleX": 2.0334, "scaleY": 2.0334 }, + { "name": "flare1", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare10", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare2", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare3", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare4", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare5", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare6", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare7", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare8", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare9", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { + "name": "torso", + "parent": "hip", + "length": 42.52, + "rotation": 103.82, + "x": -1.62, + "y": 4.9, + "color": "e0da19ff" + }, + { "name": "torso2", "parent": "torso", "length": 42.52, "x": 42.52, "color": "e0da19ff" }, + { "name": "torso3", "parent": "torso2", "length": 42.52, "x": 42.52, "color": "e0da19ff" }, + { + "name": "front-upper-arm", + "parent": "torso3", + "length": 69.45, + "rotation": 168.38, + "x": 18.72, + "y": 19.33, + "color": "00ff04ff" + }, + { + "name": "front-bracer", + "parent": "front-upper-arm", + "length": 40.57, + "rotation": 18.3, + "x": 68.8, + "y": -0.68, + "color": "00ff04ff" + }, + { + "name": "front-fist", + "parent": "front-bracer", + "length": 65.39, + "rotation": 12.43, + "x": 40.57, + "y": 0.2, + "color": "00ff04ff" + }, + { "name": "front-foot-target", "parent": "root", "x": -13.53, "y": 0.04, "color": "ff3f00ff" }, + { "name": "front-leg-target", "parent": "front-foot-target", "x": -28.4, "y": 29.06, "color": "ff3f00ff" }, + { + "name": "front-thigh", + "parent": "hip", + "length": 74.81, + "rotation": -95.51, + "x": -17.46, + "y": -11.64, + "color": "00ff04ff" + }, + { + "name": "front-shin", + "parent": "front-thigh", + "length": 128.77, + "rotation": -2.21, + "x": 78.69, + "y": 1.6, + "color": "00ff04ff" + }, + { + "name": "front-foot", + "parent": "front-shin", + "length": 41.01, + "rotation": 51.27, + "x": 128.76, + "y": -0.34, + "color": "00ff04ff" + }, + { + "name": "front-foot-tip", + "parent": "front-foot", + "length": 56.03, + "rotation": -1.68, + "x": 41.42, + "y": -0.09, + "transform": "noRotationOrReflection", + "color": "00ff04ff" + }, + { + "name": "rear-upper-arm", + "parent": "torso3", + "length": 51.94, + "rotation": -169.56, + "x": 7.32, + "y": -19.22, + "color": "ff000dff" + }, + { "name": "rear-bracer", "parent": "rear-upper-arm", "length": 34.56, "rotation": 23.15, "x": 51.36, "color": "ff000dff" }, + { + "name": "gun", + "parent": "rear-bracer", + "length": 43.11, + "rotation": -5.43, + "x": 34.42, + "y": -0.45, + "color": "ff000dff" + }, + { "name": "gun-tip", "parent": "gun", "rotation": 7.1, "x": 200.78, "y": 52.5, "color": "ff0000ff" }, + { + "name": "neck", + "parent": "torso3", + "length": 25.45, + "rotation": -31.54, + "x": 42.46, + "y": -0.31, + "color": "e0da19ff" + }, + { + "name": "head", + "parent": "neck", + "length": 131.79, + "rotation": 26.1, + "x": 27.66, + "y": -0.26, + "color": "e0da19ff" + }, + { + "name": "hair1", + "parent": "head", + "length": 47.23, + "rotation": -49.1, + "x": 149.83, + "y": -59.77, + "color": "e0da19ff" + }, + { + "name": "hair2", + "parent": "hair1", + "length": 55.57, + "rotation": 50.42, + "x": 47.23, + "y": 0.19, + "color": "e0da19ff" + }, + { + "name": "hair3", + "parent": "head", + "length": 62.22, + "rotation": -32.17, + "x": 164.14, + "y": 3.68, + "color": "e0da19ff" + }, + { + "name": "hair4", + "parent": "hair3", + "length": 80.28, + "rotation": 83.71, + "x": 62.22, + "y": -0.04, + "color": "e0da19ff" + }, + { "name": "hoverboard-thruster-front", "parent": "hoverboard-controller", "rotation": -29.2, "x": 95.77, "y": -2.99, "transform": "noRotationOrReflection" }, + { "name": "hoverboard-thruster-rear", "parent": "hoverboard-controller", "rotation": -29.2, "x": -76.47, "y": -4.88, "transform": "noRotationOrReflection" }, + { "name": "hoverglow-front", "parent": "hoverboard-thruster-front", "rotation": 0.17, "x": -1.78, "y": -37.79 }, + { "name": "hoverglow-rear", "parent": "hoverboard-thruster-rear", "rotation": 0.17, "x": 1.06, "y": -35.66 }, + { "name": "muzzle", "parent": "rear-bracer", "rotation": 3.06, "x": 242.34, "y": 34.26, "color": "ffb900ff" }, + { "name": "muzzle-ring", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring2", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring3", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring4", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "portal", "parent": "portal-root" }, + { "name": "portal-shade", "parent": "portal-root" }, + { "name": "portal-streaks1", "parent": "portal-root" }, + { "name": "portal-streaks2", "parent": "portal-root" }, + { "name": "side-glow1", "parent": "hoverboard-controller", "x": -110.56, "y": 2.62, "color": "000effff" }, + { + "name": "side-glow2", + "parent": "hoverboard-controller", + "x": -110.56, + "y": 2.62, + "scaleX": 0.738, + "scaleY": 0.738, + "color": "000effff" + } +], +"slots": [ + { "name": "portal-bg", "bone": "portal" }, + { "name": "portal-shade", "bone": "portal-shade" }, + { "name": "portal-streaks2", "bone": "portal-streaks2", "blend": "additive" }, + { "name": "portal-streaks1", "bone": "portal-streaks1", "blend": "additive" }, + { "name": "portal-flare8", "bone": "flare8", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare9", "bone": "flare9", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare10", "bone": "flare10", "color": "c3cbffff", "blend": "additive" }, + { "name": "clipping", "bone": "clipping" }, + { "name": "exhaust3", "bone": "exhaust3", "color": "5eb4ffff", "blend": "additive" }, + { "name": "hoverboard-thruster-rear", "bone": "hoverboard-thruster-rear" }, + { "name": "hoverboard-thruster-front", "bone": "hoverboard-thruster-front" }, + { "name": "hoverboard-board", "bone": "hoverboard-controller" }, + { "name": "side-glow1", "bone": "side-glow1", "color": "ff8686ff", "blend": "additive" }, + { "name": "side-glow3", "bone": "side-glow1", "color": "ff8686ff", "blend": "additive" }, + { "name": "side-glow2", "bone": "side-glow2", "color": "ff8686ff", "blend": "additive" }, + { "name": "hoverglow-front", "bone": "hoverglow-front", "color": "5eb4ffff", "blend": "additive" }, + { "name": "hoverglow-rear", "bone": "hoverglow-rear", "color": "5eb4ffff", "blend": "additive" }, + { "name": "exhaust1", "bone": "exhaust2", "color": "5eb4ffff", "blend": "additive" }, + { "name": "exhaust2", "bone": "exhaust1", "color": "5eb4ffff", "blend": "additive" }, + { "name": "rear-upper-arm", "bone": "rear-upper-arm", "attachment": "rear-upper-arm" }, + { "name": "rear-bracer", "bone": "rear-bracer", "attachment": "rear-bracer" }, + { "name": "gun", "bone": "gun", "attachment": "gun" }, + { "name": "rear-foot", "bone": "rear-foot", "attachment": "rear-foot" }, + { "name": "rear-thigh", "bone": "rear-thigh", "attachment": "rear-thigh" }, + { "name": "rear-shin", "bone": "rear-shin", "attachment": "rear-shin" }, + { "name": "neck", "bone": "neck", "attachment": "neck" }, + { "name": "torso", "bone": "torso", "attachment": "torso" }, + { "name": "front-upper-arm", "bone": "front-upper-arm", "attachment": "front-upper-arm" }, + { "name": "head", "bone": "head", "attachment": "head" }, + { "name": "eye", "bone": "head", "attachment": "eye-indifferent" }, + { "name": "front-thigh", "bone": "front-thigh", "attachment": "front-thigh" }, + { "name": "front-foot", "bone": "front-foot", "attachment": "front-foot" }, + { "name": "front-shin", "bone": "front-shin", "attachment": "front-shin" }, + { "name": "mouth", "bone": "head", "attachment": "mouth-smile" }, + { "name": "goggles", "bone": "head", "attachment": "goggles" }, + { "name": "front-bracer", "bone": "front-bracer", "attachment": "front-bracer" }, + { "name": "front-fist", "bone": "front-fist", "attachment": "front-fist-closed" }, + { "name": "muzzle", "bone": "muzzle" }, + { "name": "head-bb", "bone": "head" }, + { "name": "portal-flare1", "bone": "flare1", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare2", "bone": "flare2", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare3", "bone": "flare3", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare4", "bone": "flare4", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare5", "bone": "flare5", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare6", "bone": "flare6", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare7", "bone": "flare7", "color": "c3cbffff", "blend": "additive" }, + { "name": "crosshair", "bone": "crosshair" }, + { "name": "muzzle-glow", "bone": "gun-tip", "color": "ffffff00", "blend": "additive" }, + { "name": "muzzle-ring", "bone": "muzzle-ring", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring2", "bone": "muzzle-ring2", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring3", "bone": "muzzle-ring3", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring4", "bone": "muzzle-ring4", "color": "d8baffff", "blend": "additive" } +], +"ik": [ + { + "name": "aim-ik", + "order": 12, + "bones": [ "rear-upper-arm" ], + "target": "crosshair", + "mix": 0 + }, + { + "name": "aim-torso-ik", + "order": 7, + "bones": [ "aim-constraint-target" ], + "target": "crosshair" + }, + { + "name": "board-ik", + "bones": [ "hoverboard-controller" ], + "target": "board-ik" + }, + { + "name": "front-foot-ik", + "order": 5, + "bones": [ "front-foot" ], + "target": "front-foot-target" + }, + { + "name": "front-leg-ik", + "order": 3, + "bones": [ "front-thigh", "front-shin" ], + "target": "front-leg-target", + "bendPositive": false + }, + { + "name": "rear-foot-ik", + "order": 6, + "bones": [ "rear-foot" ], + "target": "rear-foot-target" + }, + { + "name": "rear-leg-ik", + "order": 4, + "bones": [ "rear-thigh", "rear-shin" ], + "target": "rear-leg-target", + "bendPositive": false + } +], +"transform": [ + { + "name": "aim-front-arm-transform", + "order": 10, + "bones": [ "front-upper-arm" ], + "target": "aim-constraint-target", + "rotation": -180, + "rotateMix": 0, + "translateMix": 0, + "scaleMix": 0, + "shearMix": 0 + }, + { + "name": "aim-head-transform", + "order": 9, + "bones": [ "head" ], + "target": "aim-constraint-target", + "rotation": 84.3, + "rotateMix": 0, + "translateMix": 0, + "scaleMix": 0, + "shearMix": 0 + }, + { + "name": "aim-rear-arm-transform", + "order": 11, + "bones": [ "rear-upper-arm" ], + "target": "aim-constraint-target", + "x": 57.7, + "y": 56.4, + "rotateMix": 0, + "translateMix": 0, + "scaleMix": 0, + "shearMix": 0 + }, + { + "name": "aim-torso-transform", + "order": 8, + "bones": [ "torso" ], + "target": "aim-constraint-target", + "rotation": 69.5, + "shearY": -36, + "rotateMix": 0, + "translateMix": 0, + "scaleMix": 0, + "shearMix": 0 + }, + { + "name": "front-foot-board-transform", + "order": 1, + "bones": [ "front-foot-target" ], + "target": "hoverboard-controller", + "x": -69.8, + "y": 20.7, + "rotateMix": 0, + "translateMix": 0, + "scaleMix": 0, + "shearMix": 0 + }, + { + "name": "rear-foot-board-transform", + "order": 2, + "bones": [ "rear-foot-target" ], + "target": "hoverboard-controller", + "x": 86.6, + "y": 21.3, + "rotateMix": 0, + "translateMix": 0, + "scaleMix": 0, + "shearMix": 0 + }, + { + "name": "toes-board", + "order": 13, + "bones": [ "front-foot-tip", "back-foot-tip" ], + "target": "hoverboard-controller", + "rotateMix": 0, + "translateMix": 0, + "scaleMix": 0, + "shearMix": 0 + } +], +"skins": [ + { + "name": "default", + "attachments": { + "gun": { + "gun": { "x": 77.3, "y": 16.4, "rotation": 60.83, "width": 210, "height": 203 } + }, + "clipping": { + "clipping": { + "type": "clipping", + "end": "head-bb", + "vertexCount": 9, + "vertices": [ 66.76, 509.48, 19.98, 434.54, 5.34, 336.28, 22.19, 247.93, 77.98, 159.54, 182.21, -97.56, 1452.26, -99.8, 1454.33, 843.61, 166.57, 841.02 ], + "color": "ce3a3aff" + } + }, + "goggles": { + "goggles": { + "type": "mesh", + "uvs": [ 0.53653, 0.04114, 0.72922, 0.16036, 0.91667, 0.33223, 0.97046, 0.31329, 1, 0.48053, 0.95756, 0.5733, 0.88825, 0.6328, 0.86878, 0.78962, 0.77404, 0.8675, 0.72628, 1, 0.60714, 0.93863, 0.49601, 0.88138, 0.41558, 0.75027, 0.32547, 0.70084, 0.2782, 0.58257, 0.1721, 0.63281, 0.17229, 0.75071, 0.10781, 0.79898, 0, 0.32304, 0, 0.12476, 0.07373, 0.07344, 0.15423, 0.10734, 0.23165, 0.13994, 0.30313, 0.02256, 0.34802, 0, 0.42979, 0.69183, 0.39476, 0.51042, 0.39488, 0.31512, 0.45878, 0.23198, 0.56501, 0.28109, 0.69961, 0.39216, 0.82039, 0.54204, 0.85738, 0.62343, 0.91107, 0.51407, 0.72639, 0.32147, 0.58764, 0.19609, 0.48075, 0.11269, 0.37823, 0.05501, 0.3287, 0.17866, 0.319, 0.305, 0.36036, 0.53799, 0.40327, 0.70072, 0.30059, 0.55838, 0.21957, 0.2815, 0.09963, 0.28943, 0.56863, 0.4368, 0.4911, 0.37156, 0.51185, 0.52093, 0.67018, 0.59304, 0.7619, 0.68575, 0.73296, 0.43355 ], + "triangles": [ 49, 8, 48, 9, 48, 8, 12, 25, 11, 48, 9, 10, 47, 48, 10, 47, 10, 25, 25, 10, 11, 8, 49, 7, 17, 15, 16, 17, 18, 15, 49, 32, 7, 7, 32, 6, 41, 42, 40, 12, 41, 25, 41, 12, 42, 13, 14, 42, 12, 13, 42, 41, 40, 25, 40, 26, 25, 25, 26, 47, 49, 31, 32, 31, 49, 50, 18, 44, 15, 42, 14, 44, 14, 15, 44, 5, 6, 33, 6, 32, 33, 32, 31, 33, 47, 45, 48, 49, 48, 50, 50, 45, 30, 50, 48, 45, 42, 44, 43, 5, 33, 4, 42, 39, 40, 42, 43, 39, 31, 50, 33, 40, 39, 26, 45, 47, 46, 33, 2, 4, 2, 33, 34, 47, 26, 46, 26, 27, 46, 26, 39, 27, 2, 3, 4, 30, 45, 29, 30, 34, 50, 33, 50, 34, 45, 46, 29, 30, 29, 34, 27, 28, 46, 46, 28, 29, 18, 19, 44, 29, 35, 34, 2, 34, 1, 34, 35, 1, 28, 27, 38, 27, 39, 38, 39, 43, 38, 44, 19, 21, 44, 21, 43, 21, 19, 20, 43, 22, 38, 43, 21, 22, 29, 28, 35, 28, 36, 35, 28, 38, 36, 36, 0, 35, 35, 0, 1, 22, 23, 38, 38, 37, 36, 37, 23, 24, 37, 38, 23, 36, 37, 0, 37, 24, 0 ], + "vertices": [ 172.09, 22.81, 170.1, -31.19, 159.41, -86.8, 167.03, -99.01, 143.4, -115.48, 125.21, -110.14, 109.89, -96.35, 83.65, -100.19, 63.25, -81.16, 38.37, -76.69, 37.67, -43.98, 37.01, -13.47, 50.58, 13.55, 50.52, 38.45, 64.95, 56.6, 47.9, 79.96, 29.45, 73.42, 16.31, 86.64, 81.51, 139.38, 112.56, 150.3, 126.97, 134.97, 128.63, 113.28, 130.23, 92.43, 154.79, 81.29, 162.21, 71.48, 60.96, 13.27, 86.33, 31.88, 116.93, 42.6, 135.47, 31.44, 136.98, 2.59, 131.23, -36.66, 118.22, -74.65, 108.69, -88.24, 130.46, -95.44, 144.63, -39.36, 152.25, 1.7, 156.06, 32.6, 156.22, 61.02, 132.57, 66.41, 111.94, 61.84, 79.04, 38.83, 57.27, 19.31, 70.67, 52.42, 107.02, 87.61, 95.4, 116.7, 112.91, -6.87, 116.42, 15.8, 94.82, 2.47, 97.24, -40.48, 90.66, -68.16, 127.65, -47.15 ], + "hull": 25, + "edges": [ 36, 34, 34, 32, 32, 30, 30, 28, 28, 26, 26, 24, 24, 22, 18, 16, 16, 14, 14, 12, 12, 10, 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 48, 48, 46, 46, 44, 36, 38, 40, 38, 24, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 62, 64, 64, 12, 8, 66, 66, 68, 68, 70, 70, 72, 72, 74, 74, 76, 76, 78, 78, 80, 80, 82, 82, 24, 24, 84, 84, 86, 86, 44, 40, 42, 42, 44, 42, 88, 88, 30, 58, 90, 90, 92, 92, 94, 18, 20, 20, 22, 94, 20, 18, 96, 96, 98, 60, 100, 100, 62, 98, 100 ], + "width": 261, + "height": 166 + } + }, + "head": { + "head": { + "type": "mesh", + "uvs": [ 0.75919, 0.06107, 0.88392, 0.17893, 0.90174, 0.30856, 0.94224, 0.1966, 1, 0.26584, 1, 0.422, 0.95864, 0.46993, 0.92118, 0.51333, 0.85957, 0.5347, 0.78388, 0.65605, 0.74384, 0.74838, 0.85116, 0.75151, 0.84828, 0.82564, 0.81781, 0.85367, 0.75599, 0.85906, 0.76237, 0.90468, 0.65875, 1, 0.38337, 1, 0.1858, 0.85404, 0.12742, 0.81091, 0.06025, 0.69209, 0, 0.58552, 0, 0.41021, 0.0853, 0.20692, 0.24243, 0.14504, 0.5, 0.1421, 0.50324, 0.07433, 0.41738, 0, 0.57614, 0, 0.85059, 0.36087, 0.73431, 0.43206, 0.68481, 0.31271, 0.72165, 0.16718, 0.55931, 0.04154, 0.44764, 0.22895, 0.23926, 0.26559, 0.71272, 0.44036, 0.56993, 0.383, 0.41678, 0.33511, 0.293, 0.31497, 0.70802, 0.44502, 0.56676, 0.38976, 0.41521, 0.34416, 0.28754, 0.33017, 0.88988, 0.50177, 0.30389, 0.73463, 0.2646, 0.65675, 0.21414, 0.61584, 0.14613, 0.62194, 0.10316, 0.66636, 0.10358, 0.72557, 0.14505, 0.79164, 0.20263, 0.81355, 0.27873, 0.80159, 0.34947, 0.7376, 0.23073, 0.57073, 0.08878, 0.60707, 0.29461, 0.8129, 0.73006, 0.87883, 0.69805, 0.87348, 0.66166, 0.79681 ], + "triangles": [ 34, 25, 31, 37, 38, 34, 31, 32, 29, 31, 37, 34, 37, 41, 38, 30, 31, 29, 36, 37, 31, 33, 27, 28, 26, 27, 33, 0, 33, 28, 32, 33, 0, 32, 0, 1, 33, 25, 26, 33, 32, 25, 31, 25, 32, 2, 32, 1, 2, 3, 4, 2, 29, 32, 2, 4, 5, 29, 2, 5, 6, 29, 5, 30, 36, 31, 30, 29, 6, 44, 30, 6, 36, 30, 44, 34, 24, 25, 35, 23, 24, 35, 24, 34, 39, 35, 34, 39, 22, 35, 38, 39, 34, 42, 39, 38, 43, 39, 42, 41, 42, 38, 22, 23, 35, 43, 22, 39, 40, 37, 36, 41, 37, 40, 7, 44, 6, 8, 36, 44, 40, 36, 8, 8, 44, 7, 55, 22, 43, 56, 21, 22, 55, 56, 22, 55, 48, 56, 47, 48, 55, 9, 40, 8, 55, 54, 46, 42, 55, 43, 47, 55, 46, 49, 56, 48, 20, 21, 56, 20, 56, 49, 50, 49, 48, 20, 49, 50, 46, 54, 45, 54, 55, 41, 55, 42, 41, 9, 60, 40, 46, 51, 50, 60, 41, 40, 10, 60, 9, 54, 41, 60, 46, 52, 51, 19, 50, 51, 50, 48, 47, 47, 46, 50, 46, 45, 52, 20, 50, 19, 57, 53, 45, 57, 45, 54, 53, 52, 45, 12, 10, 11, 13, 10, 12, 18, 51, 52, 19, 51, 18, 18, 52, 53, 18, 53, 57, 14, 10, 13, 60, 10, 14, 59, 60, 14, 58, 59, 14, 58, 14, 15, 17, 54, 60, 16, 17, 60, 57, 54, 17, 18, 57, 17, 59, 16, 60, 16, 59, 58, 16, 58, 15 ], + "vertices": [ 1, 48, 41.97, -41.8, 1, 3, 46, 73.47, 27.55, 0.18925, 48, -5.75, -51.71, 0.72419, 47, 112.98, -11.43, 0.08656, 3, 46, 38.23, 10.99, 0.84284, 48, -41.02, -35.22, 0.09706, 47, 92.72, -44.68, 0.06011, 1, 46, 73.36, 10.89, 1, 1, 46, 58.59, -10.38, 1, 2, 45, 75.49, -4.56, 0.10258, 46, 14.36, -24.8, 0.89742, 2, 45, 59.82, -13.73, 0.41734, 46, -2.7, -18.57, 0.58266, 1, 44, 163.07, -108.68, 1, 1, 44, 151.52, -95.05, 1, 1, 44, 110.61, -87.69, 1, 1, 44, 81.05, -86.58, 1, 1, 44, 89.82, -114.32, 1, 1, 44, 68.72, -120.91, 1, 1, 44, 58.1, -115.89, 1, 1, 44, 51.03, -100.63, 1, 1, 44, 38.79, -106.76, 1, 1, 44, 2.68, -89.7, 1, 1, 44, -22.07, -19.3, 1, 1, 44, 1.2, 45.63, 1, 1, 44, 8.07, 64.82, 1, 1, 44, 35.44, 93.73, 1, 1, 44, 59.98, 119.66, 1, 1, 44, 109.26, 136.99, 1, 1, 44, 174.07, 135.27, 1, 2, 44, 205.59, 101.22, 0.83763, 47, -16.8, 104.64, 0.16237, 2, 48, 58.94, 30.5, 0.60736, 47, 38.37, 61.9, 0.39264, 1, 48, 75.56, 19.01, 1, 1, 48, 106.7, 26.9, 1, 1, 48, 83.79, -9.51, 1, 4, 45, 44.52, 27.24, 0.19601, 46, 19.12, 19.33, 0.58067, 48, -46.83, -15.19, 0.07455, 47, 72.17, -48.25, 0.14877, 2, 45, 7.42, 19.08, 0.79203, 47, 34.31, -45.25, 0.20797, 1, 47, 45.94, -9.06, 1, 1, 48, 20.62, -16.35, 1, 1, 48, 75.74, 0.94, 1, 3, 44, 200.44, 40.47, 0.4822, 48, 44.59, 56.29, 0.1495, 47, 11.17, 50.47, 0.3683, 1, 44, 171.41, 90.12, 1, 2, 45, 1.07, 18.93, 0.79203, 47, 28.19, -43.54, 0.20797, 3, 44, 168.13, -6.01, 0.11484, 45, -28.64, 49.04, 0.13133, 47, 8.54, -6.09, 0.75382, 2, 44, 167.83, 37.87, 0.27101, 47, -15.06, 30.91, 0.72899, 1, 44, 162.36, 71.5, 1, 1, 44, 163.11, -47.44, 1, 1, 44, 165.94, -5.87, 1, 1, 44, 165.14, 37.38, 1, 1, 44, 157.6, 71.4, 1, 1, 44, 163.5, -99.54, 1, 1, 44, 45.38, 27.24, 1, 1, 44, 63.74, 44.98, 1, 1, 44, 70.7, 61.93, 1, 1, 44, 62.88, 78.71, 1, 1, 44, 46.53, 85.3, 1, 1, 44, 29.92, 79.34, 1, 1, 44, 15.08, 62.21, 1, 1, 44, 14.09, 45.33, 1, 1, 44, 24.3, 27.06, 1, 1, 44, 48.64, 15.3, 1, 1, 44, 84.87, 62.14, 1, 1, 44, 61.9, 94.84, 1, 1, 44, 22.54, 21.88, 1, 1, 44, 43.15, -95.95, 1, 1, 44, 41.77, -87.24, 1, 1, 44, 60.05, -70.36, 1 ], + "hull": 29, + "edges": [ 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 56, 54, 56, 54, 52, 52, 50, 50, 48, 48, 46, 46, 44, 42, 44, 32, 34, 4, 58, 58, 60, 62, 64, 64, 66, 66, 54, 50, 68, 68, 70, 70, 44, 60, 72, 62, 74, 72, 74, 74, 76, 76, 78, 78, 44, 16, 80, 80, 82, 82, 84, 84, 86, 86, 44, 14, 88, 88, 72, 14, 16, 10, 12, 12, 14, 12, 60, 90, 92, 92, 94, 94, 96, 96, 98, 98, 100, 100, 102, 102, 104, 104, 106, 106, 90, 108, 110, 110, 112, 38, 40, 40, 42, 112, 40, 34, 36, 36, 38, 36, 114, 114, 108, 30, 32, 30, 28, 24, 26, 28, 26, 22, 24, 22, 20, 20, 18, 18, 16, 28, 116, 116, 118, 118, 120, 120, 20 ], + "width": 271, + "height": 298 + } + }, + "portal-flare10": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-bg": { + "portal-bg": { "x": -3.1, "y": 7.25, "scaleX": 1.0492, "scaleY": 1.0492, "width": 266, "height": 266 } + }, + "mouth": { + "mouth-grind": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 11.28, -85.88, -19.56, 1.84, 36.09, 21.41, 66.93, -66.32 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + }, + "mouth-oooo": { "x": 23.69, "y": -32.24, "rotation": -70.63, "width": 93, "height": 59 }, + "mouth-smile": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 11.28, -85.89, -19.56, 1.85, 36.1, 21.42, 66.94, -66.32 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + } + }, + "head-bb": { + "head": { + "type": "boundingbox", + "vertexCount": 6, + "vertices": [ -19.14, -70.3, 40.8, -118.08, 257.78, -115.62, 285.17, 57.18, 120.77, 164.95, -5.07, 76.95 ] + } + }, + "exhaust3": { + "hoverglow-small": { "scaleX": 0.4629, "scaleY": 0.8129, "rotation": -83.07, "width": 274, "height": 75 } + }, + "portal-shade": { + "portal-shade": { "width": 266, "height": 266 } + }, + "front-upper-arm": { + "front-upper-arm": { "x": 28.31, "y": 7.37, "rotation": 97.9, "width": 46, "height": 97 } + }, + "hoverboard-thruster-rear": { + "hoverboard-thruster": { "x": 1.1, "y": -6.29, "rotation": 0.17, "width": 60, "height": 64 } + }, + "side-glow2": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.2353, "scaleY": 0.4132, "width": 274, "height": 75 } + }, + "hoverboard-thruster-front": { + "hoverboard-thruster": { "x": 0.02, "y": -7.08, "rotation": 0.17, "width": 60, "height": 64 } + }, + "front-foot": { + "front-foot": { + "type": "mesh", + "uvs": [ 0.59417, 0.23422, 0.62257, 0.30336, 0.6501, 0.37036, 0.67637, 0.38404, 0.72068, 0.4071, 0.76264, 0.42894, 1, 0.70375, 1, 1, 0.65517, 1, 0.46923, 0.99999, 0, 1, 0, 0.39197, 0.17846, 0, 0.49796, 0 ], + "triangles": [ 8, 9, 3, 4, 8, 3, 5, 8, 4, 6, 8, 5, 8, 6, 7, 11, 1, 10, 0, 12, 13, 0, 11, 12, 0, 1, 11, 9, 2, 3, 1, 2, 10, 9, 10, 2 ], + "vertices": [ 2, 37, 18.17, 41.57, 0.7896, 38, 12.46, 46.05, 0.2104, 2, 37, 24.08, 40.76, 0.71228, 38, 16.12, 41.34, 0.28772, 2, 37, 29.81, 39.98, 0.55344, 38, 19.67, 36.78, 0.44656, 2, 37, 32.81, 41.67, 0.38554, 38, 23, 35.89, 0.61446, 2, 37, 37.86, 44.52, 0.25567, 38, 28.61, 34.4, 0.74433, 2, 37, 42.65, 47.22, 0.17384, 38, 33.92, 32.99, 0.82616, 1, 38, 64.15, 14.56, 1, 1, 38, 64.51, -5.87, 1, 1, 38, 21.08, -6.64, 1, 2, 37, 44.67, -6.77, 0.5684, 38, -2.34, -6.97, 0.4316, 1, 37, 3.1, -48.81, 1, 1, 37, -26.73, -19.31, 1, 1, 37, -30.15, 15.69, 1, 1, 37, -1.84, 44.32, 1 ], + "hull": 14, + "edges": [ 14, 16, 16, 18, 18, 20, 4, 18, 20, 22, 24, 26, 22, 24, 12, 14, 10, 12, 2, 4, 2, 20, 4, 6, 6, 16, 2, 0, 0, 26, 6, 8, 8, 10 ], + "width": 126, + "height": 69 + } + }, + "rear-foot": { + "rear-foot": { + "type": "mesh", + "uvs": [ 0.48368, 0.1387, 0.51991, 0.21424, 0.551, 0.27907, 0.58838, 0.29816, 0.63489, 0.32191, 0.77342, 0.39267, 1, 0.73347, 1, 1, 0.54831, 0.99883, 0.31161, 1, 0, 1, 0, 0.41397, 0.13631, 0, 0.41717, 0 ], + "triangles": [ 8, 3, 4, 8, 4, 5, 8, 5, 6, 8, 6, 7, 11, 1, 10, 3, 9, 2, 2, 10, 1, 12, 13, 0, 0, 11, 12, 1, 11, 0, 2, 9, 10, 3, 8, 9 ], + "vertices": [ 2, 8, 10.45, 29.41, 0.90802, 9, -6.74, 49.62, 0.09198, 2, 8, 16.56, 29.27, 0.84259, 9, -2.65, 45.09, 0.15741, 2, 8, 21.8, 29.15, 0.69807, 9, 0.85, 41.2, 0.30193, 2, 8, 25.53, 31.43, 0.52955, 9, 5.08, 40.05, 0.47045, 2, 8, 30.18, 34.27, 0.39303, 9, 10.33, 38.62, 0.60697, 2, 8, 44.02, 42.73, 0.27525, 9, 25.98, 34.36, 0.72475, 2, 8, 76.47, 47.28, 0.21597, 9, 51.56, 13.9, 0.78403, 2, 8, 88.09, 36.29, 0.28719, 9, 51.55, -2.09, 0.71281, 2, 8, 52.94, -0.73, 0.47576, 9, 0.52, -1.98, 0.52424, 2, 8, 34.63, -20.23, 0.68757, 9, -26.23, -2.03, 0.31243, 2, 8, 10.44, -45.81, 0.84141, 9, -61.43, -2, 0.15859, 2, 8, -15.11, -21.64, 0.93283, 9, -61.4, 33.15, 0.06717, 1, 8, -22.57, 6.61, 1, 1, 8, -0.76, 29.67, 1 ], + "hull": 14, + "edges": [ 14, 12, 10, 12, 14, 16, 16, 18, 18, 20, 4, 18, 20, 22, 24, 26, 22, 24, 4, 2, 2, 20, 4, 6, 6, 16, 6, 8, 8, 10, 2, 0, 0, 26 ], + "width": 113, + "height": 60 + } + }, + "muzzle-ring2": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "muzzle-ring3": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "portal-flare5": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "side-glow3": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.3586, "scaleY": 0.6297, "width": 274, "height": 75 } + }, + "rear-upper-arm": { + "rear-upper-arm": { "x": 21.13, "y": 4.09, "rotation": 89.33, "width": 40, "height": 87 } + }, + "muzzle-ring": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "portal-streaks1": { + "portal-streaks1": { "scaleX": 0.9774, "scaleY": 0.9774, "width": 252, "height": 256 } + }, + "portal-streaks2": { + "portal-streaks2": { "x": -1.64, "y": 2.79, "width": 250, "height": 249 } + }, + "portal-flare2": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare1": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "muzzle": { + "muzzle01": { + "x": 151.97, + "y": 5.81, + "scaleX": 3.7361, + "scaleY": 3.7361, + "rotation": 0.15, + "width": 133, + "height": 79 + }, + "muzzle02": { + "x": 187.25, + "y": 5.9, + "scaleX": 4.0623, + "scaleY": 4.0623, + "rotation": 0.15, + "width": 135, + "height": 84 + }, + "muzzle03": { + "x": 231.96, + "y": 6.02, + "scaleX": 4.1325, + "scaleY": 4.1325, + "rotation": 0.15, + "width": 166, + "height": 106 + }, + "muzzle04": { + "x": 231.96, + "y": 6.02, + "scaleX": 4.0046, + "scaleY": 4.0046, + "rotation": 0.15, + "width": 149, + "height": 90 + }, + "muzzle05": { + "x": 293.8, + "y": 6.19, + "scaleX": 4.4673, + "scaleY": 4.4673, + "rotation": 0.15, + "width": 135, + "height": 75 + } + }, + "crosshair": { + "crosshair": { "width": 89, "height": 89 } + }, + "exhaust1": { + "hoverglow-small": { "scaleX": 0.4629, "scaleY": 0.8129, "rotation": -83.07, "width": 274, "height": 75 } + }, + "rear-bracer": { + "rear-bracer": { "x": 11.15, "y": -2.2, "rotation": 66.17, "width": 56, "height": 72 } + }, + "hoverglow-front": { + "hoverglow-small": { + "x": 2.13, + "y": -2, + "scaleX": 0.303, + "scaleY": 0.495, + "rotation": 0.15, + "width": 274, + "height": 75 + } + }, + "portal-flare3": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "muzzle-ring4": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "hoverglow-rear": { + "hoverglow-small": { + "x": 1.39, + "y": -2.09, + "scaleX": 0.303, + "scaleY": 0.495, + "rotation": 0.61, + "width": 274, + "height": 75 + } + }, + "portal-flare6": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare7": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare8": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare9": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "rear-thigh": { + "rear-thigh": { "x": 33.11, "y": -4.11, "rotation": 72.54, "width": 55, "height": 94 } + }, + "portal-flare4": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "neck": { + "neck": { "x": 9.77, "y": -3.01, "rotation": -55.22, "width": 36, "height": 41 } + }, + "front-shin": { + "front-shin": { + "type": "mesh", + "uvs": [ 0.90031, 0.05785, 1, 0.12828, 1, 0.21619, 0.9025, 0.31002, 0.78736, 0.35684, 0.78081, 0.39874, 0.77215, 0.45415, 0.77098, 0.51572, 0.84094, 0.63751, 0.93095, 0.7491, 0.95531, 0.7793, 0.78126, 0.87679, 0.5613, 1, 0.2687, 1, 0, 1, 0.00279, 0.96112, 0.01358, 0.81038, 0.02822, 0.60605, 0.08324, 0.45142, 0.18908, 0.31882, 0.29577, 0.2398, 0.30236, 0.14941, 0.37875, 0.05902, 0.53284, 0, 0.70538, 0, 0.41094, 0.71968, 0.40743, 0.54751, 0.41094, 0.4536, 0.4724, 0.35186, 0.33367, 0.27829, 0.50226, 0.31664, 0.65328, 0.67507, 0.60762, 0.52716, 0.6006, 0.45125, 0.62747, 0.37543, 0.6573, 0.3385, 0.27843, 0.32924, 0.18967, 0.45203, 0.16509, 0.58586, 0.18265, 0.7682, 0.50532, 0.24634, 0.59473, 0.17967, 0.60161, 0.10611, 0.51392, 0.04327, 0.72198, 0.28849, 0.82343, 0.20266, 0.86814, 0.11377, 0.79592, 0.04634, 0.44858, 0.15515, 0.25466, 0.96219, 0.53169, 0.9448, 0.7531, 0.8324 ], + "triangles": [ 24, 0, 47, 43, 23, 24, 47, 43, 24, 43, 22, 23, 42, 43, 47, 46, 47, 0, 42, 47, 46, 46, 0, 1, 48, 22, 43, 48, 43, 42, 21, 22, 48, 41, 48, 42, 45, 42, 46, 41, 42, 45, 46, 1, 2, 45, 46, 2, 40, 48, 41, 48, 20, 21, 29, 48, 40, 29, 20, 48, 44, 41, 45, 40, 41, 44, 3, 45, 2, 44, 45, 3, 30, 29, 40, 35, 30, 40, 36, 19, 20, 36, 20, 29, 44, 35, 40, 28, 29, 30, 4, 44, 3, 35, 44, 4, 34, 30, 35, 5, 35, 4, 34, 28, 30, 33, 28, 34, 37, 19, 36, 18, 19, 37, 27, 29, 28, 27, 28, 33, 36, 29, 27, 37, 36, 27, 5, 34, 35, 6, 34, 5, 33, 34, 6, 6, 32, 33, 7, 32, 6, 26, 37, 27, 38, 18, 37, 38, 37, 26, 17, 18, 38, 31, 32, 7, 31, 7, 8, 32, 25, 26, 38, 26, 25, 27, 33, 32, 32, 26, 27, 39, 38, 25, 17, 38, 39, 16, 17, 39, 51, 31, 8, 51, 8, 9, 11, 51, 9, 11, 9, 10, 31, 50, 25, 31, 25, 32, 50, 31, 51, 49, 39, 25, 49, 25, 50, 15, 16, 39, 49, 15, 39, 13, 49, 50, 14, 15, 49, 13, 14, 49, 12, 50, 51, 12, 51, 11, 13, 50, 12 ], + "vertices": [ -23.66, 19.37, -11.73, 28.98, 4.34, 30.83, 22.41, 24.87, 32.05, 16.48, 39.77, 16.83, 49.98, 17.3, 61.25, 18.5, 82.85, 26.78, 102.4, 36.46, 107.69, 39.09, 127.15, 26.97, 151.74, 11.65, 154.49, -12.18, 157.02, -34.07, 149.89, -34.66, 122.23, -36.97, 84.75, -40.09, 55.97, -38.88, 30.73, -33.05, 15.29, -26.03, -1.3, -27.41, -18.54, -23.09, -30.78, -11.79, -32.4, 2.27, 101.92, -6.52, 70.48, -10.44, 53.28, -12.14, 34.11, -9.28, 21.96, -22.13, 27.39, -7.59, 91.48, 12.28, 64.88, 5.44, 51.07, 3.26, 36.95, 3.85, 29.92, 5.5, 31.8, -25.56, 55.08, -30.19, 79.77, -29.37, 112.93, -24.09, 14.51, -8.83, 1.48, -2.95, -12.03, -3.94, -22.69, -12.41, 20.17, 9.71, 3.53, 16.16, -13.14, 17.93, -24.78, 10.62, -1.62, -15.37, 147.71, -14.13, 141.93, 8.07, 119.3, 23.74 ], + "hull": 25, + "edges": [ 8, 6, 6, 4, 4, 2, 2, 0, 0, 48, 46, 48, 46, 44, 44, 42, 42, 40, 40, 38, 38, 36, 36, 34, 32, 34, 50, 52, 52, 54, 54, 56, 40, 58, 58, 60, 8, 10, 20, 22, 22, 24, 62, 64, 64, 66, 66, 68, 8, 70, 70, 60, 68, 70, 58, 72, 72, 74, 74, 76, 76, 78, 24, 26, 26, 28, 58, 80, 80, 82, 82, 84, 84, 86, 86, 44, 70, 88, 88, 90, 90, 92, 92, 94, 94, 48, 80, 88, 88, 6, 82, 90, 90, 4, 84, 92, 92, 2, 86, 94, 94, 0, 56, 60, 10, 12, 12, 14, 14, 16, 28, 30, 30, 32, 26, 98, 98, 78, 30, 98, 24, 100, 100, 50, 98, 100, 22, 102, 102, 62, 100, 102, 16, 18, 18, 20, 102, 18 ], + "width": 82, + "height": 184 + } + }, + "eye": { + "eye-indifferent": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 73.41, -91.35, 23.16, -13.11, 98.03, 34.99, 148.28, -43.25 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 89 + }, + "eye-surprised": { "x": 85.72, "y": -28.18, "rotation": -70.63, "width": 93, "height": 89 } + }, + "side-glow1": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.2353, "scaleY": 0.4132, "width": 274, "height": 75 } + }, + "torso": { + "torso": { + "type": "mesh", + "uvs": [ 0.6251, 0.12672, 1, 0.26361, 1, 0.28871, 1, 0.66021, 1, 0.68245, 0.92324, 0.69259, 0.95116, 0.84965, 0.77124, 1, 0.49655, 1, 0.27181, 1, 0.13842, 0.77196, 0.09886, 0.6817, 0.05635, 0.58471, 0, 0.45614, 0, 0.33778, 0, 0.19436, 0.14463, 0, 0.27802, 0, 0.72525, 0.27835, 0.76091, 0.46216, 0.84888, 0.67963, 0.68257, 0.63249, 0.53986, 0.3847, 0.25443, 0.3217, 0.30063, 0.55174, 0.39553, 0.79507, 0.26389, 0.17007, 0.5241, 0.18674, 0.71492, 0.76655, 0.82151, 0.72956, 0.27626, 0.4304, 0.62327, 0.52952, 0.3455, 0.66679, 0.53243, 0.2914 ], + "triangles": [ 19, 18, 2, 13, 14, 23, 23, 33, 22, 22, 33, 18, 14, 15, 23, 33, 26, 27, 33, 23, 26, 23, 15, 26, 33, 27, 18, 18, 1, 2, 27, 0, 18, 18, 0, 1, 15, 16, 26, 0, 27, 17, 17, 27, 16, 27, 26, 16, 11, 24, 32, 11, 12, 24, 3, 20, 19, 32, 31, 21, 32, 24, 31, 19, 2, 3, 21, 31, 19, 12, 30, 24, 12, 13, 30, 24, 22, 31, 24, 30, 22, 31, 22, 19, 22, 18, 19, 13, 23, 30, 30, 23, 22, 8, 28, 7, 7, 29, 6, 7, 28, 29, 9, 25, 8, 8, 25, 28, 9, 10, 25, 29, 5, 6, 10, 32, 25, 25, 21, 28, 25, 32, 21, 10, 11, 32, 28, 21, 29, 29, 20, 5, 29, 21, 20, 4, 5, 3, 5, 20, 3, 20, 21, 19 ], + "vertices": [ 1, 29, 44.59, -10.39, 1, 2, 28, 59.65, -45.08, 0.31254, 29, 17.13, -45.08, 0.68746, 2, 28, 55.15, -44.72, 0.34488, 29, 12.63, -44.72, 0.65512, 2, 27, 31.01, -39.45, 0.62357, 28, -11.51, -39.45, 0.37643, 2, 27, 27.01, -39.14, 0.65234, 28, -15.5, -39.14, 0.34766, 2, 27, 25.79, -31.5, 0.75532, 28, -16.73, -31.5, 0.24468, 1, 27, -2.61, -32, 1, 1, 27, -28.2, -12.29, 1, 1, 27, -26.08, 14.55, 1, 1, 27, -24.35, 36.5, 1, 2, 27, 17.6, 46.3, 0.8332, 28, -24.92, 46.3, 0.1668, 2, 27, 34.1, 48.89, 0.59943, 28, -8.42, 48.89, 0.40058, 3, 27, 51.83, 51.67, 0.29262, 28, 9.32, 51.67, 0.63181, 29, -33.2, 51.67, 0.07557, 3, 27, 75.34, 55.35, 0.06656, 28, 32.82, 55.35, 0.62298, 29, -9.7, 55.35, 0.31046, 2, 28, 54.06, 53.67, 0.37296, 29, 11.54, 53.67, 0.62704, 2, 28, 79.79, 51.64, 0.10373, 29, 37.27, 51.64, 0.89627, 1, 29, 71.04, 34.76, 1, 1, 29, 70.01, 21.72, 1, 2, 28, 59.13, -18.02, 0.12067, 29, 16.61, -18.02, 0.87933, 2, 28, 25.87, -18.9, 0.91272, 29, -16.65, -18.9, 0.08728, 2, 27, 28.69, -24.42, 0.77602, 28, -13.83, -24.42, 0.22398, 2, 27, 38.43, -8.84, 0.7254, 28, -4.09, -8.84, 0.2746, 2, 28, 41.48, 1.59, 0.75167, 29, -1.04, 1.59, 0.24833, 2, 28, 54.98, 28.59, 0.27889, 29, 12.46, 28.59, 0.72111, 2, 27, 55.87, 27.33, 0.21124, 28, 13.35, 27.33, 0.78876, 1, 27, 11.47, 21.51, 1, 1, 29, 39.6, 25.51, 1, 1, 29, 34.6, 0.33, 1, 1, 27, 14.12, -10.1, 1, 2, 27, 19.94, -21.03, 0.92029, 28, -22.58, -21.03, 0.07971, 2, 28, 35.31, 27.99, 0.69833, 29, -7.21, 27.99, 0.30167, 1, 28, 14.84, -4.5, 1, 2, 27, 34.87, 24.58, 0.67349, 28, -7.64, 24.58, 0.32651, 1, 29, 15.76, 1, 1 ], + "hull": 18, + "edges": [ 14, 12, 12, 10, 10, 8, 18, 20, 32, 34, 30, 32, 2, 4, 36, 4, 36, 38, 38, 40, 4, 6, 6, 8, 40, 6, 40, 42, 14, 16, 16, 18, 50, 16, 46, 52, 54, 36, 2, 0, 0, 34, 54, 0, 54, 32, 20, 50, 14, 56, 56, 42, 50, 56, 56, 58, 58, 40, 58, 10, 46, 60, 60, 48, 26, 60, 60, 44, 24, 26, 24, 48, 42, 62, 62, 44, 48, 62, 48, 64, 64, 50, 42, 64, 20, 22, 22, 24, 64, 22, 26, 28, 28, 30, 28, 46, 44, 66, 66, 54, 46, 66, 66, 36, 62, 38 ], + "width": 98, + "height": 180 + } + }, + "exhaust2": { + "hoverglow-small": { + "x": 0.01, + "y": -0.76, + "scaleX": 0.4208, + "scaleY": 0.8403, + "rotation": -89.25, + "width": 274, + "height": 75 + } + }, + "rear-shin": { + "rear-shin": { "x": 58.29, "y": -2.75, "rotation": 92.37, "width": 75, "height": 178 } + }, + "front-bracer": { + "front-bracer": { "x": 12.03, "y": -1.68, "rotation": 79.6, "width": 58, "height": 80 } + }, + "front-thigh": { + "front-thigh": { "x": 42.48, "y": 4.45, "rotation": 84.87, "width": 45, "height": 112 } + }, + "muzzle-glow": { + "muzzle-glow": { "width": 50, "height": 50 } + }, + "hoverboard-board": { + "hoverboard-board": { + "type": "mesh", + "uvs": [ 0.13865, 0.56624, 0.11428, 0.51461, 0.07619, 0.52107, 0.02364, 0.52998, 0.01281, 0.53182, 0, 0.37979, 0, 0.2206, 0.00519, 0.10825, 0.01038, 0.10726, 0.03834, 0.10194, 0.05091, 0, 0.08326, 0, 0.10933, 0.04206, 0.1382, 0.08865, 0.18916, 0.24067, 0.22234, 0.4063, 0.23886, 0.44063, 0.83412, 0.44034, 0.88444, 0.38296, 0.92591, 0.32639, 0.95996, 0.28841, 0.98612, 0.28542, 1, 0.38675, 0.99494, 0.47104, 0.97883, 0.53251, 0.94409, 0.62135, 0.90206, 0.69492, 0.86569, 0.71094, 0.82822, 0.70791, 0.81286, 0.77127, 0.62931, 0.77266, 0.61364, 0.70645, 0.47166, 0.70664, 0.45901, 0.77827, 0.27747, 0.76986, 0.2658, 0.70372, 0.24976, 0.71381, 0.24601, 0.77827, 0.23042, 0.84931, 0.20926, 0.90956, 0.17299, 1, 0.15077, 0.99967, 0.12906, 0.90192, 0.10369, 0.73693, 0.10198, 0.62482, 0.09131, 0.47272, 0.09133, 0.41325, 0.15082, 0.41868, 0.21991, 0.51856, 0.06331, 0.10816, 0.08383, 0.21696, 0.08905, 0.37532, 0.15903, 0.58726, 0.17538, 0.65706, 0.20118, 0.8029, 0.17918, 0.55644, 0.22166, 0.5802, 0.86259, 0.57962, 0.92346, 0.48534, 0.96691, 0.36881, 0.0945, 0.13259, 0.12688, 0.17831, 0.15986, 0.24682, 0.18036, 0.31268, 0.20607, 0.4235, 0.16074, 0.85403, 0.13624, 0.70122, 0.12096, 0.64049, 0.02396, 0.21811, 0.02732, 0.37839, 0.02557, 0.4972, 0.14476, 0.45736, 0.18019, 0.51689, 0.19692, 0.56636 ], + "triangles": [ 10, 11, 12, 9, 10, 12, 49, 9, 12, 60, 49, 12, 13, 60, 12, 61, 60, 13, 50, 49, 60, 50, 60, 61, 68, 8, 9, 68, 9, 49, 68, 49, 50, 7, 8, 68, 6, 7, 68, 61, 13, 14, 62, 61, 14, 50, 61, 62, 63, 62, 14, 59, 20, 21, 19, 20, 59, 51, 50, 62, 51, 62, 63, 51, 69, 68, 51, 68, 50, 6, 68, 69, 5, 6, 69, 18, 19, 59, 15, 63, 14, 59, 21, 22, 47, 51, 63, 47, 46, 51, 47, 63, 64, 15, 64, 63, 64, 15, 16, 71, 46, 47, 23, 59, 22, 69, 51, 70, 45, 46, 71, 70, 51, 2, 58, 18, 59, 58, 59, 23, 17, 18, 58, 70, 5, 69, 2, 51, 46, 1, 45, 71, 47, 48, 71, 47, 64, 48, 48, 72, 71, 1, 71, 72, 16, 48, 64, 45, 2, 46, 2, 45, 1, 70, 4, 5, 3, 70, 2, 3, 4, 70, 24, 58, 23, 72, 0, 1, 73, 55, 72, 55, 0, 72, 48, 73, 72, 57, 17, 58, 25, 57, 58, 56, 48, 16, 73, 48, 56, 56, 16, 17, 56, 17, 57, 52, 0, 55, 24, 25, 58, 44, 0, 52, 67, 44, 52, 52, 56, 53, 73, 52, 55, 56, 52, 73, 67, 52, 53, 26, 57, 25, 66, 67, 53, 56, 32, 35, 53, 56, 35, 56, 57, 32, 28, 31, 57, 57, 31, 32, 57, 27, 28, 26, 27, 57, 36, 53, 35, 43, 44, 67, 43, 67, 66, 34, 35, 32, 29, 31, 28, 30, 31, 29, 53, 54, 66, 53, 36, 54, 33, 34, 32, 37, 54, 36, 65, 43, 66, 38, 54, 37, 54, 65, 66, 39, 65, 54, 42, 43, 65, 38, 39, 54, 40, 42, 65, 40, 41, 42, 65, 39, 40 ], + "vertices": [ -189.36, 15.62, -201.35, 23.47, -220.09, 22.49, -245.95, 21.13, -251.28, 20.86, -257.58, 43.96, -257.57, 68.16, -255.02, 85.24, -252.47, 85.39, -238.71, 86.2, -232.52, 101.69, -216.61, 101.69, -203.78, 95.3, -189.58, 88.21, -164.51, 65.1, -148.19, 39.93, -140.06, 34.71, 152.82, 34.73, 177.57, 43.45, 197.97, 52.05, 214.72, 57.82, 227.6, 58.27, 234.42, 42.87, 231.94, 30.06, 224.01, 20.72, 206.91, 7.21, 186.23, -3.97, 168.34, -6.4, 149.9, -5.94, 142.35, -15.57, 52.04, -15.77, 44.33, -5.71, -25.52, -5.73, -31.75, -16.62, -121.07, -15.34, -126.81, -5.28, -134.7, -6.81, -136.54, -16.61, -144.22, -27.41, -154.63, -36.57, -172.47, -50.31, -183.41, -50.26, -194.09, -35.4, -206.56, -10.32, -207.4, 6.72, -212.65, 29.84, -212.64, 38.88, -183.37, 38.05, -149.38, 22.86, -226.43, 85.25, -216.33, 68.71, -213.76, 44.64, -179.34, 12.42, -171.29, 1.81, -158.6, -20.36, -169.42, 17.11, -148.52, 13.49, 166.82, 13.56, 196.76, 27.89, 218.14, 45.6, -211.08, 81.54, -195.15, 74.59, -178.93, 64.17, -168.84, 54.16, -156.19, 37.31, -178.5, -28.13, -190.55, -4.9, -198.07, 4.33, -245.79, 68.54, -244.14, 44.18, -245, 26.12, -186.36, 32.17, -168.92, 23.12, -160.69, 15.6 ], + "hull": 45, + "edges": [ 0, 2, 8, 10, 10, 12, 12, 14, 18, 20, 20, 22, 26, 28, 28, 30, 30, 32, 32, 34, 34, 36, 36, 38, 38, 40, 40, 42, 42, 44, 44, 46, 46, 48, 48, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 60, 62, 62, 64, 64, 66, 66, 68, 68, 70, 70, 72, 72, 74, 80, 82, 82, 84, 84, 86, 86, 88, 0, 88, 2, 90, 90, 92, 92, 94, 94, 96, 96, 32, 18, 98, 98, 100, 100, 102, 2, 4, 102, 4, 92, 102, 0, 104, 104, 106, 106, 108, 78, 80, 108, 78, 74, 76, 76, 78, 62, 56, 64, 70, 0, 110, 112, 114, 114, 116, 116, 118, 118, 42, 50, 116, 114, 34, 98, 120, 120, 122, 22, 24, 24, 26, 120, 24, 122, 124, 124, 126, 126, 128, 128, 96, 80, 130, 130, 132, 132, 134, 134, 88, 14, 16, 16, 18, 136, 16, 136, 138, 138, 140, 4, 6, 6, 8, 140, 6, 96, 112, 92, 142, 142, 144, 110, 146, 146, 112, 144, 146 ], + "width": 492, + "height": 152 + } + }, + "front-fist": { + "front-fist-closed": { "x": 35.5, "y": 6, "rotation": 67.16, "width": 75, "height": 82 }, + "front-fist-open": { "x": 39.57, "y": 7.76, "rotation": 67.16, "width": 86, "height": 87 } + } + } + } +], +"events": { + "footstep": {} +}, +"animations": { + "aim": { + "slots": { + "crosshair": { + "attachment": [ + { "name": "crosshair" } + ] + } + }, + "bones": { + "front-fist": { + "rotate": [ + { "angle": 36.08 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": -26.55 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 62.31 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": 9.11 } + ] + }, + "gun": { + "rotate": [ + { "angle": -0.31 } + ] + } + }, + "ik": { + "aim-ik": [ + { "mix": 0.995 } + ] + }, + "transform": { + "aim-head-transform": [ + { "rotateMix": 0.659, "translateMix": 0, "scaleMix": 0, "shearMix": 0 } + ], + "aim-torso-transform": [ + { "rotateMix": 0.423, "translateMix": 0, "scaleMix": 0, "shearMix": 0 } + ], + "aim-front-arm-transform": [ + { "rotateMix": 0.784, "translateMix": 0, "scaleMix": 0, "shearMix": 0 } + ] + }, + "deform": { + "default": { + "goggles": { + "goggles": [ + { + "offset": 16, + "vertices": [ -0.18341, -4.60426, -0.25211, -6.33094 ] + } + ] + }, + "mouth": { + "mouth-smile": [ + { + "vertices": [ 5.66431, 2.18625, 0.48294, -15.04339, 0.53525, -20.30316, -7.72803, -7.72495 ] + } + ] + }, + "head": { + "head": [ + { + "offset": 34, + "vertices": [ -0.22919, -5.75542, -0.22919, -5.75542, -0.22919, -5.75542 ] + } + ] + }, + "eye": { + "eye-indifferent": [ + { + "vertices": [ -0.68777, -17.26618, -0.68777, -17.26618, -0.68777, -17.26618, -0.68777, -17.26618 ] + } + ] + } + } + } + }, + "death": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-oooo" }, + { "time": 2.2333, "name": "mouth-grind" }, + { "time": 4.5333, "name": "mouth-oooo" } + ] + }, + "eye": { + "attachment": [ + { "name": "eye-surprised" }, + { "time": 0.4667, "name": "eye-indifferent" }, + { "time": 2.2333, "name": "eye-surprised" }, + { "time": 4.5333, "name": "eye-indifferent" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "head": { + "rotate": [ + { "angle": -2.83 }, + { "time": 0.1333, "angle": -28.74 }, + { "time": 0.2333, "angle": 11.43 }, + { "time": 0.3333, "angle": -50.25 }, + { "time": 0.4, "angle": -72.67, "curve": "stepped" }, + { "time": 0.4333, "angle": -72.67 }, + { "time": 0.5, "angle": -20.25 }, + { "time": 0.5667, "angle": -85.29, "curve": "stepped" }, + { "time": 2.2333, "angle": -85.29 }, + { "time": 2.5, "angle": -51.96, "curve": "stepped" }, + { "time": 4.5333, "angle": -51.96 }, + { "time": 4.6667, "angle": -85.29 } + ] + }, + "neck": { + "rotate": [ + { "angle": -2.83 }, + { "time": 0.1333, "angle": 12.35 }, + { "time": 0.2333, "angle": 29.89 }, + { "time": 0.3, "angle": 70.36 }, + { "time": 0.4, "angle": -10.22, "curve": "stepped" }, + { "time": 0.4333, "angle": -10.22 }, + { "time": 0.5, "angle": 2.93 }, + { "time": 0.5667, "angle": 47.95, "curve": "stepped" }, + { "time": 2.2333, "angle": 47.95 }, + { "time": 2.5, "angle": 18.51, "curve": "stepped" }, + { "time": 4.5333, "angle": 18.51 }, + { "time": 4.6667, "angle": 47.95 } + ] + }, + "torso": { + "rotate": [ + { "angle": -8.62 }, + { "time": 0.1333, "angle": 28.2 }, + { "time": 0.2667, "angle": -280.19 }, + { "time": 0.4, "angle": -237.23, "curve": "stepped" }, + { "time": 0.4333, "angle": -237.23 }, + { "time": 0.5, "angle": 76.03 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "angle": -38.86 }, + { "time": 0.1333, "angle": -299.59 }, + { "time": 0.2667, "angle": -244.75 }, + { "time": 0.4, "angle": -292.36 }, + { "time": 0.4333, "angle": -315.85 }, + { "time": 0.5, "angle": -347.94 }, + { "time": 0.7, "angle": -347.33, "curve": "stepped" }, + { "time": 2.2333, "angle": -347.33 }, + { "time": 2.7, "angle": -290.68 }, + { "time": 2.7667, "angle": -285.11 }, + { "time": 4.6667, "angle": -290.68 }, + { "time": 4.8, "angle": 8.61 }, + { "time": 4.8667, "angle": 10.94 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": -44.7 }, + { "time": 0.1333, "angle": 112.26 }, + { "time": 0.2667, "angle": 129.08 }, + { "time": 0.4, "angle": 134.94, "curve": "stepped" }, + { "time": 0.4333, "angle": 134.94 }, + { "time": 0.5667, "angle": 172.6 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": 21.88 }, + { "time": 0.1333, "angle": 11.49 }, + { "time": 0.2667, "angle": -18.82 }, + { "time": 0.4, "angle": -18.93 }, + { "time": 0.4333, "angle": -18.28 }, + { "time": 0.5, "angle": 60.62 }, + { "time": 0.7, "angle": -18.88, "curve": "stepped" }, + { "time": 2.2333, "angle": -18.88 }, + { "time": 2.7, "angle": -1.96, "curve": "stepped" }, + { "time": 4.6667, "angle": -1.96 }, + { "time": 4.8, "angle": 34.55 }, + { "time": 4.9333, "angle": -18.75 } + ] + }, + "front-fist": { + "rotate": [ + { "angle": -2.33 }, + { "time": 0.2667, "angle": 26.35 }, + { "time": 0.7, "angle": -6.08, "curve": "stepped" }, + { "time": 2.2333, "angle": -6.08 }, + { "time": 2.7, "angle": 5.73, "curve": "stepped" }, + { "time": 4.6667, "angle": 5.73 }, + { "time": 4.8667, "angle": -6.52 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": 10.36 }, + { "time": 0.1333, "angle": -23.12 }, + { "time": 0.2667, "angle": -23.12 }, + { "time": 0.4, "angle": -23.16, "curve": "stepped" }, + { "time": 0.4333, "angle": -23.16 }, + { "time": 0.5667, "angle": -23.2 } + ] + }, + "gun": { + "rotate": [ + { "angle": -2.79 }, + { "time": 0.1333, "angle": -24.58 } + ] + }, + "hip": { + "translate": [ + {}, + { "time": 0.2, "x": 50.35, "y": 151.73 }, + { "time": 0.4, "x": 5.17, "y": -119.65, "curve": "stepped" }, + { "time": 0.4333, "x": 5.17, "y": -119.65 }, + { "time": 0.5, "x": 50.35, "y": -205.19 } + ] + }, + "front-thigh": { + "rotate": [ + {}, + { "time": 0.1333, "angle": 8.47 }, + { "time": 0.2667, "angle": 115.96 }, + { "time": 0.4, "angle": 180.66, "curve": "stepped" }, + { "time": 0.4333, "angle": 180.66 }, + { "time": 0.5, "angle": 155.22 }, + { "time": 0.6, "angle": 97.74 } + ] + }, + "front-shin": { + "rotate": [ + {}, + { "time": 0.1333, "angle": -27.37 }, + { "time": 0.2667, "angle": -35.1 }, + { "time": 0.4, "angle": -37.73, "curve": "stepped" }, + { "time": 0.4333, "angle": -37.73 }, + { "time": 0.5, "angle": -40.07 }, + { "time": 0.6, "angle": 2.76 } + ] + }, + "rear-thigh": { + "rotate": [ + {}, + { "time": 0.1333, "angle": 70.45 }, + { "time": 0.2667, "angle": 155.35 }, + { "time": 0.4, "angle": 214.31, "curve": "stepped" }, + { "time": 0.4333, "angle": 214.31 }, + { "time": 0.5, "angle": 169.67 }, + { "time": 0.8, "angle": 83.27 } + ] + }, + "rear-shin": { + "rotate": [ + {}, + { "time": 0.1333, "angle": 18.94 }, + { "time": 0.2667, "angle": -21.04 }, + { "time": 0.4, "angle": -29.94, "curve": "stepped" }, + { "time": 0.4333, "angle": -29.94 }, + { "time": 0.5, "angle": -16.79 }, + { "time": 0.8, "angle": 7.78 } + ] + }, + "rear-foot": { + "rotate": [ + {}, + { "time": 0.1333, "angle": -11.63 }, + { "time": 0.4, "angle": -45.6 } + ] + }, + "front-foot": { + "rotate": [ + {}, + { "time": 0.4, "angle": -48.75 } + ] + }, + "front-foot-tip": { + "rotate": [ + {}, + { "time": 0.1333, "angle": -43.25 }, + { "time": 0.2, "angle": 6.05 }, + { "time": 0.3, "angle": 36.84 }, + { "time": 0.3667, "angle": 74.42 }, + { "time": 0.5667, "angle": 77.34 }, + { "time": 0.7, "angle": 59.35 } + ] + }, + "back-foot-tip": { + "rotate": [ + {}, + { "time": 0.1333, "angle": 83.04 }, + { "time": 0.3, "angle": 100.03 }, + { "time": 0.3667, "angle": 118.36 }, + { "time": 0.5667, "angle": 115.44 }, + { "time": 0.7, "angle": 88.21 }, + { "time": 0.8333, "angle": 53.38 } + ] + }, + "hair4": { + "rotate": [ + {}, + { "time": 0.2, "angle": -23.42 }, + { "time": 0.3, "angle": -16.06 }, + { "time": 0.3333, "angle": 19.03 }, + { "time": 0.4333, "angle": -4.91 }, + { "time": 0.5667, "angle": 1.29 } + ] + }, + "hair2": { + "rotate": [ + {}, + { "time": 0.2, "angle": -23.42 }, + { "time": 0.3, "angle": -16.06 }, + { "time": 0.3333, "angle": 19.03 }, + { "time": 0.4333, "angle": -4.91 }, + { "time": 0.5667, "angle": 1.29 } + ] + } + }, + "ik": { + "rear-leg-ik": [ + { "mix": 0.005, "bendPositive": false } + ], + "front-leg-ik": [ + { "mix": 0, "bendPositive": false } + ], + "rear-foot-ik": [ + { "mix": 0.005 } + ], + "front-foot-ik": [ + { "mix": 0 } + ] + } + }, + "hoverboard": { + "slots": { + "exhaust3": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "side-glow2": { + "attachment": [ + { "time": 0.0667, "name": "hoverglow-small" }, + { "time": 1, "name": null } + ] + }, + "hoverglow-rear": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "exhaust1": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "hoverboard-thruster-front": { + "attachment": [ + { "name": "hoverboard-thruster" } + ] + }, + "hoverboard-thruster-rear": { + "attachment": [ + { "name": "hoverboard-thruster" } + ] + }, + "hoverglow-front": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "side-glow1": { + "attachment": [ + { "name": "hoverglow-small" }, + { "time": 0.9667, "name": null } + ] + }, + "exhaust2": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "side-glow3": { + "attachment": [ + { "name": "hoverglow-small" }, + { "time": 0.9667, "name": null } + ] + }, + "hoverboard-board": { + "attachment": [ + { "name": "hoverboard-board" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "hoverboard-controller": { + "translate": [ + { "x": 319.55, "y": -1.59, "curve": 0.545, "c3": 0.625, "c4": 0.5 }, + { "time": 0.2667, "x": 347.66, "y": 47.75, "curve": 0.375, "c2": 0.5, "c3": 0.75 }, + { "time": 0.5333, "x": 338.47, "y": 85.72, "curve": 0.25, "c3": 0.522, "c4": 0.99 }, + { "time": 1, "x": 319.55, "y": -1.59 } + ] + }, + "hip": { + "translate": [ + { "x": -53.49, "y": 32.14, "curve": 0.279, "c2": 0.27, "c3": 0.677, "c4": 0.99 }, + { "time": 0.1333, "x": -49.31, "y": 23.31, "curve": 0.417, "c3": 0.75 }, + { "time": 0.3333, "x": -33.64, "y": 50.72, "curve": 0.25, "c3": 0.75 }, + { + "time": 0.5667, + "x": -20.06, + "y": 122.72, + "curve": 0.429, + "c2": 0.01, + "c3": 0.685, + "c4": 0.35 + }, + { "time": 1, "x": -53.49, "y": 32.14 } + ] + }, + "exhaust1": { + "scale": [ + { "x": 1.593, "y": 0.964 }, + { "time": 0.1333, "y": 0.713 }, + { "time": 0.2, "x": 1.774, "y": 0.883 }, + { "time": 0.3667, "x": 1.181, "y": 0.649 }, + { "time": 0.5333, "x": 1.893, "y": 0.819 }, + { "time": 0.6333, "x": 1.18, "y": 0.686 }, + { "time": 0.7333, "x": 1.903, "y": 0.855 }, + { "time": 0.8667, "x": 1.311, "y": 0.622 }, + { "time": 1, "x": 1.593, "y": 0.964 } + ] + }, + "exhaust2": { + "scale": [ + { "x": 1.88, "y": 0.832 }, + { "time": 0.1, "x": 1.311, "y": 0.686 }, + { "time": 0.2333, "x": 2.01, "y": 0.769 }, + { "time": 0.3667, "y": 0.794 }, + { "time": 0.5, "x": 1.699, "y": 0.86 }, + { "time": 0.5667, "x": 1.181, "y": 0.713 }, + { "time": 0.7667, "x": 1.881, "y": 0.796 }, + { "time": 0.9, "x": 1.3, "y": 0.649 }, + { "time": 1, "x": 1.88, "y": 0.832 } + ] + }, + "hoverboard-thruster-front": { + "rotate": [ + {}, + { "time": 0.5, "angle": 24.06 }, + { "time": 1 } + ] + }, + "hoverglow-front": { + "scale": [ + { "x": 0.849, "y": 1.764 }, + { "time": 0.0667, "x": 0.835, "y": 2.033 }, + { "time": 0.1667, "x": 0.752, "y": 1.735 }, + { "time": 0.2333, "x": 0.809, "y": 1.71 }, + { "time": 0.3, "x": 0.717, "y": 1.45 }, + { "time": 0.3667, "x": 0.777, "y": 1.45 }, + { "time": 0.4, "x": 0.725, "y": 1.241 }, + { "time": 0.4667, "x": 0.685, "y": 1.173 }, + { "time": 0.5667, "x": 0.825, "y": 1.572 }, + { "time": 0.6, "x": 0.758, "y": 1.297 }, + { "time": 0.6667, "x": 0.725, "y": 1.241 }, + { "time": 0.7667, "x": 0.895, "y": 1.857 }, + { "time": 0.8333, "x": 0.845, "y": 1.962 }, + { "time": 0.9, "x": 0.802, "y": 1.491 }, + { "time": 0.9667, "x": 0.845, "y": 1.31 }, + { "time": 1, "x": 0.849, "y": 1.764 } + ] + }, + "hoverboard-thruster-rear": { + "rotate": [ + {}, + { "time": 0.5, "angle": 24.06 }, + { "time": 1 } + ] + }, + "hoverglow-rear": { + "scale": [ + { "x": 0.845, "y": 1.31 }, + { "time": 0.0667, "x": 0.856, "y": 1.629 }, + { "time": 0.1333, "x": 0.835, "y": 2.033 }, + { "time": 0.2, "x": 0.752, "y": 1.735 }, + { "time": 0.3, "x": 0.809, "y": 1.71 }, + { "time": 0.3667, "x": 0.717, "y": 1.45 }, + { "time": 0.4333, "x": 0.777, "y": 1.45 }, + { "time": 0.5, "x": 0.725, "y": 1.241 }, + { "time": 0.5667, "x": 0.685, "y": 1.173 }, + { "time": 0.6333, "x": 0.758, "y": 1.297 }, + { "time": 0.7333, "x": 0.725, "y": 1.241 }, + { "time": 0.7667, "x": 0.825, "y": 1.572 }, + { "time": 0.8333, "x": 0.895, "y": 1.857 }, + { "time": 0.9, "x": 0.845, "y": 1.962 }, + { "time": 0.9667, "x": 0.802, "y": 1.491 }, + { "time": 1, "x": 0.845, "y": 1.31 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "angle": -85.92, "curve": 0.25, "c3": 0.75 }, + { "time": 0.3667, "angle": -53.64, "curve": 0.722, "c3": 0.75 }, + { "time": 0.6333, "angle": -79.62, "curve": 0.25, "c3": 0.75 }, + { "time": 1, "angle": -85.92 } + ], + "translate": [ + { "x": -0.59, "y": -2.94 }, + { "time": 0.2667, "x": -6.76, "y": -11.66 }, + { "time": 0.3667, "x": -1.74, "y": -6.39 }, + { "time": 0.6333, "x": 0.72, "y": -2.88 }, + { "time": 1, "x": -0.59, "y": -2.94 } + ] + }, + "front-fist": { + "rotate": [ + { "angle": 16.07 }, + { "time": 0.2667, "angle": -26.01 }, + { "time": 0.5667, "angle": 21.48 }, + { "time": 1, "angle": 16.07 } + ], + "translate": [ + {}, + { "time": 0.4667, "x": 0.52, "y": -3.27 }, + { "time": 1 } + ], + "shear": [ + { "y": 19.83 }, + { "time": 0.4667, "x": 15.28, "y": 28.31 }, + { "time": 1, "y": 19.83 } + ] + }, + "board-ik": { + "translate": [ + { "x": 393.62, "curve": 0.25, "c3": 0.75 }, + { "time": 0.3333, "x": 393.48, "y": 117.69, "curve": 0.25, "c3": 0.75 }, + { "time": 0.5, "x": 393.62, "y": 83.82 }, + { "time": 0.6667, "x": 393.62, "y": 30.15 }, + { "time": 1, "x": 393.62 } + ] + }, + "front-thigh": { + "translate": [ + { "x": -7.49, "y": 8.51 } + ] + }, + "front-leg-target": { + "translate": [ + { "time": 0.3667 }, + { "time": 0.5, "x": 12.78, "y": 8.79 }, + { "time": 0.8667 } + ] + }, + "rear-leg-target": { + "translate": [ + { "time": 0.4667 }, + { "time": 0.5667, "x": 4.53, "y": 1.77 }, + { "time": 0.6667, "x": -1.05, "y": -0.44 }, + { "time": 1 } + ] + }, + "exhaust3": { + "scale": [ + { "x": 1.882, "y": 0.81 }, + { "time": 0.0667, "x": 1.731, "y": 0.761 }, + { "time": 0.2, "x": 1.3, "y": 0.649 }, + { "time": 0.3, "x": 2.051, "y": 0.984 }, + { "time": 0.4, "x": 1.311, "y": 0.686 }, + { "time": 0.5333, "x": 1.86, "y": 0.734 }, + { "time": 0.6667, "y": 0.794 }, + { "time": 0.8, "x": 1.549, "y": 0.825 }, + { "time": 0.8667, "x": 1.181, "y": 0.713 }, + { "time": 1, "x": 1.731, "y": 0.78 } + ] + }, + "side-glow1": { + "rotate": [ + { "angle": 51.12, "curve": "stepped" }, + { "time": 0.0667, "angle": 43.82, "curve": "stepped" }, + { "time": 0.1, "angle": 40.95, "curve": "stepped" }, + { "time": 0.1667, "angle": 27.78, "curve": "stepped" }, + { "time": 0.2, "angle": 10.24, "curve": "stepped" }, + { "time": 0.2667, "curve": "stepped" }, + { "time": 0.8, "angle": -25.81 } + ], + "translate": [ + { "x": 338.28, "y": 40.22, "curve": "stepped" }, + { "time": 0.0667, "x": 331.2, "y": 30.39, "curve": "stepped" }, + { "time": 0.1, "x": 318.63, "y": 20.59, "curve": "stepped" }, + { "time": 0.1667, "x": 302.45, "y": 9.64, "curve": "stepped" }, + { "time": 0.2, "x": 276.87, "y": 1.13, "curve": "stepped" }, + { "time": 0.2667, "x": 248.16, "curve": "stepped" }, + { "time": 0.3, "x": 221.36, "curve": "stepped" }, + { "time": 0.3667, "x": 195.69, "curve": "stepped" }, + { "time": 0.4, "x": 171.08, "curve": "stepped" }, + { "time": 0.4667, "x": 144.84, "curve": "stepped" }, + { "time": 0.5, "x": 121.22, "curve": "stepped" }, + { "time": 0.5667, "x": 91.98, "curve": "stepped" }, + { "time": 0.6, "x": 62.63, "curve": "stepped" }, + { "time": 0.6667, "x": 30.78, "curve": "stepped" }, + { "time": 0.7, "curve": "stepped" }, + { "time": 0.7667, "x": -28.45, "curve": "stepped" }, + { "time": 0.8, "x": -67.49, "y": 16.82, "curve": "stepped" }, + { "time": 0.8667, "x": -83.07, "y": 24.36, "curve": "stepped" }, + { "time": 0.9, "x": -93.81, "y": 29.55 } + ], + "scale": [ + { "x": 0.535, "curve": "stepped" }, + { "time": 0.0667, "x": 0.594, "curve": "stepped" }, + { "time": 0.1, "x": 0.844, "curve": "stepped" }, + { "time": 0.1667, "curve": "stepped" }, + { "time": 0.8, "x": 0.534, "curve": "stepped" }, + { "time": 0.8667, "x": 0.428, "y": 0.801, "curve": "stepped" }, + { "time": 0.9, "x": 0.349, "y": 0.654 } + ] + }, + "side-glow2": { + "rotate": [ + { "time": 0.0667, "angle": 51.12, "curve": "stepped" }, + { "time": 0.1, "angle": 43.82, "curve": "stepped" }, + { "time": 0.1667, "angle": 40.95, "curve": "stepped" }, + { "time": 0.2, "angle": 27.78, "curve": "stepped" }, + { "time": 0.2667, "angle": 10.24, "curve": "stepped" }, + { "time": 0.3, "curve": "stepped" }, + { "time": 0.8667, "angle": -25.81 } + ], + "translate": [ + { "time": 0.0667, "x": 338.28, "y": 40.22, "curve": "stepped" }, + { "time": 0.1, "x": 331.2, "y": 30.39, "curve": "stepped" }, + { "time": 0.1667, "x": 318.63, "y": 20.59, "curve": "stepped" }, + { "time": 0.2, "x": 302.45, "y": 9.64, "curve": "stepped" }, + { "time": 0.2667, "x": 276.87, "y": 1.13, "curve": "stepped" }, + { "time": 0.3, "x": 248.16, "curve": "stepped" }, + { "time": 0.3667, "x": 221.36, "curve": "stepped" }, + { "time": 0.4, "x": 195.69, "curve": "stepped" }, + { "time": 0.4667, "x": 171.08, "curve": "stepped" }, + { "time": 0.5, "x": 144.84, "curve": "stepped" }, + { "time": 0.5667, "x": 121.22, "curve": "stepped" }, + { "time": 0.6, "x": 91.98, "curve": "stepped" }, + { "time": 0.6667, "x": 62.63, "curve": "stepped" }, + { "time": 0.7, "x": 30.78, "curve": "stepped" }, + { "time": 0.7667, "curve": "stepped" }, + { "time": 0.8, "x": -28.45, "curve": "stepped" }, + { "time": 0.8667, "x": -67.49, "y": 16.82, "curve": "stepped" }, + { "time": 0.9, "x": -83.07, "y": 24.36, "curve": "stepped" }, + { "time": 0.9667, "x": -93.81, "y": 29.55 } + ], + "scale": [ + { "time": 0.0667, "x": 0.535, "curve": "stepped" }, + { "time": 0.1, "x": 0.594, "curve": "stepped" }, + { "time": 0.1667, "x": 0.844, "curve": "stepped" }, + { "time": 0.2, "curve": "stepped" }, + { "time": 0.8667, "x": 0.534, "curve": "stepped" }, + { "time": 0.9, "x": 0.428, "y": 0.801, "curve": "stepped" }, + { "time": 0.9667, "x": 0.349, "y": 0.654 } + ] + }, + "torso": { + "rotate": [ + { "angle": -34.73, "curve": 0.438, "c3": 0.75 }, + { "time": 0.2667, "angle": -39.37, "curve": 0.25, "c3": 0.75 }, + { "time": 0.5, "angle": -28.86, "curve": 0.25, "c3": 0.75 }, + { "time": 0.6333, "angle": -21.01 }, + { "time": 1, "angle": -34.73 } + ] + }, + "neck": { + "rotate": [ + { "angle": 10.2 }, + { "time": 0.2667, "angle": 16.14 }, + { "time": 0.5, "angle": 5.83 }, + { "time": 0.6333, "angle": 2.68 }, + { "time": 1, "angle": 10.2 } + ] + }, + "head": { + "rotate": [ + { "angle": 10.2 }, + { "time": 0.2667, "angle": 16.14 }, + { "time": 0.5, "angle": 5.83 }, + { "time": 0.6333, "angle": 2.68 }, + { "time": 1, "angle": 10.2 } + ], + "translate": [ + {}, + { "time": 0.2667, "x": -4.22, "y": -3.62 }, + { "time": 0.6333, "x": 0.84, "y": 6.01 }, + { "time": 1 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": -11.18, "curve": 0.25, "c3": 0.75 }, + { "time": 0.5, "angle": 12.32, "curve": 0.25, "c3": 0.75 }, + { "time": 0.6333, "angle": 6.91, "curve": 0.25, "c3": 0.75 }, + { "time": 1, "angle": -11.18 } + ] + }, + "hair3": { + "rotate": [ + { "angle": 9.61, "curve": "stepped" }, + { "time": 0.3667, "angle": 9.61 }, + { "time": 0.5, "angle": -8.42 }, + { "time": 1, "angle": 9.61 } + ] + }, + "hair4": { + "rotate": [ + { "angle": -17.7 }, + { "time": 0.0333, "angle": -9.09 }, + { "time": 0.0667, "angle": -9.34 }, + { "time": 0.1, "angle": -3.31 }, + { "time": 0.1667, "angle": 0.65 }, + { "time": 0.2, "angle": 5.23 }, + { "time": 0.2667, "angle": 17.56 }, + { "time": 0.3667, "angle": 27.97 }, + { "time": 0.5, "angle": -1.45 }, + { "time": 0.5667, "angle": -1.78 }, + { "time": 0.6333, "angle": -8.9 }, + { "time": 0.6667, "angle": -5.4 }, + { "time": 0.7333, "angle": -15.32 }, + { "time": 0.7667, "angle": -9.19 }, + { "time": 0.8333, "angle": -23.6 }, + { "time": 0.8667, "angle": -22.7 }, + { "time": 0.9333, "angle": -17.38 }, + { "time": 0.9667, "angle": -18.96 }, + { "time": 1, "angle": -17.7 } + ] + }, + "hair1": { + "rotate": [ + { "angle": 9.61, "curve": "stepped" }, + { "time": 0.3667, "angle": 9.61 }, + { "time": 0.5, "angle": -8.42 }, + { "time": 1, "angle": 9.61 } + ] + }, + "hair2": { + "rotate": [ + { "angle": -22.7 }, + { "time": 0.0667, "angle": -17.38 }, + { "time": 0.1333, "angle": -17.7 }, + { "time": 0.1667, "angle": -9.09 }, + { "time": 0.2, "angle": -9.34 }, + { "time": 0.2333, "angle": -3.31 }, + { "time": 0.2667, "angle": 0.65 }, + { "time": 0.3333, "angle": 5.23 }, + { "time": 0.3667, "angle": 17.56 }, + { "time": 0.5, "angle": 27.97 }, + { "time": 0.6333, "angle": -1.45 }, + { "time": 0.7, "angle": -1.78 }, + { "time": 0.7667, "angle": -8.9 }, + { "time": 0.8, "angle": -5.4 }, + { "time": 0.8667, "angle": -15.32 }, + { "time": 0.9, "angle": -9.19 }, + { "time": 0.9667, "angle": -23.6 }, + { "time": 1, "angle": -22.7 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 31.65, "curve": 0.25, "c3": 0.75 }, + { "time": 0.4333, "angle": 13.01, "curve": 0.25, "c3": 0.75 }, + { "time": 0.6667, "angle": 20.85, "curve": 0.25, "c3": 0.75 }, + { "time": 1, "angle": 31.65 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": 31 }, + { "time": 0.4333, "angle": 12.79 }, + { "time": 0.6667, "angle": 20.85 }, + { "time": 1, "angle": 31 } + ] + }, + "gun": { + "rotate": [ + { "angle": 1.95 }, + { "time": 0.4333, "angle": 12.79 }, + { "time": 0.6667, "angle": 15.87 }, + { "time": 1, "angle": 1.95 } + ] + } + }, + "transform": { + "toes-board": [ + { "translateMix": 0, "scaleMix": 0, "shearMix": 0 } + ], + "front-foot-board-transform": [ + {} + ], + "rear-foot-board-transform": [ + {} + ] + }, + "deform": { + "default": { + "goggles": { + "goggles": [ + { "curve": 0.25, "c3": 0.75 }, + { + "time": 0.2667, + "vertices": [ 0.67711, -3.13914, 0.27417, -1.27147, 0.15489, -0.72019, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.42483, -1.97125, 1.55292, -7.20752, 0.1845, -0.85692, 0.62342, -2.89004, 0.80454, -3.72999, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.01049, -4.68358, 1.14495, -5.30811, 1.05917, -4.91033, 0.7856, -3.6421, 0.88443, -4.1001, 0.91542, -4.24387, 0.80144, -3.7155, 0.7665, -3.55506, 0.29612, -1.37293, 0.03147, -0.14642, 0.22645, -1.05166, 0.13694, -0.63699, 0.25405, -1.17808, 0.55052, -2.5523, 0.77677, -3.60118, 1.59353, -7.39157, 1.35063, -6.26342, 1.34974, -6.25925, 0.94851, -4.39735, 0.83697, -3.88036, 0.80624, -3.73668, 1.01196, -4.69016, 0, 0, 0.1845, -0.85692, 0.1845, -0.85692, 0.1845, -0.85692, 0.1845, -0.85692, 0.1845, -0.85692, 0.1845, -0.85692 ], + "curve": 0.25, + "c3": 0.75 + }, + { "time": 1 } + ] + }, + "torso": { + "torso": [ + {}, + { + "time": 0.2667, + "offset": 10, + "vertices": [ 4.46481, -0.3543, 4.46481, -0.35429, 4.46481, -0.3543, 4.46481, -0.35429, 4.46481, -0.3543, 4.46481, -0.35429, 4.46481, -0.3543, 0, 0, -0.59544, -7.5094, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, -0.5954, -7.50941, -0.5954, -7.50941, -0.5954, -7.50941, -0.5954, -7.50941, 3.86934, -7.86369, 3.86935, -7.86369, 3.86934, -7.86369, 3.86935, -7.86369, -0.5954, -7.50941, -0.5954, -7.50941, -0.5954, -7.50941, -0.5954, -7.50941, -0.59544, -7.5094, -0.5954, -7.50941, -0.59544, -7.5094, -0.5954, -7.50941, 3.0E-5, -1.0E-5, 0.35948, -1.81172, 0, 0, 0, 0, -0.13678, -6.00883, -0.13666, -6.0088, 2.46274, -6.26834, 2.27113, -5.86305, 2.27148, -5.86322, 0.52808, -3.21825 ] + }, + { "time": 0.5 }, + { + "time": 0.6333, + "offset": 2, + "vertices": [ 3.41785, -0.27124, 3.41788, -0.27125, 3.41785, -0.27124, 3.41788, -0.27125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.4682, 5.90338, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.88608, 5.63213, 3.88608, 5.63213, 0.46823, 5.90337, 0.46823, 5.90337, 0, 0, 0, 0, 0.4682, 5.90338, 0.46823, 5.90337, 0.46823, 5.90337, 0.46823, 5.90337, 0.46823, 5.90337, 0.46823, 5.90337, 0.4682, 5.90338, 0.46823, 5.90337, 0.4682, 5.90338, 0.46823, 5.90337, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, -0.5545, 7.37883, -0.5545, 7.37883, -0.26138, 7.75283, -0.76694, 6.33778, -0.76703, 6.33779 ] + }, + { "time": 1 } + ] + }, + "front-foot": { + "front-foot": [ + { + "offset": 26, + "vertices": [ -0.02832, -5.37024, -0.02832, -5.37024, 3.8188, -3.7757, -0.02832, -5.37024, -3.82159, 3.77847 ] + } + ] + }, + "rear-foot": { + "rear-foot": [ + { + "offset": 28, + "vertices": [ -1.93078, 1.34782, -0.31417, 2.33363, 3.05122, 0.33946, 2.31472, -2.01678, 2.17583, -2.05795, -0.04277, -2.99459, 1.15429, 0.26328, 0.97501, -0.67169 ] + } + ] + }, + "mouth": { + "mouth-smile": [ + { "curve": 0.25, "c3": 0.75 }, + { + "time": 0.2667, + "vertices": [ 0.15454, -6.6912, 0.15454, -6.6912, 0.15454, -6.6912, 0.15454, -6.6912 ], + "curve": 0.25, + "c3": 0.75 + }, + { "time": 1 } + ] + }, + "head": { + "head": [ + { + "offset": 60, + "vertices": [ 2.77362, 1.62589, 1.93787, 2.56528 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.2667, + "offset": 34, + "vertices": [ 1.96774, -9.13288, 1.96774, -9.13288, 1.96774, -9.13288, 0.52141, -2.41945, 0, 0, 0, 0, 0, 0, 0, 0, -0.28486, 1.32153, -0.28486, 1.32153, 0, 0, 0, 0, 0, 0, 1.04011, 0.60971, 0.7267, 0.96198, 7.3906, -5.46259, 3.91425, 8.31534, 2.51528, -2.75824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6.35114, 5.70461, 6.83772, -5.11176, 3.67865, 7.70451, 5.75797, -8.66576, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.08572, -3.70304, 1.49945, -3.38693, 0.21432, -9.25756, 0, 0, 0, 0, 0.08572, -3.70304, 0.21432, -9.25756, 0, 0, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0, 0, 0, 0, 0, 0, 0, 0, 0.34761, -1.61296, 0.26072, -1.20974, 0.65176, -3.02431 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 1, + "offset": 60, + "vertices": [ 2.77362, 1.62589, 1.93787, 2.56528 ] + } + ] + }, + "front-shin": { + "front-shin": [ + { + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + }, + { + "time": 0.3667, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -11.66571, -9.07211, -25.65866, -17.53735, -25.53217, -16.50978, -11.78232, -11.26097, 0, 0, 0.60487, -1.63589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0, 0, -2.64522, -7.35739, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0.60487, -1.63589, 0.60487, -1.63589, 0.60487, -1.63589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0, 0, -10.06873, -12.0999 ] + }, + { + "time": 0.5333, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -7.00775, -8.24771, -6.45482, -6.49312, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + }, + { + "time": 1, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + } + ] + }, + "eye": { + "eye-indifferent": [ + { "curve": 0.25, "c3": 0.75 }, + { + "time": 0.2667, + "vertices": [ 0.22339, -6.575, 0.22339, -6.575, 0.22339, -6.575, 0.22339, -6.575 ], + "curve": 0.25, + "c3": 0.75 + }, + { "time": 1 } + ] + }, + "hoverboard-board": { + "hoverboard-board": [ + {}, + { + "time": 0.2667, + "offset": 1, + "vertices": [ 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 3.55673, -3.0E-4, 3.55673, -3.0E-4, 0, 0, 0, 0, 0, 0, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, 0, 0, 0, 0, 0, 0, 0, 0, -4.90558, 0.11214, -9.40706, 6.2E-4, -6.34871, 4.3E-4, -6.34925, -6.57018, -6.34925, -6.57018, -6.34871, 4.3E-4, -2.3308, 1.7E-4, -2.33133, -6.57045, -2.33133, -6.57045, -2.3308, 1.7E-4, 0, 0, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 3.3297, 4.44005, 3.3297, 4.44005, 3.3297, 4.44005, 1.2E-4, 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, 1.2E-4, 2.45856, 1.2E-4, 2.45856, -9.40694, 2.45918, 1.88063, 0.44197, -2.9E-4, -3.54808, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.46227, 1.7E-4, 0, 0, 0, 0, 1.2E-4, 2.45856 ] + }, + { "time": 1 } + ] + } + } + } + }, + "idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-foot-target": { + "translate": [ + { "x": -69.06 } + ] + }, + "hip": { + "translate": [ + { "x": -7.16, "y": -23.15, "curve": 0.205, "c3": 0.75 }, + { "time": 0.6667, "x": -5.33, "y": -35.48, "curve": 0.591, "c3": 0.642 }, + { "time": 1.6667, "x": -7.16, "y": -23.15 } + ] + }, + "rear-foot-target": { + "translate": [ + { "x": 48.87 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "angle": -70.59 }, + { "time": 0.8, "angle": -80.61 }, + { "time": 1.6667, "angle": -70.59 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": 42.09 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 39.2 }, + { "time": 0.6667, "angle": 29.37 }, + { "time": 1.6667, "angle": 39.2 } + ] + }, + "head": { + "rotate": [ + { "angle": -8.95, "curve": 0.25, "c3": 0.75 }, + { "time": 0.6667, "angle": -4.12, "curve": 0.25, "c3": 0.75 }, + { "time": 1.6667, "angle": -8.95 } + ] + }, + "front-fist": { + "rotate": [ + {}, + { "time": 0.8, "angle": 2.04 }, + { "time": 1.6667 } + ], + "scale": [ + {}, + { "time": 0.8, "x": 0.94 }, + { "time": 1.6667 } + ] + }, + "rear-bracer": { + "rotate": [ + {}, + { "time": 0.6667, "angle": 16.09 }, + { "time": 1.6667 } + ] + }, + "gun": { + "rotate": [ + {}, + { "time": 0.6667, "angle": 0.45 }, + { "time": 1.6667 } + ] + }, + "torso": { + "rotate": [ + { "angle": -8.85 }, + { "time": 0.6667, "angle": -13.61 }, + { "time": 1.6667, "angle": -8.85 } + ] + }, + "neck": { + "rotate": [ + { "angle": 3.78, "curve": 0.25, "c3": 0.75 }, + { "time": 0.6667, "angle": 5.45, "curve": 0.25, "c3": 0.75 }, + { "time": 1.6667, "angle": 3.78 } + ] + } + } + }, + "idle-turn": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-upper-arm": { + "rotate": [ + { "angle": -302.77, "curve": 0, "c2": 0.81, "c3": 0.467 }, + { "time": 0.2667, "angle": -70.59 } + ], + "translate": [ + { "x": -5.24, "y": -18.27, "curve": 0.25, "c3": 0.418 }, + { "time": 0.2667 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 248.56, "curve": 0, "c2": 0.81, "c3": 0.467 }, + { "time": 0.1333, "angle": 39.2 } + ], + "translate": [ + { "x": -2.84, "y": 37.28, "curve": 0.25, "c3": 0.521 }, + { "time": 0.1333 } + ] + }, + "gun": { + "rotate": [ + { "angle": -3.95, "curve": 0, "c2": 0.39, "c3": 0.354, "c4": 0.72 }, + { "time": 0.0333, "angle": -20.45, "curve": 0.288, "c2": 0.75, "c3": 0.55 }, + { "time": 0.2 } + ] + }, + "neck": { + "rotate": [ + { "angle": 17.2, "curve": 0, "c2": 0.81, "c3": 0.467 }, + { "time": 0.2667, "angle": 3.78 } + ] + }, + "hip": { + "translate": [ + { "x": -2.69, "y": -6.79, "curve": 0, "c2": 0.81, "c3": 0.467 }, + { "time": 0.2667, "x": -7.16, "y": -23.15 } + ] + }, + "front-fist": { + "rotate": [ + { "angle": -15.54, "curve": 0, "c2": 0.36, "c3": 0.343, "c4": 0.69 }, + { "time": 0.0667, "angle": 19.02, "curve": 0.082, "c2": 0.81, "c3": 0.514 }, + { "time": 0.2667 } + ], + "scale": [ + { "x": 0.94, "curve": 0, "c2": 0.81, "c3": 0.467 }, + { "time": 0.2667 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": 11.75, "curve": 0, "c2": 0.44, "c3": 0.369, "c4": 0.76 }, + { "time": 0.0333, "angle": -33.39, "curve": 0.207, "c2": 0.78, "c3": 0.587 }, + { "time": 0.2 } + ] + }, + "torso": { + "rotate": [ + { "angle": -18.25, "curve": 0, "c2": 0.81, "c3": 0.467 }, + { "time": 0.2667, "angle": -8.85 } + ], + "scale": [ + { "y": 1.03, "curve": 0.25, "c3": 0.494 }, + { "time": 0.2667 } + ] + }, + "head": { + "rotate": [ + { "angle": 5.12, "curve": 0, "c2": 0.81, "c3": 0.467 }, + { "time": 0.2667, "angle": -8.95 } + ], + "scale": [ + { "y": 1.03, "curve": 0.25, "c3": 0.401 }, + { "time": 0.2667 } + ] + }, + "rear-foot-target": { + "translate": [ + { "x": -58.39, "y": 30.48, "curve": 0, "c2": 0.55, "c3": 0.403, "c4": 0.85 }, + { "time": 0.1, "x": 34.14, "y": -1.61, "curve": 0.286, "c2": 0.75, "c3": 0.634 }, + { "time": 0.2, "x": 48.87 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": 6.69, "curve": 0, "c2": 0.81, "c3": 0.467 }, + { "time": 0.2667, "angle": 42.09 } + ] + }, + "front-foot-target": { + "rotate": [ + { "angle": -1.85 }, + { "time": 0.1667 } + ], + "translate": [ + { "x": 9.97, "y": 0.82, "curve": 0, "c2": 0.81, "c3": 0.467 }, + { "time": 0.1667, "x": -69.06 } + ] + }, + "hair3": { + "rotate": [ + { "angle": -9.01, "curve": 0.25, "c3": 0.361 }, + { "time": 0.2667 } + ] + }, + "hair4": { + "rotate": [ + { "angle": -16.49, "curve": 0.25, "c3": 0.361 }, + { "time": 0.2667 } + ] + }, + "hair1": { + "rotate": [ + { "angle": -3.85, "curve": 0.25, "c3": 0.361 }, + { "time": 0.2667 } + ] + }, + "hair2": { + "rotate": [ + { "angle": 1.25, "curve": 0.25, "c3": 0.361 }, + { "time": 0.2667 } + ] + }, + "front-thigh": { + "translate": [ + { "x": 12.21, "y": 1.89, "curve": 0.25, "c3": 0.75 }, + { "time": 0.1333 } + ] + }, + "rear-thigh": { + "translate": [ + { "x": -16.11, "y": -1.38, "curve": 0.25, "c3": 0.75 }, + { "time": 0.1333 } + ] + } + }, + "deform": { + "default": { + "torso": { + "torso": [ + { + "offset": 2, + "vertices": [ 4.71576, 4.44464, 4.71579, 4.44463, 4.7399, 4.67474, 4.73993, 4.67473, 5.0968, 8.08033, 5.0968, 8.08034, 5.1181, 8.28423, 5.11813, 8.28422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 1.21198, -8.88572, 1.21201, -8.88573, 1.2106, -7.18206, 1.21063, -7.18207, 0.98038, -5.14252, 0.98038, -5.14252, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, -1.13269, -8.03748, -1.13266, -8.03748, -1.13268, -8.03748, -1.13269, -8.03748, -1.13268, -8.03748, -1.13266, -8.03748, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, 0.77191, -5.83292, 0.77274, -5.83294, 0, 0, 0.67996, -9.11016, 0.67938, -9.11015 ], + "curve": 0.25, + "c3": 0.282 + }, + { + "time": 0.2667, + "offset": 74, + "vertices": [ 0.52324, 5.68796, 0.52335, 5.68797, 0.52335, 5.68797, 0.52347, 5.68797, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.49251, 5.35334, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0.52335, 5.68797, 0, 0, 0, 0, 2.59232, 6.1724 ] + } + ] + } + } + } + }, + "jump": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" }, + { "time": 0.2, "name": "front-fist-closed" }, + { "time": 0.6667, "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { "angle": 91.53, "curve": 0.278, "c2": 0.46, "c3": 0.764 }, + { "time": 0.2, "angle": -35.84, "curve": 0.761, "c3": 0.75 }, + { "time": 0.4333, "angle": 127.74 }, + { "time": 0.7333, "angle": 48.18, "curve": 0.227, "c2": 0.27, "c3": 0.433 }, + { "time": 0.8333, "angle": 25.35 }, + { "time": 0.9333, "angle": 45.38 }, + { "time": 1.0333, "angle": 38.12 }, + { "time": 1.1333, "angle": 25.35 }, + { "time": 1.3333, "angle": 91.53 } + ], + "translate": [ + { "x": -2.57, "y": 5.78 }, + { "time": 0.4333, "x": 8.3, "y": 7.99 }, + { "time": 0.7333, "x": 7.21, "y": -4 }, + { "time": 1.3333, "x": -2.57, "y": 5.78 } + ] + }, + "torso": { + "rotate": [ + { "angle": -42.64 }, + { "time": 0.2, "angle": -5.74 }, + { "time": 0.4333, "angle": -50.76 }, + { "time": 0.7333, "angle": 1.9 }, + { "time": 0.8333, "angle": 11.59 }, + { "time": 0.9667, "angle": -1.9 }, + { "time": 1.1333, "angle": 11.59 }, + { "time": 1.3333, "angle": -42.64 } + ] + }, + "rear-thigh": { + "rotate": [ + { "angle": -26.32 }, + { "time": 0.2, "angle": 121.44 }, + { "time": 0.4333, "angle": 70.55 }, + { "time": 0.7333, "angle": 79.9, "curve": 0.296, "c2": 0.3, "c3": 0.59 }, + { "time": 0.8333, "angle": 99.12 }, + { "time": 0.9333, "angle": 74.06 }, + { "time": 1.0333, "angle": 98.05 }, + { "time": 1.1333, "angle": 99.12 }, + { "time": 1.3333, "angle": -26.32 } + ], + "translate": [ + { "x": -0.56, "y": -0.32 }, + { "time": 0.4333, "x": -8.5, "y": 10.58 }, + { "time": 0.7333, "x": -1.96, "y": -0.32 }, + { "time": 1.3333, "x": -0.56, "y": -0.32 } + ] + }, + "rear-shin": { + "rotate": [ + { "angle": -78.69 }, + { "time": 0.4333, "angle": -55.56 }, + { "time": 0.7333, "angle": -62.84 }, + { "time": 0.8333, "angle": -80.75 }, + { "time": 0.9333, "angle": -41.13 }, + { "time": 1.0333, "angle": -77.4 }, + { "time": 1.1333, "angle": -80.75 }, + { "time": 1.3333, "angle": -78.69 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "angle": -22.62 }, + { "time": 0.2, "angle": -246.69 }, + { "time": 0.6, "angle": 11.28, "curve": 0.246, "c3": 0.633, "c4": 0.54 }, + { "time": 0.7333, "angle": -57.46, "curve": 0.38, "c2": 0.53, "c3": 0.745 }, + { "time": 0.8667, "angle": -112.6 }, + { "time": 0.9333, "angle": -102.17 }, + { "time": 1.0333, "angle": -108.61 }, + { "time": 1.1333, "angle": -112.6 }, + { "time": 1.3333, "angle": -22.62 } + ], + "translate": [ + { "x": 6.08, "y": 7.15 }, + { "time": 0.2, "x": 7.23, "y": -13.13, "curve": "stepped" }, + { "time": 0.7333, "x": 7.23, "y": -13.13 }, + { "time": 1.3333, "x": 6.08, "y": 7.15 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": 66.47 }, + { "time": 0.2, "angle": 42.4 }, + { "time": 0.4333, "angle": 26.06 }, + { "time": 0.7333, "angle": 13.28 }, + { "time": 0.8667, "angle": -28.65 }, + { "time": 0.9333, "angle": -22.31 }, + { "time": 1.0333, "angle": -35.39 }, + { "time": 1.1333, "angle": -28.65 }, + { "time": 1.3333, "angle": 66.47 } + ] + }, + "front-fist": { + "rotate": [ + { "angle": -28.43 }, + { "time": 0.4333, "angle": -45.61 }, + { "time": 0.7333, "angle": -53.66 }, + { "time": 0.8667, "angle": 7.56 }, + { "time": 0.9333, "angle": 31.16 }, + { "time": 1.0333, "angle": -32.59 }, + { "time": 1.1333, "angle": 7.56 }, + { "time": 1.3333, "angle": -28.43 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 39.69 }, + { "time": 0.2, "angle": 276.58 }, + { "time": 0.3, "angle": 17.74 }, + { "time": 0.4333, "angle": 83.38 }, + { "time": 0.6, "angle": -4.72, "curve": 0.246, "c3": 0.633, "c4": 0.54 }, + { "time": 0.7333, "angle": -69.63, "curve": 0.343, "c2": 0.36, "c3": 0.68, "c4": 0.71 }, + { "time": 0.7667, "angle": 321.47, "curve": 0.334, "c2": 0.33, "c3": 0.667, "c4": 0.67 }, + { "time": 0.8, "angle": 33.71, "curve": 0.359, "c2": 0.64, "c3": 0.694 }, + { "time": 0.8667, "angle": 34.56 }, + { "time": 1.0333, "angle": 71.97 }, + { "time": 1.1333, "angle": 34.56 }, + { "time": 1.3333, "angle": 39.69 } + ], + "translate": [ + { "x": -3.1, "y": -4.87 }, + { "time": 0.2, "x": 23.33, "y": 49.07 }, + { "time": 0.4333, "x": 20.78, "y": 40.21 }, + { "time": 1.3333, "x": -3.1, "y": -4.87 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": 29.67 }, + { "time": 0.2, "angle": 45.07 }, + { "time": 0.4333, "angle": -4.35 }, + { "time": 0.7667, "angle": 61.69 }, + { "time": 0.8, "angle": 82.6 }, + { "time": 0.8667, "angle": 80.06 }, + { "time": 1.0333, "angle": 57.56 }, + { "time": 1.1333, "angle": 80.06 }, + { "time": 1.3333, "angle": 29.67 } + ] + }, + "neck": { + "rotate": [ + { "angle": 24.91 }, + { "time": 0.2, "angle": 16.32 }, + { "time": 0.4333, "angle": 7.45 }, + { "time": 0.7333, "angle": -20.35 }, + { "time": 0.8333, "angle": -0.69, "curve": "stepped" }, + { "time": 1.1333, "angle": -0.69 }, + { "time": 1.3333, "angle": 24.91 } + ] + }, + "head": { + "rotate": [ + { "angle": 24.92 }, + { "time": 0.2, "angle": 10.36 }, + { "time": 0.4333, "angle": 28.65 }, + { "time": 0.7333, "angle": -2.66 }, + { "time": 0.8333, "angle": -28.94, "curve": "stepped" }, + { "time": 1.1333, "angle": -28.94 }, + { "time": 1.3333, "angle": 24.92 } + ] + }, + "hip": { + "translate": [ + { "x": -34.52, "y": -78.63, "curve": 0.233, "c2": 1.01, "c3": 0.75 }, + { + "time": 0.2, + "x": -34.52, + "y": 182.51, + "curve": 0.232, + "c2": 0.48, + "c3": 0.599, + "c4": 0.79 + }, + { + "time": 0.7667, + "x": -34.52, + "y": 596.22, + "curve": 0.33, + "c2": 0.17, + "c3": 0.661, + "c4": 0.22 + }, + { "time": 1.1333, "x": -34.52, "y": 2.5 }, + { "time": 1.3333, "x": -34.52, "y": -78.63 } + ] + }, + "front-shin": { + "rotate": [ + { "angle": -90.63, "curve": 0.416, "c2": 0.55, "c3": 0.743 }, + { "time": 0.2, "angle": -10.52, "curve": 0.644, "c2": 0.01, "c3": 0.75 }, + { "time": 0.4333, "angle": -127.72 }, + { "time": 0.7333, "angle": -19.92 }, + { "time": 0.8333, "angle": -5.17 }, + { "time": 0.9333, "angle": -35.06 }, + { "time": 1.0333, "angle": -43.97 }, + { "time": 1.1333, "angle": -5.17 }, + { "time": 1.3333, "angle": -90.63 } + ] + }, + "front-foot": { + "rotate": [ + { "angle": -0.8 }, + { "time": 0.0333, "angle": 16.28 }, + { "time": 0.0667, "angle": 23.52 }, + { "time": 0.1, "angle": 21.02 }, + { "time": 0.1333, "angle": 10.93 }, + { "time": 0.2, "angle": -38.46 }, + { "time": 0.4333, "angle": 6.62 }, + { "time": 0.7333, "angle": -11.52 }, + { "time": 1.0333, "angle": -22.92 }, + { "time": 1.3333, "angle": -0.8 } + ] + }, + "rear-foot": { + "rotate": [ + { "angle": -12.78 }, + { "time": 0.2, "angle": 17.06 }, + { "time": 0.4333, "angle": 19.45 }, + { "time": 0.7333, "angle": 2.67 }, + { "time": 1.0333, "angle": -28.5 }, + { "time": 1.3333, "angle": -12.78 } + ] + }, + "gun": { + "rotate": [ + { "angle": 6.18 }, + { "time": 0.2, "angle": 30.81 }, + { "time": 0.4333, "angle": 13.26 }, + { "time": 0.7333, "angle": 14.98 }, + { "time": 0.7667, "angle": 25.65 }, + { "time": 0.8, "angle": 20.62 }, + { "time": 0.8667, "angle": 64.53 }, + { "time": 1.0333, "angle": 8.6 }, + { "time": 1.1333, "angle": 64.53 }, + { "time": 1.3333, "angle": 6.18 } + ] + }, + "back-foot-tip": { + "rotate": [ + { "angle": -134.56 }, + { "time": 0.0667, "angle": -53.37 }, + { "time": 0.1667, "angle": 44.6 }, + { "time": 0.4333, "angle": 20.16 }, + { "time": 0.7333, "angle": 27.1 }, + { "time": 0.9667, "angle": 22.88 }, + { "time": 1.2667, "angle": -35.32 }, + { "time": 1.3333, "angle": -134.56 } + ] + }, + "front-foot-tip": { + "rotate": [ + {}, + { "time": 0.1667, "angle": -52.5 }, + { "time": 0.4333, "angle": -15.64 }, + { "time": 0.7333, "angle": 25.35 }, + { "time": 0.9667, "angle": -21.32 }, + { "time": 1.1333, "angle": -10.35 }, + { "time": 1.2, "angle": 0.81 } + ] + }, + "hair3": { + "rotate": [ + { "angle": 22.53 }, + { "time": 0.0667, "angle": 11.66 }, + { "time": 0.2, "angle": -6.59 }, + { "time": 0.6667, "angle": 9.32 }, + { "time": 1.3333, "angle": 22.53 } + ] + }, + "hair4": { + "rotate": [ + { "angle": -6.07 }, + { "time": 0.0667, "angle": 11.67 }, + { "time": 0.2, "angle": -6.57 }, + { "time": 0.3333, "angle": 10.17 }, + { "time": 0.6667, "angle": 14.76 }, + { "time": 0.8667, "angle": -33.44 }, + { "time": 1.1667, "angle": -19.29 }, + { "time": 1.3333, "angle": -6.07 } + ] + }, + "hair2": { + "rotate": [ + { "angle": 2.7 }, + { "time": 0.0667, "angle": 11.67 }, + { "time": 0.2, "angle": -6.57 }, + { "time": 0.3333, "angle": 18.94 }, + { "time": 0.6667, "angle": 23.53 }, + { "time": 0.8667, "angle": -24.67 }, + { "time": 1.1667, "angle": -10.51 }, + { "time": 1.3333, "angle": 2.7 } + ] + }, + "hair1": { + "rotate": [ + { "angle": 22.54 }, + { "time": 0.0667, "angle": 11.67 }, + { "time": 0.2, "angle": -6.57 }, + { "time": 0.6667, "angle": 9.33 }, + { "time": 1.3333, "angle": 22.54 } + ] + } + }, + "ik": { + "rear-leg-ik": [ + { "mix": 0, "bendPositive": false } + ], + "front-leg-ik": [ + { "mix": 0, "bendPositive": false } + ], + "rear-foot-ik": [ + { "mix": 0 } + ], + "front-foot-ik": [ + { "mix": 0 } + ] + }, + "events": [ + { "time": 1.1333, "name": "footstep" } + ] + }, + "portal": { + "slots": { + "portal-bg": { + "attachment": [ + { "name": "portal-bg" }, + { "time": 3.1, "name": null } + ] + }, + "portal-flare8": { + "attachment": [ + { "time": 1.2, "name": "portal-flare3" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667, "name": null } + ] + }, + "portal-flare3": { + "attachment": [ + { "time": 1.2, "name": "portal-flare3" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667, "name": null } + ] + }, + "portal-flare6": { + "attachment": [ + { "time": 1.2667, "name": "portal-flare3" }, + { "time": 1.3333, "name": null } + ] + }, + "portal-streaks1": { + "attachment": [ + { "name": "portal-streaks1" }, + { "time": 3.1, "name": null } + ] + }, + "portal-flare2": { + "attachment": [ + { "time": 1.1, "name": "portal-flare2" }, + { "time": 1.1333, "name": "portal-flare3" }, + { "time": 1.1667, "name": "portal-flare1" }, + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667, "name": null } + ] + }, + "portal-flare10": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare1" }, + { "time": 1.2667, "name": "portal-flare3" }, + { "time": 1.3, "name": null } + ] + }, + "portal-flare7": { + "attachment": [ + { "time": 1.1333, "name": "portal-flare2" }, + { "time": 1.1667, "name": null } + ] + }, + "portal-flare1": { + "attachment": [ + { "time": 1.1, "name": "portal-flare1" }, + { "time": 1.1333, "name": "portal-flare2" }, + { "time": 1.1667, "name": "portal-flare3" }, + { "time": 1.2, "name": "portal-flare1" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3333, "name": null } + ] + }, + "portal-flare5": { + "attachment": [ + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3333, "name": null } + ] + }, + "portal-shade": { + "attachment": [ + { "name": "portal-shade" }, + { "time": 3.1, "name": null } + ] + }, + "portal-streaks2": { + "attachment": [ + { "name": "portal-streaks2" }, + { "time": 3.1, "name": null } + ] + }, + "portal-flare9": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3, "name": null } + ] + }, + "portal-flare4": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare1" }, + { "time": 1.2667, "name": "portal-flare2" }, + { "time": 1.3333, "name": null } + ] + }, + "clipping": { + "attachment": [ + { "name": "clipping" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "portal-root": { + "translate": [ + { "x": -458.35, "y": 105.19, "curve": 0.934, "c2": 0.07, "c3": 0.671, "c4": 0.99 }, + { "time": 1, "x": -448.03, "y": 105.19 }, + { "time": 2.5, "x": -431.97, "y": 105.19, "curve": 0.426, "c3": 0.747, "c4": 0.41 }, + { "time": 3.1, "x": -457.42, "y": 105.19 } + ], + "scale": [ + { "x": 0.003, "y": 0.006, "curve": 0.823, "c2": 0.24, "c3": 0.867, "c4": 0.66 }, + { + "time": 0.4, + "x": 0.175, + "y": 0.387, + "curve": 0.727, + "c2": 1.8, + "c3": 0.671, + "c4": 0.99 + }, + { "time": 1, "x": 0.645, "y": 1.426 }, + { "time": 1.2333, "x": 0.685, "y": 1.516 }, + { "time": 1.6, "x": 0.634, "y": 1.401 }, + { "time": 1.9667, "x": 0.67, "y": 1.481 }, + { "time": 2.2, "x": 0.688, "y": 1.522 }, + { "time": 2.5, "x": 0.645, "y": 1.426, "curve": 0.98, "c2": -0.26, "c3": 0.717 }, + { "time": 3.1, "x": 0.007, "y": 0.015 } + ] + }, + "portal-streaks1": { + "rotate": [ + {}, + { "time": 0.3333, "angle": 120 }, + { "time": 0.6667, "angle": -120 }, + { "time": 1 }, + { "time": 1.3333, "angle": 120 }, + { "time": 1.6667, "angle": -120 }, + { "time": 2 }, + { "time": 2.3333, "angle": 120 }, + { "time": 2.6667, "angle": -120 }, + { "time": 3 }, + { "time": 3.3333, "angle": 120 } + ], + "translate": [ + { "x": 15.15, "curve": 0.243, "c3": 0.649, "c4": 0.6 }, + { "time": 0.6667, "x": 10.9, "y": -6.44, "curve": 0.382, "c2": 0.57, "c3": 0.735 }, + { "time": 1, "x": 9.21, "y": -8.66 }, + { "time": 1.3333, "x": 21.53, "y": -3.19 }, + { "time": 2, "x": 9.21, "y": 6.26 }, + { "time": 2.5667, "x": 9.21, "y": -0.8 }, + { "time": 2.9333, "x": 9.21, "y": -8.91 } + ], + "scale": [ + { "curve": 0.25, "c3": 0.75 }, + { "time": 0.6667, "x": 1.053, "y": 1.053, "curve": 0.25, "c3": 0.75 }, + { "time": 1.3333, "x": 0.986, "y": 0.986, "curve": 0.25, "c3": 0.75 }, + { "time": 2, "x": 1.053, "y": 1.053 } + ] + }, + "portal-streaks2": { + "rotate": [ + {}, + { "time": 0.6667, "angle": 120 }, + { "time": 1.3333, "angle": -120 }, + { "time": 2 }, + { "time": 2.6667, "angle": 120 }, + { "time": 3.3333, "angle": -120 } + ], + "translate": [ + { "x": -2.11 }, + { "time": 1, "x": -2.11, "y": 6.63 }, + { "time": 1.9333, "x": -2.11 } + ], + "scale": [ + { "x": 1.014, "y": 1.014 } + ] + }, + "portal-shade": { + "translate": [ + { "x": -29.68 } + ], + "scale": [ + { "x": 0.714, "y": 0.714 } + ] + }, + "portal": { + "rotate": [ + {}, + { "time": 0.6667, "angle": 120 }, + { "time": 1.3333, "angle": -120 }, + { "time": 2 }, + { "time": 2.6667, "angle": 120 }, + { "time": 3.3333, "angle": -120 } + ] + }, + "clipping": { + "translate": [ + { "x": -476.55, "y": 2.27 } + ], + "scale": [ + { "x": 0.983, "y": 1.197 } + ] + }, + "hip": { + "rotate": [ + { "time": 1.0667, "angle": 22.74 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { "time": 1.0667, "x": -694.16, "y": 183.28 }, + { "time": 1.1333, "x": -509.15, "y": 83.28 }, + { "time": 1.2333, "x": -316.97, "y": 37.07 }, + { "time": 1.4, "x": -160.9, "y": -90.39 }, + { "time": 1.6, "x": -102.86, "y": -94.33, "curve": 0.596, "c2": 0.01, "c3": 0.75 }, + { "time": 2.1333, "x": -7.2, "y": -31.12, "curve": 0.205, "c3": 0.75 }, + { "time": 2.6, "x": -5.34, "y": -36.81, "curve": 0.591, "c3": 0.642 }, + { "time": 3.6, "x": -7.16, "y": -24.48 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "time": 1.0667, "angle": 41.6, "curve": "stepped" }, + { "time": 1.2333, "angle": 41.6 }, + { "time": 1.3333, "angle": 20.8 }, + { "time": 1.4, "angle": 19.02 }, + { "time": 1.4333, "angle": -0.28 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { "time": 1.0667, "x": -591.13, "y": 438.46 }, + { "time": 1.1333, "x": -406.12, "y": 338.47 }, + { "time": 1.2333, "x": -214.35, "y": 255.24 }, + { "time": 1.4, "x": -8.88, "y": 15.25 }, + { "time": 1.4333, "x": 8.36, "y": 0.2, "curve": 0.216, "c2": 0.54, "c3": 0.75 }, + { "time": 1.9333, "x": 48.87 } + ] + }, + "front-foot-target": { + "rotate": [ + { "time": 1.0667, "angle": 32.08, "curve": "stepped" }, + { "time": 1.2333, "angle": 32.08 }, + { "time": 1.3333, "angle": -0.28 }, + { "time": 1.6, "angle": -34.77 }, + { "time": 1.9333, "angle": -2.15 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { "time": 1.0667, "x": -533.93, "y": 363.75 }, + { "time": 1.1333, "x": -348.92, "y": 263.76 }, + { "time": 1.2333, "x": -201.23, "y": 199.93 }, + { "time": 1.3333, "x": -109.57, "y": 0.2, "curve": 0.255, "c2": 0.48, "c3": 0.75 }, + { "time": 1.7333, "x": -69.06 } + ] + }, + "torso": { + "rotate": [ + { "time": 1.0667, "angle": 9.73, "curve": "stepped" }, + { "time": 1.2333, "angle": 9.73 }, + { "time": 1.3333, "angle": 2.88 }, + { "time": 1.4667, "angle": -73.99 }, + { "time": 1.6, "angle": -75.07, "curve": 0.392, "c2": 0.03, "c3": 0.719, "c4": 0.43 }, + { "time": 1.7333, "angle": -77.34, "curve": 0.456, "c2": 0.36, "c3": 0.68, "c4": 1.21 }, + { "time": 2.3333, "angle": -32.03 }, + { "time": 2.6, "angle": -36.79 }, + { "time": 3.6, "angle": -32.03 } + ] + }, + "neck": { + "rotate": [ + { "time": 1.0667, "angle": -3.57, "curve": "stepped" }, + { "time": 1.1333, "angle": -3.57 }, + { "time": 1.2333, "angle": -13.5 }, + { "time": 1.3333, "angle": -1.7 }, + { "time": 1.4333, "angle": 2.3 }, + { "time": 1.5667, "angle": 11.42 }, + { "time": 1.9333, "angle": 3.78, "curve": 0.269, "c3": 0.618, "c4": 0.42 }, + { "time": 2.1333, "angle": 7.93, "curve": 0.345, "c2": 0.37, "c3": 0.757 }, + { "time": 2.6, "angle": 5.45, "curve": 0.25, "c3": 0.75 }, + { "time": 3.6, "angle": 3.78 } + ] + }, + "head": { + "rotate": [ + { "time": 1.0667, "angle": 16.4, "curve": "stepped" }, + { "time": 1.1333, "angle": 16.4 }, + { "time": 1.2333, "angle": 15.19 }, + { "time": 1.3333, "angle": -32.21 }, + { "time": 1.4333, "angle": 15.95 }, + { "time": 1.5667, "angle": 20.28 }, + { "time": 1.7333, "angle": 15.24 }, + { "time": 1.9333, "angle": -18.95, "curve": 0.269, "c3": 0.618, "c4": 0.42 }, + { "time": 2.1333, "angle": 2.65, "curve": 0.345, "c2": 0.37, "c3": 0.757 }, + { "time": 2.6, "angle": -4.12, "curve": 0.25, "c3": 0.75 }, + { "time": 3.6, "angle": -8.95 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "time": 1.0667, "angle": 330.49, "curve": "stepped" }, + { "time": 1.1333, "angle": 330.49 }, + { "time": 1.2333, "angle": 21.94 }, + { "time": 1.4, "angle": 8.14 }, + { "time": 1.8, "angle": -3.47, "curve": 0.673, "c2": 0.01, "c3": 0.747, "c4": 0.98 }, + { "time": 2, "angle": 39.2 }, + { "time": 2.8333, "angle": 31.41, "curve": 0.322, "c2": 0.17, "c3": 0.655, "c4": 0.5 }, + { "time": 3.6, "angle": 39.2 } + ] + }, + "back-foot-tip": { + "rotate": [ + { "time": 1.0667, "angle": 56.07, "curve": "stepped" }, + { "time": 1.1333, "angle": 56.07 }, + { "time": 1.2333, "angle": 24.68 }, + { "time": 1.3667, "angle": 30.41 }, + { "time": 1.4333, "angle": 19.18 }, + { "time": 1.5, "angle": -0.84 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "time": 1.0667, "angle": -239.74, "curve": "stepped" }, + { "time": 1.1333, "angle": -239.74 }, + { "time": 1.2333, "angle": -287.2 }, + { "time": 1.3333, "angle": -28.87 }, + { "time": 1.4667, "angle": -92.44 }, + { "time": 1.9333, "angle": -80.61 }, + { "time": 3.6, "angle": -70.59 } + ] + }, + "front-bracer": { + "rotate": [ + { "time": 1.0667, "angle": 0.66, "curve": "stepped" }, + { "time": 1.2333, "angle": 0.66 }, + { "time": 1.3333, "angle": 36.83 }, + { "time": 1.4333, "angle": 12 }, + { "time": 1.5, "angle": -10.19 }, + { "time": 1.5667, "angle": -8 }, + { "time": 1.9333, "angle": 42.09 } + ] + }, + "front-thigh": { + "translate": [ + { "time": 1.1, "x": -6.41, "y": 18.23, "curve": "stepped" }, + { "time": 1.1333, "x": -6.41, "y": 18.23 }, + { "time": 1.2, "x": 1.61, "y": 3.66 }, + { "time": 1.2333, "x": 4.5, "y": -3.15 }, + { "time": 1.3667, "x": -3.79, "y": 2.94 }, + { "time": 1.4, "x": -8.37, "y": 8.72 }, + { "time": 1.4333, "x": -11.26, "y": 16.99 }, + { "time": 1.4667, "x": -9.89, "y": 24.73, "curve": "stepped" }, + { "time": 1.8667, "x": -9.89, "y": 24.73 }, + { "time": 2.1, "x": -4.66, "y": 10.25 } + ] + }, + "front-foot-tip": { + "rotate": [ + { "time": 1.0667, "angle": 42.55, "curve": "stepped" }, + { "time": 1.1333, "angle": 42.55 }, + { "time": 1.2333, "angle": 17.71 }, + { "time": 1.3667, "angle": 3.63 }, + { "time": 1.4333, "angle": 1.45 } + ] + }, + "rear-bracer": { + "rotate": [ + { "time": 1.0667, "angle": 108.71, "curve": "stepped" }, + { "time": 1.1333, "angle": 108.71 }, + { "time": 1.2333, "angle": 64.64 }, + { "time": 1.4, "angle": 66.25 }, + { "time": 1.7, "angle": 26.39 }, + { "time": 1.8, "angle": 13.42 }, + { "time": 2 }, + { "time": 2.8333, "angle": 11.32 }, + { "time": 3.6 } + ] + }, + "front-fist": { + "rotate": [ + { "time": 1.1, "angle": 6.32 }, + { "time": 1.2 }, + { "time": 1.4667, "angle": 24.51 }, + { "time": 1.5667, "angle": -6.03 }, + { "time": 1.7, "angle": -44.92 }, + { "time": 1.9333 }, + { "time": 2.7333, "angle": 2.04 }, + { "time": 3.6 } + ], + "scale": [ + { "time": 1.9333 }, + { "time": 2.7333, "x": 0.844 }, + { "time": 3.6 } + ] + }, + "gun": { + "rotate": [ + { "time": 1.2667 }, + { "time": 1.7, "angle": 17.34 }, + { "time": 1.8, "angle": 21.99 }, + { "time": 2 }, + { "time": 2.8333, "angle": 6.53 }, + { "time": 3.6 } + ] + }, + "hair2": { + "rotate": [ + { "time": 1.0667, "angle": 26.19, "curve": "stepped" }, + { "time": 1.4333, "angle": 26.19 }, + { "time": 1.5667, "angle": -16.41, "curve": 0.664, "c3": 0.75 }, + { "time": 1.7, "angle": 7.44 }, + { "time": 1.8, "angle": 22.84 }, + { "time": 2, "angle": 35.35 }, + { "time": 2.1, "angle": 19.51 }, + { "time": 2.1667 } + ] + }, + "hair4": { + "rotate": [ + { "time": 1.0667, "angle": 26.19, "curve": "stepped" }, + { "time": 1.4333, "angle": 26.19 }, + { "time": 1.5667, "angle": -16.41, "curve": 0.664, "c3": 0.75 }, + { "time": 1.7, "angle": 7.44 }, + { "time": 1.8, "angle": 22.84 }, + { "time": 2, "angle": 35.35 }, + { "time": 2.1, "angle": 19.51 }, + { "time": 2.1667 } + ] + }, + "hair3": { + "rotate": [ + { "time": 1.4333 }, + { "time": 1.5667, "angle": -8.68, "curve": 0.664, "c3": 0.75 }, + { "time": 1.7 } + ] + }, + "hair1": { + "rotate": [ + { "time": 1.4333 }, + { "time": 1.5667, "angle": -8.68, "curve": 0.664, "c3": 0.75 }, + { "time": 1.7 } + ] + }, + "flare1": { + "rotate": [ + { "time": 1.1, "angle": 8.2 } + ], + "translate": [ + { "time": 1.1, "x": -19.97, "y": 149.68 }, + { "time": 1.2, "x": 3.85, "y": 152.43 }, + { "time": 1.2333, "x": -15.42, "y": 152.29 } + ], + "scale": [ + { "time": 1.1, "x": 0.805, "y": 0.805 }, + { "time": 1.1667, "x": 1.279, "y": 0.605 }, + { "time": 1.2, "x": 2.151, "y": 0.805 }, + { "time": 1.2333, "x": 1.608, "y": 0.805 }, + { "time": 1.3, "x": 0.547, "y": 0.416 } + ], + "shear": [ + { "time": 1.1, "y": 4.63 }, + { "time": 1.2333, "x": -5.74, "y": 4.63 } + ] + }, + "flare2": { + "rotate": [ + { "time": 1.1, "angle": 12.29 } + ], + "translate": [ + { "time": 1.1, "x": -8.63, "y": 132.96 }, + { "time": 1.2, "x": 4.35, "y": 132.93 } + ], + "scale": [ + { "time": 1.1, "x": 0.864, "y": 0.864 }, + { "time": 1.1667, "x": 0.945, "y": 0.945 }, + { "time": 1.2, "x": 1.511, "y": 1.081 } + ], + "shear": [ + { "time": 1.1, "y": 24.03 } + ] + }, + "flare3": { + "rotate": [ + { "time": 1.1667, "angle": 2.88 } + ], + "translate": [ + { "time": 1.1667, "x": 3.24, "y": 114.81 } + ], + "scale": [ + { "time": 1.1667, "x": 0.668, "y": 0.668 } + ], + "shear": [ + { "time": 1.1667, "y": 38.59 } + ] + }, + "flare4": { + "rotate": [ + { "time": 1.1667, "angle": -8.64 } + ], + "translate": [ + { "time": 1.1667, "x": -3.82, "y": 194.06 }, + { "time": 1.2667, "x": -1.82, "y": 198.47, "curve": "stepped" }, + { "time": 1.3, "x": -1.94, "y": 187.81 } + ], + "scale": [ + { "time": 1.1667, "x": 0.545, "y": 0.545 }, + { "time": 1.2667, "x": 0.757, "y": 0.757 } + ], + "shear": [ + { "time": 1.1667, "x": 7.42, "y": -22.04 } + ] + }, + "flare5": { + "translate": [ + { "time": 1.2, "x": -11.17, "y": 176.42 }, + { "time": 1.2333, "x": -8.56, "y": 179.04, "curve": "stepped" }, + { "time": 1.3, "x": -14.57, "y": 168.69 } + ], + "scale": [ + { "time": 1.2333, "x": 1.146 }, + { "time": 1.3, "x": 0.703, "y": 0.61 } + ], + "shear": [ + { "time": 1.2, "x": 6.9 } + ] + }, + "flare6": { + "rotate": [ + { "time": 1.2333, "angle": -5.36 }, + { "time": 1.2667, "angle": -0.54 } + ], + "translate": [ + { "time": 1.2333, "x": 14.52, "y": 204.67 }, + { "time": 1.2667, "x": 19.16, "y": 212.9, "curve": "stepped" }, + { "time": 1.3, "x": 9.23, "y": 202.85 } + ], + "scale": [ + { "time": 1.2333, "x": 0.777, "y": 0.49 }, + { "time": 1.2667, "x": 0.777, "y": 0.657 }, + { "time": 1.3, "x": 0.475, "y": 0.401 } + ] + }, + "flare7": { + "rotate": [ + { "time": 1.1, "angle": 5.98 }, + { "time": 1.1333, "angle": 32.82 } + ], + "translate": [ + { "time": 1.1, "x": -6.34, "y": 112.98 }, + { "time": 1.1333, "x": 2.66, "y": 111.6 } + ], + "scale": [ + { "time": 1.1, "x": 0.588, "y": 0.588 } + ], + "shear": [ + { "time": 1.1333, "x": -19.93 } + ] + }, + "flare8": { + "rotate": [ + { "time": 1.2333, "angle": -6.85 } + ], + "translate": [ + { "time": 1.1667, "x": 66.67, "y": 125.52, "curve": "stepped" }, + { "time": 1.2, "x": 58.24, "y": 113.53, "curve": "stepped" }, + { "time": 1.2333, "x": 40.15, "y": 114.69 } + ], + "scale": [ + { "time": 1.1667, "x": 1.313, "y": 1.203 }, + { "time": 1.2333, "x": 1.038, "y": 0.95 } + ], + "shear": [ + { "time": 1.2, "y": -13.01 } + ] + }, + "flare9": { + "rotate": [ + { "time": 1.1667, "angle": 2.9 } + ], + "translate": [ + { "time": 1.1667, "x": 28.45, "y": 151.35, "curve": "stepped" }, + { "time": 1.2, "x": 48.8, "y": 191.09, "curve": "stepped" }, + { "time": 1.2333, "x": 52, "y": 182.52, "curve": "stepped" }, + { "time": 1.2667, "x": 77.01, "y": 195.96 } + ], + "scale": [ + { "time": 1.1667, "x": 0.871, "y": 1.073 }, + { "time": 1.2, "x": 0.927, "y": 0.944 }, + { "time": 1.2333, "x": 1.165, "y": 1.336 } + ], + "shear": [ + { "time": 1.1667, "x": 7.95, "y": 25.48 } + ] + }, + "flare10": { + "rotate": [ + { "time": 1.1667, "angle": 2.18 } + ], + "translate": [ + { "time": 1.1667, "x": 55.64, "y": 137.64, "curve": "stepped" }, + { "time": 1.2, "x": 90.49, "y": 151.07, "curve": "stepped" }, + { "time": 1.2333, "x": 114.06, "y": 153.05, "curve": "stepped" }, + { "time": 1.2667, "x": 90.44, "y": 164.61 } + ], + "scale": [ + { "time": 1.1667, "x": 2.657, "y": 0.891 }, + { "time": 1.2, "x": 3.314, "y": 1.425 }, + { "time": 1.2333, "x": 2.871, "y": 0.924 }, + { "time": 1.2667, "x": 2.317, "y": 0.775 } + ], + "shear": [ + { "time": 1.1667, "x": -1.35 } + ] + } + }, + "deform": { + "default": { + "torso": { + "torso": [ + { "time": 1.3333 }, + { + "time": 1.4667, + "offset": 26, + "vertices": [ -6.5248, 6.64212, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.65784, 8.28917, 0.65787, 8.28917, 1.41232, 5.06703, 1.41235, 5.067, 0, 0, 0, 0, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, -0.91647, 9.00049, -0.9164, 9.00037, 1.76997, 9.34928, -1.01155, 7.51457, -1.01145, 7.51462 ], + "curve": "stepped" + }, + { + "time": 1.8333, + "offset": 26, + "vertices": [ -6.5248, 6.64212, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.65784, 8.28917, 0.65787, 8.28917, 1.41232, 5.06703, 1.41235, 5.067, 0, 0, 0, 0, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, -0.91647, 9.00049, -0.9164, 9.00037, 1.76997, 9.34928, -1.01155, 7.51457, -1.01145, 7.51462 ] + }, + { "time": 2 } + ] + } + } + } + }, + "run": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { "angle": 42.05, "curve": 0.196, "c2": 0.86, "c3": 0.75 }, + { "time": 0.0667, "angle": 46.08 }, + { "time": 0.1333, "angle": -20.29 }, + { "time": 0.2, "angle": -27.24 }, + { "time": 0.2667, "angle": -47.17 }, + { "time": 0.3333, "angle": -39.79 }, + { "time": 0.4, "angle": -25.86 }, + { "time": 0.4667, "angle": 14.35 }, + { "time": 0.5333, "angle": 55.63 }, + { "time": 0.6, "angle": 69.65 }, + { "time": 0.6667, "angle": 86.41 }, + { "time": 0.7333, "angle": 65.88 }, + { "time": 0.8, "angle": 42.05 } + ], + "translate": [ + {}, + { "time": 0.0333, "x": -5.8, "y": 11.16 }, + { "time": 0.0667, "x": -5.13, "y": 11.55 }, + { "time": 0.1333, "x": -7.7, "y": 8.99 }, + { "time": 0.5333, "x": -1.26, "y": 3.83 }, + { "time": 0.8 } + ] + }, + "torso": { + "rotate": [ + { "angle": -39.71 }, + { "time": 0.2, "angle": -57.29 }, + { "time": 0.4, "angle": -39.71 }, + { "time": 0.6, "angle": -57.29 }, + { "time": 0.8, "angle": -39.71 } + ] + }, + "rear-thigh": { + "rotate": [ + { "angle": -56.59 }, + { "time": 0.0667, "angle": -21.57 }, + { "time": 0.1333, "angle": 27.95 }, + { "time": 0.2, "angle": 42.43 }, + { "time": 0.2667, "angle": 62.37 }, + { "time": 0.3333, "angle": 45.43 }, + { "time": 0.4, "angle": 15.67 }, + { "time": 0.4667, "angle": 28.22 }, + { "time": 0.5333, "angle": -38.62 }, + { "time": 0.6, "angle": -53.27 }, + { "time": 0.6667, "angle": -79.31 }, + { "time": 0.7333, "angle": -86.47 }, + { "time": 0.8, "angle": -56.59 } + ], + "translate": [ + {}, + { "time": 0.4, "x": -6.76, "y": -3.86 }, + { "time": 0.4333, "x": -15.85, "y": 7.28 }, + { "time": 0.4667, "x": -13.05, "y": 4.05 }, + { "time": 0.5, "x": -10.25, "y": 7.11 }, + { "time": 0.5333, "x": -9.02, "y": -5.15 }, + { "time": 0.6667, "x": -23.18, "y": -2.58 }, + { "time": 0.8 } + ] + }, + "rear-shin": { + "rotate": [ + { "angle": -74 }, + { "time": 0.0667, "angle": -83.38 }, + { "time": 0.1333, "angle": -106.7 }, + { "time": 0.2, "angle": -66.01 }, + { "time": 0.2667, "angle": -55.22 }, + { "time": 0.3333, "angle": -24.8 }, + { "time": 0.4, "angle": 18.44, "curve": 0.25, "c3": 0.75 }, + { "time": 0.4667, "angle": -56.65 }, + { "time": 0.5333, "angle": -11.95, "curve": 0.25, "c3": 0.75 }, + { "time": 0.6667, "angle": -41.27 }, + { "time": 0.7333, "angle": -43.61 }, + { "time": 0.8, "angle": -74 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "angle": -89.37 }, + { "time": 0.0667, "angle": -95.67 }, + { "time": 0.1333, "angle": -22.01 }, + { "time": 0.2, "angle": -316.04 }, + { "time": 0.2667, "angle": -274.94 }, + { "time": 0.3333, "angle": -273.74 }, + { "time": 0.4, "angle": -272.09 }, + { "time": 0.4667, "angle": -264.9 }, + { "time": 0.5333, "angle": -320.1 }, + { "time": 0.6, "angle": -50.84 }, + { "time": 0.6667, "angle": -81.73 }, + { "time": 0.7333, "angle": -83.92 }, + { "time": 0.8, "angle": -89.37 } + ], + "translate": [ + { "x": 6.25, "y": 10.05 }, + { "time": 0.2667, "x": 4.96, "y": -13.13 }, + { "time": 0.6, "x": -2.43, "y": 1.95 }, + { "time": 0.8, "x": 6.25, "y": 10.05 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": 33.44 }, + { "time": 0.0667, "angle": 20.54 }, + { "time": 0.1333, "angle": 15.26 }, + { "time": 0.2, "angle": 19.29 }, + { "time": 0.2667, "angle": 22.62 }, + { "time": 0.3333, "angle": 37.29 }, + { "time": 0.4, "angle": 41.53 }, + { "time": 0.4667, "angle": 31.74 }, + { "time": 0.5333, "angle": 67.45 }, + { "time": 0.6667, "angle": 39.77 }, + { "time": 0.7333, "angle": 30.95 }, + { "time": 0.8, "angle": 33.44 } + ] + }, + "front-fist": { + "rotate": [ + { "angle": -19.76 }, + { "time": 0.0667, "angle": -37.11 }, + { "time": 0.1333, "angle": -50.8 }, + { "time": 0.2667, "angle": -12.69 }, + { "time": 0.3333, "angle": 3.01 }, + { "time": 0.4333, "angle": 12.06 }, + { "time": 0.5333, "angle": 13.26 }, + { "time": 0.8, "angle": -19.76 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 68.68 }, + { "time": 0.0667, "angle": 73.89 }, + { "time": 0.1333, "angle": -9.64 }, + { "time": 0.2, "angle": 284.28 }, + { "time": 0.2667, "angle": 283.29 }, + { "time": 0.3333, "angle": 278.29 }, + { "time": 0.4, "angle": 271.03 }, + { "time": 0.4667, "angle": 263.2 }, + { "time": 0.5333, "angle": 314.26 }, + { "time": 0.6, "angle": 16.83 }, + { "time": 0.6667, "angle": 70.35 }, + { "time": 0.7333, "angle": 73.54 }, + { "time": 0.8, "angle": 68.68 } + ], + "translate": [ + { "x": -2.57, "y": -8.89 }, + { "time": 0.1333, "x": -4.68, "y": 7.21 }, + { "time": 0.6, "x": 4.33, "y": 2.06 }, + { "time": 0.8, "x": -2.57, "y": -8.89 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": 31.05 }, + { "time": 0.0667, "angle": 28.28 }, + { "time": 0.1333, "angle": 49.36 }, + { "time": 0.2, "angle": 59.37 }, + { "time": 0.2667, "angle": 8.56 }, + { "time": 0.3333, "angle": 9.39 }, + { "time": 0.4, "angle": 11.51 }, + { "time": 0.4667, "angle": 7.22 }, + { "time": 0.5333, "angle": -18.44 }, + { "time": 0.6, "angle": 11.45 }, + { "time": 0.6667, "angle": 9.99 }, + { "time": 0.7333, "angle": 8.29 }, + { "time": 0.8, "angle": 31.05 } + ] + }, + "neck": { + "rotate": [ + { "angle": 11.03 }, + { "time": 0.2, "angle": 13.59 }, + { "time": 0.4, "angle": 11.03 }, + { "time": 0.6, "angle": 13.59 }, + { "time": 0.8, "angle": 11.03 } + ] + }, + "head": { + "rotate": [ + { "angle": 14.73 }, + { "time": 0.1, "angle": 12.35 }, + { "time": 0.2, "angle": 25.55 }, + { "time": 0.4, "angle": 11.03 }, + { "time": 0.5, "angle": 12.35 }, + { "time": 0.6, "angle": 25.55 }, + { "time": 0.8, "angle": 14.73 } + ] + }, + "front-shin": { + "rotate": [ + { "curve": 0.481, "c2": 0.01, "c3": 0.75 }, + { "time": 0.0667, "angle": -64.42 }, + { "time": 0.1333, "angle": -20.6, "curve": 0.25, "c3": 0.75 }, + { "time": 0.2667, "angle": -62.52 }, + { "time": 0.3333, "angle": -79.75 }, + { "time": 0.4, "angle": -78.28 }, + { "time": 0.4667, "angle": -118.96, "curve": 0.93, "c2": 0.01, "c3": 0.953, "c4": 0.95 }, + { "time": 0.6, "angle": -88.96 }, + { "time": 0.6667, "angle": -79.1 }, + { "time": 0.7333, "angle": -47.78 }, + { "time": 0.8 } + ] + }, + "front-foot": { + "rotate": [ + {}, + { "time": 0.0333, "angle": -21.13, "curve": 0.121, "c2": 0.24, "c3": 0.75 }, + { "time": 0.0667, "angle": 17.64 }, + { "time": 0.1, "angle": 29.93 }, + { "time": 0.1333, "angle": 16.45 }, + { "time": 0.2, "angle": -29.23 }, + { "time": 0.2667, "angle": -1.62 }, + { "time": 0.3333, "angle": -10.23 }, + { "time": 0.4667, "angle": -15.99 }, + { "time": 0.6, "angle": 9.03 }, + { "time": 0.7333, "angle": 17.33 }, + { "time": 0.8 } + ] + }, + "rear-foot": { + "rotate": [ + {}, + { "time": 0.0667, "angle": -12.04 }, + { "time": 0.1333, "angle": -0.87 }, + { "time": 0.2, "angle": 25.81 }, + { "time": 0.2667, "angle": 4.71 }, + { "time": 0.4, "angle": 18.09, "curve": 0.281, "c2": 0.74, "c3": 0.75 }, + { "time": 0.4333, "angle": -1.71 }, + { "time": 0.4667, "angle": 27.13 }, + { "time": 0.5, "angle": 38.84 }, + { "time": 0.5333, "angle": 30.77 }, + { "time": 0.5667, "angle": -20.49 }, + { "time": 0.6, "angle": -30.81 }, + { "time": 0.6667, "angle": -1.32 }, + { "time": 0.8 } + ] + }, + "gun": { + "rotate": [ + {}, + { "time": 0.1333, "angle": 24.73 }, + { "time": 0.5, "angle": -11.88 }, + { "time": 0.8 } + ] + }, + "hip": { + "translate": [ + { "y": -24.88, "curve": 0.301, "c2": 0.8, "c3": 0.663, "c4": 0.91 }, + { "time": 0.0667, "y": -40.28, "curve": 0.456, "c3": 0.339, "c4": 0.99 }, + { "time": 0.2667, "y": 20.51, "curve": 0.17, "c2": 0.53, "c3": 0.597, "c4": 0.99 }, + { "time": 0.4, "y": -24.88 }, + { "time": 0.4333, "y": -26.36 }, + { "time": 0.4667, "y": -45.06, "curve": 0.25, "c3": 0.75 }, + { "time": 0.6667, "y": 20.51 }, + { "time": 0.8, "y": -24.88 } + ] + }, + "front-foot-target": { + "rotate": [ + {}, + { "time": 0.0333, "angle": -41.68 }, + { "time": 0.1333, "angle": -102.42 }, + { "time": 0.2, "angle": -121.44 }, + { "time": 0.2333, "angle": -133.6 }, + { "time": 0.2667, "angle": -139.86 }, + { "time": 0.3333, "angle": -152.4 }, + { "time": 0.3667, "angle": -146.32 }, + { "time": 0.5, "angle": -143.8 }, + { "time": 0.5333, "angle": -114.84 }, + { "time": 0.5667, "angle": -99.09 }, + { "time": 0.6, "angle": -63.03 }, + { "time": 0.6333, "angle": -47.35 }, + { "time": 0.6667, "angle": -31.04 }, + { "time": 0.7, "angle": -25.02 }, + { "time": 0.7667, "angle": -15.95 }, + { "time": 0.8 } + ], + "translate": [ + { "x": 159.32, "y": 38.68 }, + { "time": 0.0333, "x": 115.32, "y": 0.18 }, + { "time": 0.0667, "x": 16.34, "y": 0.18 }, + { "time": 0.1333, "x": -116.47, "y": 0.18 }, + { "time": 0.2, "x": -210.62, "y": 126.29 }, + { "time": 0.2333, "x": -226.12, "y": 203.77 }, + { "time": 0.2667, "x": -223.74, "y": 258.01 }, + { "time": 0.3333, "x": -208.24, "y": 250.26 }, + { "time": 0.3667, "x": -207.64, "y": 215.69 }, + { "time": 0.4, "x": -205.86, "y": 185.3 }, + { "time": 0.4333, "x": -179.04, "y": 176.95 }, + { "time": 0.4667, "x": -154, "y": 157.28 }, + { "time": 0.5, "x": -128.97, "y": 108.41 }, + { "time": 0.5333, "x": -76.68, "y": 75.29 }, + { "time": 0.5667, "x": -41.24, "y": 67.74 }, + { "time": 0.6, "x": 28.48, "y": 59.03 }, + { "time": 0.6333, "x": 70.89, "y": 78.2 }, + { "time": 0.6667, "x": 110.42, "y": 99 }, + { "time": 0.7, "x": 122.21, "y": 79.59 }, + { "time": 0.7667, "x": 145.33, "y": 44.62 }, + { "time": 0.8, "x": 159.32, "y": 38.68 } + ] + }, + "front-leg-target": { + "translate": [ + { "x": -14.25, "y": -25.96 }, + { "time": 0.1333, "x": -13.64, "y": -34.72 }, + { "time": 0.1667, "x": -11.42, "y": -12.61 }, + { "time": 0.5, "x": -14.89, "y": -31.79 }, + { "time": 0.8, "x": -14.25, "y": -25.96 } + ] + }, + "rear-foot-target": { + "rotate": [ + {}, + { "time": 0.0667, "angle": 18.55 }, + { "time": 0.1333, "angle": 52.76 }, + { "time": 0.1667, "angle": 87.4 }, + { "time": 0.2333, "angle": 133.95 }, + { "time": 0.3, "angle": 150.92 }, + { "time": 0.3667, "angle": 168.02 }, + { "time": 0.4, "angle": 129.09 }, + { "time": 0.4333, "angle": 125.95 }, + { "time": 0.5, "angle": 114.27 }, + { "time": 0.5333, "angle": 85.37 }, + { "time": 0.5667, "angle": 49.18 }, + { "time": 0.6333, "angle": 9.51 }, + { "time": 0.7, "angle": 4.15 }, + { "time": 0.7667, "angle": -1.37 }, + { "time": 0.8 } + ], + "translate": [ + { "x": -248.9, "y": 230.07 }, + { "time": 0.0667, "x": -228.7, "y": 134.12 }, + { "time": 0.1333, "x": -145.38, "y": 94.22 }, + { "time": 0.1667, "x": -82.76, "y": 54.33 }, + { "time": 0.2333, "x": 37.93, "y": 74.39 }, + { "time": 0.2667, "x": 80.38, "y": 91.82 }, + { "time": 0.3, "x": 93.21, "y": 67.3 }, + { "time": 0.3667, "x": 99.34, "y": 35.47 }, + { "time": 0.4, "x": 68.63, "y": 0.35 }, + { "time": 0.4333, "x": 21.58, "y": -2.64 }, + { "time": 0.5, "x": -92.91, "y": -2.64 }, + { "time": 0.5333, "x": -166.79, "y": -2.64 }, + { "time": 0.5667, "x": -252.52, "y": 57.15 }, + { "time": 0.6333, "x": -304.32, "y": 214.03 }, + { "time": 0.7, "x": -296.92, "y": 281.37 }, + { "time": 0.7667, "x": -269.54, "y": 257.69 }, + { "time": 0.8, "x": -248.9, "y": 230.07 } + ] + }, + "rear-leg-target": { + "translate": [ + { "x": 85, "y": -33.59 } + ] + }, + "back-foot-tip": { + "rotate": [ + { "angle": -151.52 }, + { "time": 0.1333, "angle": -93.33 }, + { "time": 0.1667, "angle": -70.78 }, + { "time": 0.2333, "angle": 22.43 }, + { "time": 0.3, "angle": 36.86 }, + { "time": 0.3667, "angle": 34.85 }, + { "time": 0.4, "angle": 0.77 }, + { "time": 0.4333, "angle": 0.83, "curve": "stepped" }, + { "time": 0.5333, "angle": 0.83 }, + { "time": 0.5667, "angle": -61.7 }, + { "time": 0.6333, "angle": -139.59 }, + { "time": 0.7, "angle": -146.79 }, + { "time": 0.8, "angle": -151.52 } + ] + }, + "front-foot-tip": { + "rotate": [ + { "angle": 42.2 }, + { "time": 0.0333, "angle": -0.24 }, + { "time": 0.1333, "angle": -0.28 }, + { "time": 0.1667, "angle": -59.58 }, + { "time": 0.2, "angle": -112.55 }, + { "time": 0.2667, "angle": -130.08 }, + { "time": 0.3333, "angle": -146.2 }, + { "time": 0.5, "angle": -86.49 }, + { "time": 0.5333, "angle": -86.99 }, + { "time": 0.5667, "angle": -66.87 }, + { "time": 0.6, "angle": -22.9 }, + { "time": 0.6333, "angle": -12.07 }, + { "time": 0.7, "angle": 35.4 }, + { "time": 0.8, "angle": 42.2 } + ] + }, + "hair1": { + "rotate": [ + {}, + { "time": 0.1, "angle": -10.22 }, + { "time": 0.2667, "angle": 7.16 }, + { "time": 0.3667, "angle": -0.15 }, + { "time": 0.4667, "angle": -10.22 }, + { "time": 0.6333, "angle": 7.16 }, + { "time": 0.7333, "angle": -0.15 }, + { "time": 0.8 } + ] + }, + "hair2": { + "rotate": [ + {}, + { "time": 0.1, "angle": -10.22 }, + { "time": 0.1667, "angle": -30.13 }, + { "time": 0.2667, "angle": 6.38 }, + { "time": 0.3667, "angle": -13.49 }, + { "time": 0.4667, "angle": -10.22 }, + { "time": 0.5333, "angle": -30.13 }, + { "time": 0.6333, "angle": 6.38 }, + { "time": 0.7333, "angle": -13.49 }, + { "time": 0.8 } + ] + }, + "hair3": { + "rotate": [ + {}, + { "time": 0.1, "angle": -10.22 }, + { "time": 0.2667, "angle": 7.16 }, + { "time": 0.3667, "angle": -0.15 }, + { "time": 0.4667, "angle": -10.22 }, + { "time": 0.6333, "angle": 7.16 }, + { "time": 0.7333, "angle": -0.15 }, + { "time": 0.8 } + ] + }, + "hair4": { + "rotate": [ + {}, + { "time": 0.1, "angle": -10.22 }, + { "time": 0.1667, "angle": -30.13 }, + { "time": 0.2667, "angle": 6.38 }, + { "time": 0.3667, "angle": -13.49 }, + { "time": 0.4667, "angle": -10.22 }, + { "time": 0.5333, "angle": -30.13 }, + { "time": 0.6333, "angle": 6.38 }, + { "time": 0.7333, "angle": -13.49 }, + { "time": 0.8 } + ] + }, + "torso2": { + "rotate": [ + { "angle": 4.52 } + ] + }, + "torso3": { + "rotate": [ + { "angle": 4.52 } + ] + } + }, + "deform": { + "default": { + "goggles": { + "goggles": [ + { + "vertices": [ -0.08838, 0.23265, -0.04028, 0.11366, -1.15417, 5.38666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82043, 3.80259, -0.0957, 0.27988, -0.11633, 0.3275, -5.76245, 7.7601, -3.05988, 10.76797, -2.18188, 10.12057, -4.92511, 9.4566, 0, 0, 0, 0, 0.65329, -3.03143, 0.55997, -2.59837, -1.40085, 6.49587, -0.16394, 0.42825, -0.14651, 0.37986, -0.13544, 0.3509, -0.11295, 0.31703, -0.12219, 0.33459, -0.12271, 0.32938, -0.10715, 0.28685, -0.90088, 4.0234, -0.04678, 0.13842, -1.0719, 4.96331, -1.06213, 4.94196, -1.04929, 4.90511, -0.04034, 0.1196, -0.07523, 0.20426, -0.10211, 0.26987, -0.12775, 0.33331, -0.13965, 0.36775, -0.14172, 0.37709, -0.13071, 0.35703, -0.11951, 0.33389, -0.14542, 0.39532, -0.16638, 0.43952, -1.40085, 6.49587, -0.82043, 3.80259, -0.82043, 3.80259, -0.82043, 3.80259, -1.82895, 8.48514, -1.82895, 8.48514, -1.82895, 8.48514 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.4, + "vertices": [ 1.7334, -8.03619, 0.70187, -3.25497, 0.39651, -1.84367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.08755, -5.04639, 3.97546, -18.45124, 0.47232, -2.1937, 1.59595, -7.39851, 2.05963, -9.54877, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.58685, -11.98995, 2.93106, -13.58876, 2.71149, -12.57045, 2.01114, -9.32378, 2.26413, -10.49626, 2.34348, -10.8643, 2.0517, -9.51168, 1.96225, -9.10095, 0.75806, -3.51469, 0.08057, -0.37485, 0.57971, -2.69226, 0.35056, -1.63069, 0.65036, -3.01589, 1.40933, -6.5339, 1.98853, -9.21902, 4.07944, -18.92243, 3.45761, -16.03436, 3.45532, -16.02369, 2.42819, -11.25721, 2.14264, -9.93373, 2.06396, -9.5659, 2.59061, -12.00682, 0, 0, 0.47232, -2.1937, 0.47232, -2.1937, 0.47232, -2.1937, 0.47232, -2.1937, 0.47232, -2.1937, 0.47232, -2.1937 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.8, + "vertices": [ -0.08838, 0.23265, -0.04028, 0.11366, -1.15417, 5.38666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82043, 3.80259, -0.0957, 0.27988, -0.11633, 0.3275, -5.76245, 7.7601, -3.05988, 10.76797, -2.18188, 10.12057, -4.92511, 9.4566, 0, 0, 0, 0, 0.65329, -3.03143, 0.55997, -2.59837, -1.40085, 6.49587, -0.16394, 0.42825, -0.14651, 0.37986, -0.13544, 0.3509, -0.11295, 0.31703, -0.12219, 0.33459, -0.12271, 0.32938, -0.10715, 0.28685, -0.90088, 4.0234, -0.04678, 0.13842, -1.0719, 4.96331, -1.06213, 4.94196, -1.04929, 4.90511, -0.04034, 0.1196, -0.07523, 0.20426, -0.10211, 0.26987, -0.12775, 0.33331, -0.13965, 0.36775, -0.14172, 0.37709, -0.13071, 0.35703, -0.11951, 0.33389, -0.14542, 0.39532, -0.16638, 0.43952, -1.40085, 6.49587, -0.82043, 3.80259, -0.82043, 3.80259, -0.82043, 3.80259, -1.82895, 8.48514, -1.82895, 8.48514, -1.82895, 8.48514 ] + } + ] + }, + "torso": { + "torso": [ + { + "offset": 10, + "vertices": [ 6.35965, 1.33517, 6.35962, 1.33517, 6.35965, 1.33517, 6.35962, 1.33517, 0, 0, 0, 0, 0, 0, 0.82059, 5.12242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.82059, 5.12243, 0.82062, 5.12241, 0.82059, 5.12243, 0.82062, 5.12241, 1.43295, 3.92841, 1.43304, 3.92826, 0.82059, 5.12242, 0.82059, 5.12243, 0.82059, 5.12243, 0.82062, 5.12241, 0.24155, 4.36882, 0.24158, 4.36882, 0.24156, 4.36882, 0.24155, 4.36882, 0.24156, 4.36882, 3.0E-5, -1.0E-5, 0.82062, 5.12241, -0.77553, 4.89196, 0, 0, 0, 0, -0.80437, 5.76189, -0.80463, 5.76189, 0.687, 7.31474, -0.35934, 5.4162, -0.35928, 5.41616 ] + }, + { + "time": 0.4, + "offset": 2, + "vertices": [ 1.46152, 2.96601, 1.46152, 2.966, 0.68634, 3.23446, 0.68634, 3.23445, 2.20619, 0.10388, 2.20618, 0.10388, 0, 0, 0, 0, -0.31029, -2.89859, -0.31027, -2.8986, 0, 0, -0.1851, 0.38208, 0.33795, -3.61552, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0.23715, 2.56816, 0.23701, 2.56804, 0.23724, 2.56822, 0.39799, 4.23787, 0.39807, 4.23792, -0.55164, 4.21406, -0.55157, 4.21406, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, -0.29404, -8.94628, -0.29398, -8.94629, -0.02417, -9.50224, -0.02417, -9.50224, 0.23018, -9.9391, 0.23019, -9.9391, -4.64136, -8.88914, -4.64133, -8.88915, -2.62137, -9.24012, -2.62134, -9.24013, -1.70071, -5.16261, -1.70071, -5.16262, -1.70074, -5.16261, -1.70071, -5.16261, -1.70074, -5.16261, 3.0E-5, -1.0E-5, -7.37057, -10.47318, 1.06334, -5.92199, 0, 0, 0, 0, -0.49225, -2.67543, -0.49225, -2.67542, 3.36296, -7.48156, -2.08173, -6.76357, -2.08174, -6.76364 ] + }, + { + "time": 0.8, + "offset": 10, + "vertices": [ 6.35965, 1.33517, 6.35962, 1.33517, 6.35965, 1.33517, 6.35962, 1.33517, 0, 0, 0, 0, 0, 0, 0.82059, 5.12242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.82059, 5.12243, 0.82062, 5.12241, 0.82059, 5.12243, 0.82062, 5.12241, 1.43295, 3.92841, 1.43304, 3.92826, 0.82059, 5.12242, 0.82059, 5.12243, 0.82059, 5.12243, 0.82062, 5.12241, 0.24155, 4.36882, 0.24158, 4.36882, 0.24156, 4.36882, 0.24155, 4.36882, 0.24156, 4.36882, 3.0E-5, -1.0E-5, 0.82062, 5.12241, -0.77553, 4.89196, 0, 0, 0, 0, -0.80437, 5.76189, -0.80463, 5.76189, 0.687, 7.31474, -0.35934, 5.4162, -0.35928, 5.41616 ] + } + ] + }, + "mouth": { + "mouth-grind": [ + { + "vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.4, + "vertices": [ -1.86761, -2.71146, 0.01212, -11.43619, 0.01212, -11.43619, -1.86761, -2.71146 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.8, + "vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ] + } + ] + }, + "head": { + "head": [ + { + "offset": 32, + "vertices": [ 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.4, + "offset": 34, + "vertices": [ 3.14838, -14.61261, 3.14838, -14.61261, 3.14838, -14.61261, 0.83426, -3.87112, 0, 0, 0, 0, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0, 0, 0, 0, 0, 0, 0, 0, 0.55618, -2.58074, 0.41714, -1.93558, 1.04282, -4.83889 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.8, + "offset": 32, + "vertices": [ 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ] + } + ] + }, + "eye": { + "eye-indifferent": [ + { + "vertices": [ -0.15329, 0.70867, -0.15329, 0.70867, -0.15329, 0.70867, -0.15329, 0.70867 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.4, + "vertices": [ 3.92969, -18.23849, 3.92969, -18.23849, 3.92969, -18.23849, 3.92969, -18.23849 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.8, + "vertices": [ -0.15329, 0.70867, -0.15329, 0.70867, -0.15329, 0.70867, -0.15329, 0.70867 ] + } + ] + } + } + }, + "events": [ + { "name": "footstep" }, + { "time": 0.3667, "name": "footstep" } + ] + }, + "run-to-idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-foot-target": { + "translate": [ + { "x": -16.5, "y": 3.41 }, + { "time": 0.1333, "x": -69.06 } + ] + }, + "hip": { + "translate": [ + { "x": -28.78, "y": -72.96, "curve": 0.507, "c2": 0.21, "c3": 0.607 }, + { "time": 0.2667, "x": -7.16, "y": -23.15 } + ] + }, + "rear-foot-target": { + "translate": [ + { "x": 33.15, "y": 31.61 }, + { "time": 0.0667, "x": 24.41, "y": -3.54 }, + { "time": 0.2667, "x": 48.87 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "angle": -80.61 }, + { "time": 0.2667, "angle": -70.59 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": 8.79 }, + { "time": 0.2667, "angle": 42.09 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 55.3 }, + { "time": 0.2667, "angle": 39.2 } + ] + }, + "head": { + "rotate": [ + {}, + { "time": 0.2667, "angle": -8.95 } + ] + }, + "front-fist": { + "rotate": [ + { "angle": 38.26 }, + { "time": 0.2667 } + ], + "scale": [ + { "x": 0.844 }, + { "time": 0.2667 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": 57.24 }, + { "time": 0.2667 } + ] + }, + "gun": { + "rotate": [ + { "angle": 2.28 }, + { "time": 0.2667 } + ] + }, + "torso": { + "rotate": [ + { "angle": -12.98 }, + { "time": 0.2667, "angle": -8.85 } + ], + "scale": [ + { "x": 0.963, "y": 1.074, "curve": 0.25, "c3": 0.494 }, + { "time": 0.2667 } + ] + }, + "neck": { + "rotate": [ + {}, + { "time": 0.2667, "angle": 3.78 } + ] + }, + "hair3": { + "rotate": [ + {}, + { "time": 0.1333, "angle": -8.67 }, + { "time": 0.2667 } + ] + }, + "hair4": { + "rotate": [ + {}, + { "time": 0.1333, "angle": -13.07 }, + { "time": 0.2667 } + ] + }, + "hair1": { + "rotate": [ + {}, + { "time": 0.1333, "angle": -9.73 }, + { "time": 0.2667 } + ] + }, + "hair2": { + "rotate": [ + {}, + { "time": 0.1333, "angle": -0.14 }, + { "time": 0.2667 } + ] + } + } + }, + "shoot": { + "slots": { + "muzzle-ring4": { + "color": [ + { "time": 0.0333, "color": "d8baffff", "curve": 0.846, "c3": 0.903, "c4": 0.79 }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2, "name": null } + ] + }, + "muzzle-ring3": { + "color": [ + { "time": 0.0333, "color": "d8baffff", "curve": 0.846, "c3": 0.903, "c4": 0.79 }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2, "name": null } + ] + }, + "muzzle-ring": { + "color": [ + { "time": 0.0333, "color": "d8baffff", "curve": 0.846, "c3": 0.903, "c4": 0.79 }, + { "time": 0.2333, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2333, "name": null } + ] + }, + "muzzle-glow": { + "color": [ + { "color": "ff0c0c00" }, + { "time": 0.0333, "color": "ffc9adff", "curve": 0.831, "c2": 0.04, "c3": 0.899, "c4": 0.73 }, + { "time": 0.3, "color": "ff400cff" }, + { "time": 0.6333, "color": "ff0c0c00" } + ], + "attachment": [ + { "name": "muzzle-glow" } + ] + }, + "muzzle-ring2": { + "color": [ + { "time": 0.0333, "color": "d8baffff", "curve": 0.846, "c3": 0.903, "c4": 0.79 }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2, "name": null } + ] + }, + "muzzle": { + "color": [ + { "time": 0.1333, "color": "ffffffff" }, + { "time": 0.2, "color": "ffffff62" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle01" }, + { "time": 0.0667, "name": "muzzle02" }, + { "time": 0.1, "name": "muzzle03" }, + { "time": 0.1333, "name": "muzzle04" }, + { "time": 0.1667, "name": "muzzle05" }, + { "time": 0.2, "name": null } + ] + } + }, + "bones": { + "gun": { + "rotate": [ + { "time": 0.0667, "curve": 0.419, "c2": 0.64, "c3": 0.778, "c4": 0.95 }, + { "time": 0.1333, "angle": 45.35, "curve": 0.069, "c2": 0.51, "c3": 0.75 }, + { "time": 0.6333 } + ] + }, + "muzzle": { + "translate": [ + { "x": -11.02, "y": 25.16 } + ] + }, + "rear-upper-arm": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.1, "x": 4.74, "y": 9.98 }, + { "time": 0.2333 } + ] + }, + "rear-bracer": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.1, "x": -4.36, "y": -2.88 }, + { "time": 0.2333 } + ] + }, + "gun-tip": { + "translate": [ + {}, + { "time": 0.3, "x": 3.15, "y": 0.39 } + ], + "scale": [ + { "x": 0.366, "y": 0.366 }, + { "time": 0.0333, "x": 1.453, "y": 1.453 }, + { "time": 0.3, "x": 0.366, "y": 0.366 } + ] + }, + "muzzle-ring": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2333, "x": 64.47 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2333, "x": 5.951, "y": 5.951 } + ] + }, + "muzzle-ring2": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 172.57 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 4, "y": 4 } + ] + }, + "muzzle-ring3": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 277.17 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 2, "y": 2 } + ] + }, + "muzzle-ring4": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 392.06 } + ] + } + } + }, + "walk": { + "bones": { + "rear-foot-target": { + "rotate": [ + { "angle": -32.82 }, + { "time": 0.1, "angle": -77.14 }, + { "time": 0.2, "angle": -73.32 }, + { "time": 0.4333, "angle": 30.49 }, + { "time": 0.5, "angle": -0.28, "curve": "stepped" }, + { "time": 0.6667, "angle": -0.28 }, + { "time": 0.7667, "angle": -33.78 }, + { "time": 0.8667, "angle": -32.82 } + ], + "translate": [ + { "x": -167.32, "y": 0.12 }, + { "time": 0.1, "x": -205.81, "y": 42.58 }, + { + "time": 0.2, + "x": -119.04, + "y": 61.48, + "curve": 0.296, + "c2": 0.33, + "c3": 0.634, + "c4": 0.67 + }, + { "time": 0.4333, "x": 92.52, "y": 26.2 }, + { "time": 0.5, "x": 47.15, "y": -0.96 }, + { "time": 0.5333, "x": 27.23, "y": -0.86 }, + { "time": 0.6667, "x": -42.87, "y": -0.52 }, + { "time": 0.7667, "x": -110.82, "y": -0.18 }, + { "time": 0.8667, "x": -167.32, "y": 0.12 } + ] + }, + "front-foot-target": { + "rotate": [ + { "angle": 29.01 }, + { "time": 0.0667, "angle": -0.28, "curve": "stepped" }, + { "time": 0.1, "angle": -0.28 }, + { "time": 0.2 }, + { "time": 0.3333, "angle": -28.33 }, + { "time": 0.4333, "angle": -43.6 }, + { "time": 0.5333, "angle": -78.46 }, + { "time": 0.6667, "angle": -80.78 }, + { "time": 0.7667, "angle": -36.75 }, + { "time": 0.8667, "angle": 29.01 } + ], + "translate": [ + { "x": 153.74, "y": 27.82 }, + { "time": 0.0667, "x": 109.33, "y": -0.52 }, + { "time": 0.1, "x": 91.43, "y": -0.43 }, + { "time": 0.2, "x": 36.13, "y": -0.15 }, + { "time": 0.3333, "x": -38.12, "y": 0.22 }, + { "time": 0.4333, "x": -94.33, "y": 0.5 }, + { "time": 0.5333, "x": -136.78, "y": 57.05 }, + { "time": 0.6667, "x": -54.53, "y": 69.29 }, + { "time": 0.8667, "x": 153.74, "y": 27.82 } + ] + }, + "hip": { + "translate": [ + { "x": 3.42, "y": -16.2 }, + { "time": 0.1, "x": 13.57, "y": -20.63, "curve": 0.548, "c3": 0.75 }, + { "time": 0.3333, "x": 6.91, "y": 2.52, "curve": 0.25, "c3": 0.75 }, + { "time": 0.4333, "x": 6.54, "y": -14.78 }, + { "time": 0.5333, "x": 6.83, "y": -19.85, "curve": 0.548, "c3": 0.75 }, + { "time": 0.7667, "x": 6.91, "y": 2.52, "curve": 0.25, "c3": 0.75 }, + { "time": 0.8667, "x": 3.42, "y": -16.2 } + ] + }, + "front-foot-tip": { + "rotate": [ + { "angle": 28.96 }, + { "time": 0.0667, "angle": 0.82 }, + { "time": 0.1, "angle": 1.68, "curve": "stepped" }, + { "time": 0.4333, "angle": 1.68 }, + { "time": 0.5333, "angle": -59.66 }, + { "time": 0.6667, "angle": -94.92 }, + { "time": 0.7667, "angle": -35.84 }, + { "time": 0.8667, "angle": 28.96 } + ] + }, + "torso": { + "rotate": [ + { "angle": -20.72 }, + { "time": 0.2, "angle": 0.92, "curve": 0.25, "c3": 0.75 }, + { "time": 0.4333, "angle": -20.72, "curve": 0.136, "c2": 0.36, "c3": 0.75 }, + { "time": 0.6667, "angle": 0.92, "curve": 0.25, "c3": 0.75 }, + { "time": 0.8667, "angle": -20.72 } + ] + }, + "neck": { + "rotate": [ + { "angle": 18.06 }, + { "time": 0.2, "angle": 12.81, "curve": 0.25, "c3": 0.75 }, + { "time": 0.3333, "angle": 15.4 }, + { "time": 0.4333, "angle": 18.06, "curve": 0.168, "c2": 0.27, "c3": 0.75 }, + { "time": 0.6667, "angle": 12.81, "curve": 0.25, "c3": 0.75 }, + { "time": 0.7667, "angle": 15.95 }, + { "time": 0.8667, "angle": 18.06 } + ] + }, + "head": { + "rotate": [ + { "angle": 4.88 }, + { "time": 0.2, "angle": 12.81, "curve": 0.25, "c3": 0.75 }, + { "time": 0.3333, "angle": 15.4 }, + { "time": 0.4333, "angle": 18.06, "curve": 0.168, "c2": 0.27, "c3": 0.75 }, + { "time": 0.6667, "angle": 12.81, "curve": 0.25, "c3": 0.75 }, + { "time": 0.7667, "angle": 15.95 }, + { "time": 0.8667, "angle": 4.88 } + ] + }, + "back-foot-tip": { + "rotate": [ + {}, + { "time": 0.1, "angle": -59.01 }, + { "time": 0.2, "angle": -99.81 }, + { "time": 0.3333, "angle": -28.38 }, + { "time": 0.4333, "angle": 48.63 }, + { "time": 0.5, "angle": 0.85 }, + { "time": 0.8667 } + ] + }, + "front-thigh": { + "rotate": [ + { "angle": 41.32 } + ], + "translate": [ + { "x": 15.47, "y": -0.08 }, + { "time": 0.1, "x": 9.94, "y": -2.81 }, + { "time": 0.2, "x": 4.34, "y": 0.72 }, + { "time": 0.3333, "x": 0.02, "y": -1.11 }, + { "time": 0.4333, "x": -4.26, "y": 0.02 }, + { "time": 0.5333, "x": 1.53, "y": -1.94 }, + { "time": 0.6667, "x": 8.32, "y": -5.38 }, + { "time": 0.7667, "x": 6.11, "y": -4.87 }, + { "time": 0.8667, "x": 15.47, "y": -0.08 } + ] + }, + "rear-thigh": { + "rotate": [ + { "angle": -32.3 } + ], + "translate": [ + { "x": -24.88, "y": 0.12 }, + { "time": 0.2, "x": -10.72, "y": -1.15 }, + { "time": 0.4333, "x": -1.33, "y": 0.01 }, + { "time": 0.6667, "x": -16.28, "y": 0.08 }, + { "time": 0.7667, "x": -20.18, "y": 0.1 }, + { "time": 0.8667, "x": -24.88, "y": 0.12 } + ] + }, + "torso2": { + "rotate": [ + { "angle": -5 }, + { "time": 0.2, "angle": -15.91, "curve": 0.25, "c3": 0.75 }, + { "time": 0.4333, "angle": -5, "curve": 0.136, "c2": 0.36, "c3": 0.75 }, + { "time": 0.6667, "angle": -15.91, "curve": 0.25, "c3": 0.75 }, + { "time": 0.8667, "angle": -5 } + ] + }, + "torso3": { + "rotate": [ + { "angle": -4.68 }, + { "time": 0.2, "angle": -19.5, "curve": 0.25, "c3": 0.75 }, + { "time": 0.4333, "angle": -4.68, "curve": 0.136, "c2": 0.36, "c3": 0.75 }, + { "time": 0.6667, "angle": -19.5, "curve": 0.25, "c3": 0.75 }, + { "time": 0.8667, "angle": -4.68 } + ] + }, + "front-upper-arm": { + "rotate": [ + { "angle": -9.51 }, + { "time": 0.1, "angle": -19.4, "curve": 0.482, "c3": 0.645, "c4": 1.09 }, + { "time": 0.4667, "angle": -303.86, "curve": 0.25, "c3": 0.75 }, + { "time": 0.8667, "angle": -9.51 } + ], + "translate": [ + { "x": 1.46, "y": 3.5 }, + { "time": 0.2, "x": -5.92, "y": 4.93 }, + { "time": 0.4333, "x": -5.24, "y": -4.38 }, + { "time": 0.6667, "x": -7.69, "y": -8.62 }, + { "time": 0.8667, "x": 1.46, "y": 3.5 } + ] + }, + "front-bracer": { + "rotate": [ + { "angle": 1.95 }, + { "time": 0.1, "angle": 18.36, "curve": 0.246, "c3": 0.645, "c4": 1.09 }, + { "time": 0.4667, "angle": 24.83, "curve": 0.25, "c3": 0.75 }, + { "time": 0.8667, "angle": 1.95 } + ] + }, + "front-fist": { + "rotate": [ + { "angle": -28.48 }, + { "time": 0.1, "angle": -27, "curve": 0.25, "c3": 0.645, "c4": 1.09 }, + { "time": 0.3333, "angle": -33.94, "curve": 0.407, "c2": -0.01, "c3": 0.75 }, + { "time": 0.5333, "angle": 3.77, "curve": 0.25, "c3": 0.75 }, + { "time": 0.8667, "angle": -28.48 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "angle": 28.28, "curve": 0.25, "c3": 0.75 }, + { "time": 0.1333, "angle": 22.94, "curve": 0.25, "c3": 0.75 }, + { "time": 0.4333, "angle": 326.34 }, + { "time": 0.5667, "angle": 312.87, "curve": 0.407, "c2": -0.01, "c3": 0.75 }, + { "time": 0.7, "angle": -6.78, "curve": 0.407, "c2": -0.01, "c3": 0.75 }, + { "time": 0.8667, "angle": 28.28 } + ], + "translate": [ + { "x": -0.18, "y": 1.45 }, + { "time": 0.2, "x": 0.72, "y": 2.17 }, + { "time": 0.4333, "x": 16.77, "y": 19.95 }, + { "time": 0.8667, "x": -0.18, "y": 1.45 } + ] + }, + "hair2": { + "rotate": [ + { "angle": 18.54 }, + { "time": 0.1, "angle": 1.97 }, + { "time": 0.2, "angle": -5.65 }, + { "time": 0.4333, "angle": 24.96 }, + { "time": 0.6333, "angle": -6.26 }, + { "time": 0.8667, "angle": 18.54 } + ] + }, + "hair4": { + "rotate": [ + { "angle": 1.97 }, + { "time": 0.1, "angle": -5.65 }, + { "time": 0.3333, "angle": 24.96 }, + { "time": 0.5333, "angle": -6.26 }, + { "time": 0.7667, "angle": 18.54 }, + { "time": 0.8667, "angle": 1.97 } + ] + }, + "rear-bracer": { + "rotate": [ + { "angle": 10.06, "curve": 0.25, "c3": 0.75 }, + { "time": 0.1333, "angle": 11.68, "curve": 0.25, "c3": 0.75 }, + { "time": 0.4333, "angle": -3.66 }, + { "time": 0.5667, "angle": -1.27, "curve": 0.407, "c2": -0.01, "c3": 0.75 }, + { "time": 0.7, "angle": -4.16, "curve": 0.407, "c2": -0.01, "c3": 0.75 }, + { "time": 0.8667, "angle": 10.06 } + ] + }, + "gun": { + "rotate": [ + { "angle": -14.67, "curve": 0.25, "c3": 0.75 }, + { "time": 0.2333, "angle": 18.91, "curve": 0.25, "c3": 0.75 }, + { "time": 0.4333, "angle": 25.77 }, + { "time": 0.5667, "angle": 12.57, "curve": 0.407, "c2": -0.01, "c3": 0.75 }, + { "time": 0.7, "angle": -8.69, "curve": 0.407, "c2": -0.01, "c3": 0.75 }, + { "time": 0.8667, "angle": -14.67 } + ] + }, + "rear-shin": { + "rotate": [ + { "angle": -5 } + ] + }, + "rear-foot": { + "rotate": [ + { "angle": 3.52 } + ] + }, + "aim-constraint-target": { + "rotate": [ + { "angle": -3.19 } + ] + }, + "front-shin": { + "rotate": [ + { "angle": -10.44 } + ] + }, + "front-foot": { + "rotate": [ + { "angle": -0.79 } + ] + } + }, + "deform": { + "default": { + "goggles": { + "goggles": [ + { + "vertices": [ -0.08838, 0.23265, -0.04028, 0.11366, -1.15417, 5.38666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82043, 3.80259, -0.0957, 0.27988, -0.11633, 0.3275, -5.76245, 7.7601, -3.05988, 10.76797, -2.18188, 10.12057, -4.92511, 9.4566, 0, 0, 0, 0, 0.65329, -3.03143, 0.55997, -2.59837, -1.40085, 6.49587, -0.16394, 0.42825, -0.14651, 0.37986, -0.13544, 0.3509, 0.70346, 4.33792, 0.69421, 4.35548, 0.6937, 4.35027, 0.70926, 4.30774, -0.90088, 4.0234, -0.04678, 0.13842, -1.0719, 4.96331, -1.06213, 4.94196, -1.04929, 4.90511, -0.04034, 0.1196, -0.07523, 0.20426, -0.10211, 0.26987, -0.12775, 0.33331, -0.13965, 0.36775, -0.14172, 0.37709, -0.13071, 0.35703, -0.11951, 0.33389, -0.14542, 0.39532, -0.16638, 0.43952, -1.40085, 6.49587, -0.82043, 3.80259, -0.82043, 3.80259, -0.82043, 3.80259, -1.82895, 8.48514, -1.82895, 8.48514, -1.82895, 8.48514 ], + "curve": "stepped" + }, + { + "time": 0.1333, + "vertices": [ -0.08838, 0.23265, -0.04028, 0.11366, -1.15417, 5.38666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82043, 3.80259, -0.0957, 0.27988, -0.11633, 0.3275, -5.76245, 7.7601, -3.05988, 10.76797, -2.18188, 10.12057, -4.92511, 9.4566, 0, 0, 0, 0, 0.65329, -3.03143, 0.55997, -2.59837, -1.40085, 6.49587, -0.16394, 0.42825, -0.14651, 0.37986, -0.13544, 0.3509, 0.70346, 4.33792, 0.69421, 4.35548, 0.6937, 4.35027, 0.70926, 4.30774, -0.90088, 4.0234, -0.04678, 0.13842, -1.0719, 4.96331, -1.06213, 4.94196, -1.04929, 4.90511, -0.04034, 0.1196, -0.07523, 0.20426, -0.10211, 0.26987, -0.12775, 0.33331, -0.13965, 0.36775, -0.14172, 0.37709, -0.13071, 0.35703, -0.11951, 0.33389, -0.14542, 0.39532, -0.16638, 0.43952, -1.40085, 6.49587, -0.82043, 3.80259, -0.82043, 3.80259, -0.82043, 3.80259, -1.82895, 8.48514, -1.82895, 8.48514, -1.82895, 8.48514 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.4333, + "vertices": [ 0.72116, -13.02245, -0.08078, -15.10208, 0.5881, -9.07231, 0, 0, -0.95035, 2.12869, -4.29099, 4.74269, -0.37964, -1.86985, -0.50616, -2.49316, 2.05878, -14.16591, 3.97546, -18.45124, 0.47232, -2.1937, 1.59595, -7.39851, 2.05963, -9.54877, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.58685, -11.98995, 2.93106, -13.58876, 2.71149, -12.57045, 1.12061, -13.71136, 1.3736, -14.88384, 1.45294, -15.25188, 1.16116, -13.89926, 0.95001, -14.08721, -0.25418, -8.50095, -0.4256, -2.86804, 0.72946, -6.04102, 2.13202, -10.56477, -0.57986, -18.66593, -1.0582, -18.68787, 1.98853, -9.21902, 2.82358, -21.9123, 3.45761, -16.03436, 3.45532, -16.02369, 2.42819, -11.25721, 2.14264, -9.93373, 2.06396, -9.5659, 2.59061, -12.00682, 0, 0, 0.47232, -2.1937, 0.47232, -2.1937, 0.47232, -2.1937, 0.47232, -2.1937, 0.47232, -2.1937, -0.53992, -7.17996 ], + "curve": "stepped" + }, + { + "time": 0.6, + "vertices": [ 0.72116, -13.02245, -0.08078, -15.10208, 0.5881, -9.07231, 0, 0, -0.95035, 2.12869, -4.29099, 4.74269, -0.37964, -1.86985, -0.50616, -2.49316, 2.05878, -14.16591, 3.97546, -18.45124, 0.47232, -2.1937, 1.59595, -7.39851, 2.05963, -9.54877, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.58685, -11.98995, 2.93106, -13.58876, 2.71149, -12.57045, 1.12061, -13.71136, 1.3736, -14.88384, 1.45294, -15.25188, 1.16116, -13.89926, 0.95001, -14.08721, -0.25418, -8.50095, -0.4256, -2.86804, 0.72946, -6.04102, 2.13202, -10.56477, -0.57986, -18.66593, -1.0582, -18.68787, 1.98853, -9.21902, 2.82358, -21.9123, 3.45761, -16.03436, 3.45532, -16.02369, 2.42819, -11.25721, 2.14264, -9.93373, 2.06396, -9.5659, 2.59061, -12.00682, 0, 0, 0.47232, -2.1937, 0.47232, -2.1937, 0.47232, -2.1937, 0.47232, -2.1937, 0.47232, -2.1937, -0.53992, -7.17996 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.8667, + "vertices": [ -0.08838, 0.23265, -0.04028, 0.11366, -1.15417, 5.38666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82043, 3.80259, -0.0957, 0.27988, -0.11633, 0.3275, -5.76245, 7.7601, -3.05988, 10.76797, -2.18188, 10.12057, -4.92511, 9.4566, 0, 0, 0, 0, 0.65329, -3.03143, 0.55997, -2.59837, -1.40085, 6.49587, -0.16394, 0.42825, -0.14651, 0.37986, -0.13544, 0.3509, 0.70346, 4.33792, 0.69421, 4.35548, 0.6937, 4.35027, 0.70926, 4.30774, -0.90088, 4.0234, -0.04678, 0.13842, -1.0719, 4.96331, -1.06213, 4.94196, -1.04929, 4.90511, -0.04034, 0.1196, -0.07523, 0.20426, -0.10211, 0.26987, -0.12775, 0.33331, -0.13965, 0.36775, -0.14172, 0.37709, -0.13071, 0.35703, -0.11951, 0.33389, -0.14542, 0.39532, -0.16638, 0.43952, -1.40085, 6.49587, -0.82043, 3.80259, -0.82043, 3.80259, -0.82043, 3.80259, -1.82895, 8.48514, -1.82895, 8.48514, -1.82895, 8.48514 ] + } + ] + }, + "torso": { + "torso": [ + { + "offset": 24, + "vertices": [ 0.99754, -8.62222, -4.36671, -11.12821, 3.38991, -3.5328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.00336, 4.8839, -1.39807, 4.78593, 0, 0, 0, 0, 0, 0, 0, 0, 0.99754, -8.62222, 0, 0, 0, 0, 0.41353, -3.58589, -0.58401, 5.03633, -1.02026, 4.96621, 0, 0, 0, 0, -0.61319, 2.98462, 0.39218, -3.38733, 0.68637, -3.34027, -1.63116, 5.58357 ] + }, + { + "time": 0.1, + "vertices": [ -1.87766, 0.23508, 10.64218, 3.4945, 8.76065, 8.13096, 7.4079, 0.46964, 6.52606, 4.22304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.46204, -2.67851, -1.00093, -5.80334, -0.61595, -3.57126, 0.15442, -3.62069, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.95602, 6.51617, -0.21823, 8.17005, 0.60684, 0.26677, 0.45453, 0.48326, 2.96719, 0.85007, 2.5141, 1.78982, 1.42711, 0.95876, 1.02582, 1.37934, 0.9938, 8.43367, -2.3866, 8.1498, 1.32321, 11.29527, -2.3905, 11.22245, -0.27824, 3.32372, -1.36951, 3.04126, -0.69302, -4.01772, -1.54007, 8.31738, -0.07013, 9.53309, 0.51686, 2.99771, 0.51686, 2.99771, -0.12991, 3.03919, 1.17288, 12.46493, -2.98672, 12.23994, 1.91373, 6.46839, -0.23099, -1.33925, 0.05792, -1.35778, -2.41547, 12.32078 ] + }, + { + "time": 0.2, + "vertices": [ 0.13651, -3.42358, 14.41745, 0.02832, 13.25629, 5.67007, 12.89688, -0.65636, 12.12503, 4.44476, 0, 0, 0, 0, 0, 0, 0, 0, -0.12337, 0.36149, -0.237, 0.29979, -0.16426, 3.2699, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9.74475, 6.80592, 6.30356, 10.07764, 0.60684, 0.26677, 0.45453, 0.48326, 2.96719, 0.85007, 2.5141, 1.78982, 1.42711, 0.95876, 1.02582, 1.37934, 0.9938, 8.43367, -2.3866, 8.1498, 1.55508, 5.86423, -0.86441, 6.00507, -0.27824, 3.32372, -1.36951, 3.04126, 0, 0, -0.14114, 3.53476, 2.55927, 6.99835, -0.29503, 1.56245, 0, 0, 0, 0, 1.40475, 7.03388, -1.46063, 7.02255, 1.91373, 6.46839, 0, 0, 0, 0, -1.77957, 10.14687 ] + }, + { + "time": 0.4333, + "offset": 2, + "vertices": [ -1.25909, 6.12791, -1.75449, 6.0049, -1.25909, 6.12791, -1.75449, 6.0049, -0.72083, 6.21444, -1.25909, 6.12791, -0.72083, 6.21444, -1.25909, 6.12791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.74069, -3.60475, 1.03217, -3.53232, 0.74069, -3.60475, 1.03217, -3.53232, 0.42329, -3.65553, 0.74069, -3.60475 ] + }, + { + "time": 0.5333, + "offset": 2, + "vertices": [ -0.19458, 10.61421, -1.69006, 10.61533, -0.19458, 10.61421, -1.69006, 10.61533, -0.72083, 6.21444, -1.25909, 6.12791, -0.72083, 6.21444, -1.25909, 6.12791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.14001, -9.69365, 2.7449, -9.38902, 1.25098, -11.38506, 3.2207, -11.01592, 0.42329, -3.65553, 0.74069, -3.60475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.237, -4.22984 ] + }, + { + "time": 0.6667, + "offset": 2, + "vertices": [ -1.25909, 6.12791, -1.75449, 6.0049, -1.25909, 6.12791, -1.75449, 6.0049, -0.72083, 6.21444, -1.25909, 6.12791, -0.72083, 6.21444, -1.25909, 6.12791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.74069, -3.60475, 1.03217, -3.53232, 0.74069, -3.60475, 1.03217, -3.53232, 0.42329, -3.65553, 0.74069, -3.60475 ] + }, + { + "time": 0.8667, + "offset": 24, + "vertices": [ 0.99754, -8.62222, -4.36671, -11.12821, 3.38991, -3.5328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.00336, 4.8839, -1.39807, 4.78593, 0, 0, 0, 0, 0, 0, 0, 0, 0.99754, -8.62222, 0, 0, 0, 0, 0.41353, -3.58589, -0.58401, 5.03633, -1.02026, 4.96621, 0, 0, 0, 0, -0.61319, 2.98462, 0.39218, -3.38733, 0.68637, -3.34027, -1.63116, 5.58357 ] + } + ] + }, + "mouth": { + "mouth-grind": [ + { + "vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ], + "curve": "stepped" + }, + { + "time": 0.1333, + "vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.4333, + "vertices": [ -1.87524, -8.97547, 0.00449, -17.7002, 0.00449, -17.7002, -1.87524, -8.97547 ], + "curve": "stepped" + }, + { + "time": 0.6, + "vertices": [ -1.87524, -8.97547, 0.00449, -17.7002, 0.00449, -17.7002, -1.87524, -8.97547 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.8667, + "vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ] + } + ], + "mouth-smile": [ + { + "vertices": [ -6.59216, 5.02815, 5.28665, -1.62104, 2.43057, -7.10703, -6.07846, 8.24725 ], + "curve": "stepped" + }, + { + "time": 0.1333, + "vertices": [ -6.59216, 5.02815, 5.28665, -1.62104, 2.43057, -7.10703, -6.07846, 8.24725 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.4333, + "vertices": [ 1.95737, -8.63879, 0.58041, -17.27288, 1.98795, -27.30994, -8.04211, -23.88625 ], + "curve": "stepped" + }, + { + "time": 0.6, + "vertices": [ 1.95737, -8.63879, 0.58041, -17.27288, 1.98795, -27.30994, -8.04211, -23.88625 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.8667, + "vertices": [ -6.59216, 5.02815, 5.28665, -1.62104, 2.43057, -7.10703, -6.07846, 8.24725 ] + } + ] + }, + "head": { + "head": [ + { + "offset": 8, + "vertices": [ 2.09991, 9.25076, 8.45337, 4.30371, -3.35175, 8.87419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.13202, 7.95453, 2.22333, 9.79501, 8.95061, 4.55695, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, -3.54895, 9.39622, 8.95061, 4.55695, 0, 0, 3.18365, 15.68383, 14.26176, 7.26074, -5.65479, 14.97183, 3.18365, 15.68383, 0, 0, 0, 0, 1.99811, 9.84312, -6.13202, 7.95453, -3.54895, 9.39622, 0, 0, 0, 0, 2.3309, 11.48366, 0, 0, 0, 0, 0, 0, 2.66449, 13.12421, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ], + "curve": "stepped" + }, + { + "time": 0.1333, + "offset": 8, + "vertices": [ 2.09991, 9.25076, 8.45337, 4.30371, -3.35175, 8.87419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.13202, 7.95453, 2.22333, 9.79501, 8.95061, 4.55695, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, -3.54895, 9.39622, 8.95061, 4.55695, 0, 0, 3.18365, 15.68383, 14.26176, 7.26074, -5.65479, 14.97183, 3.18365, 15.68383, 0, 0, 0, 0, 1.99811, 9.84312, -6.13202, 7.95453, -3.54895, 9.39622, 0, 0, 0, 0, 2.3309, 11.48366, 0, 0, 0, 0, 0, 0, 2.66449, 13.12421, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.4333, + "offset": 34, + "vertices": [ 3.14838, -14.61261, 3.14838, -14.61261, 3.14838, -14.61261, 0.83426, -3.87112, 0, 0, 0, 0, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -1.59174, -7.84007, -0.89545, -4.41003, -0.89545, -4.41003, -1.59174, -7.84007, 0.55618, -2.58074, 0.41714, -1.93558, 1.04282, -4.83889 ], + "curve": "stepped" + }, + { + "time": 0.6, + "offset": 34, + "vertices": [ 3.14838, -14.61261, 3.14838, -14.61261, 3.14838, -14.61261, 0.83426, -3.87112, 0, 0, 0, 0, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -1.59174, -7.84007, -0.89545, -4.41003, -0.89545, -4.41003, -1.59174, -7.84007, 0.55618, -2.58074, 0.41714, -1.93558, 1.04282, -4.83889 ] + }, + { + "time": 0.8667, + "offset": 8, + "vertices": [ 2.09991, 9.25076, 8.45337, 4.30371, -3.35175, 8.87419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.13202, 7.95453, 2.22333, 9.79501, 8.95061, 4.55695, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, -3.54895, 9.39622, 8.95061, 4.55695, 0, 0, 3.18365, 15.68383, 14.26176, 7.26074, -5.65479, 14.97183, 3.18365, 15.68383, 0, 0, 0, 0, 1.99811, 9.84312, -6.13202, 7.95453, -3.54895, 9.39622, 0, 0, 0, 0, 2.3309, 11.48366, 0, 0, 0, 0, 0, 0, 2.66449, 13.12421, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ] + } + ] + }, + "eye": { + "eye-indifferent": [ + { + "vertices": [ -0.15329, 0.70867, -0.15329, 0.70867, -0.15329, 0.70867, -0.15329, 0.70867 ], + "curve": "stepped" + }, + { + "time": 0.1333, + "vertices": [ -0.15329, 0.70867, -0.15329, 0.70867, -0.15329, 0.70867, -0.15329, 0.70867 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.4333, + "vertices": [ 3.92969, -18.23849, 3.92969, -18.23849, 3.92969, -18.23849, 3.92969, -18.23849 ], + "curve": "stepped" + }, + { + "time": 0.6, + "vertices": [ 3.92969, -18.23849, 3.92969, -18.23849, 3.92969, -18.23849, 3.92969, -18.23849 ], + "curve": 0.25, + "c3": 0.75 + }, + { + "time": 0.8667, + "vertices": [ -0.15329, 0.70867, -0.15329, 0.70867, -0.15329, 0.70867, -0.15329, 0.70867 ] + } + ] + } + } + }, + "events": [ + { "name": "footstep" }, + { "time": 0.4333, "name": "footstep" } + ] + } +} +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-pro.skel b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-pro.skel new file mode 100644 index 0000000..df61267 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy-pro.skel differ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy.atlas b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy.atlas new file mode 100644 index 0000000..a2a83fe --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy.atlas @@ -0,0 +1,286 @@ + +spineboy.png +size: 1024,256 +format: RGBA8888 +filter: Linear,Linear +repeat: none +crosshair + rotate: false + xy: 352, 7 + size: 45, 45 + orig: 45, 45 + offset: 0, 0 + index: -1 +eye-indifferent + rotate: false + xy: 862, 105 + size: 47, 45 + orig: 47, 45 + offset: 0, 0 + index: -1 +eye-surprised + rotate: false + xy: 505, 79 + size: 47, 45 + orig: 47, 45 + offset: 0, 0 + index: -1 +front-bracer + rotate: false + xy: 826, 66 + size: 29, 40 + orig: 29, 40 + offset: 0, 0 + index: -1 +front-fist-closed + rotate: false + xy: 786, 65 + size: 38, 41 + orig: 38, 41 + offset: 0, 0 + index: -1 +front-fist-open + rotate: true + xy: 710, 51 + size: 43, 44 + orig: 43, 44 + offset: 0, 0 + index: -1 +front-foot + rotate: false + xy: 210, 6 + size: 63, 35 + orig: 63, 35 + offset: 0, 0 + index: -1 +front-shin + rotate: true + xy: 665, 128 + size: 41, 92 + orig: 41, 92 + offset: 0, 0 + index: -1 +front-thigh + rotate: true + xy: 2, 2 + size: 23, 56 + orig: 23, 56 + offset: 0, 0 + index: -1 +front-upper-arm + rotate: false + xy: 250, 205 + size: 23, 49 + orig: 23, 49 + offset: 0, 0 + index: -1 +goggles + rotate: false + xy: 665, 171 + size: 131, 83 + orig: 131, 83 + offset: 0, 0 + index: -1 +gun + rotate: false + xy: 798, 152 + size: 105, 102 + orig: 105, 102 + offset: 0, 0 + index: -1 +head + rotate: false + xy: 2, 27 + size: 136, 149 + orig: 136, 149 + offset: 0, 0 + index: -1 +hoverboard-board + rotate: false + xy: 2, 178 + size: 246, 76 + orig: 246, 76 + offset: 0, 0 + index: -1 +hoverboard-thruster + rotate: true + xy: 722, 96 + size: 30, 32 + orig: 30, 32 + offset: 0, 0 + index: -1 +hoverglow-small + rotate: false + xy: 275, 81 + size: 137, 38 + orig: 137, 38 + offset: 0, 0 + index: -1 +mouth-grind + rotate: false + xy: 614, 97 + size: 47, 30 + orig: 47, 30 + offset: 0, 0 + index: -1 +mouth-oooo + rotate: false + xy: 612, 65 + size: 47, 30 + orig: 47, 30 + offset: 0, 0 + index: -1 +mouth-smile + rotate: false + xy: 661, 64 + size: 47, 30 + orig: 47, 30 + offset: 0, 0 + index: -1 +muzzle-glow + rotate: false + xy: 382, 54 + size: 25, 25 + orig: 25, 25 + offset: 0, 0 + index: -1 +muzzle-ring + rotate: true + xy: 275, 54 + size: 25, 105 + orig: 25, 105 + offset: 0, 0 + index: -1 +muzzle01 + rotate: true + xy: 911, 95 + size: 67, 40 + orig: 67, 40 + offset: 0, 0 + index: -1 +muzzle02 + rotate: false + xy: 792, 108 + size: 68, 42 + orig: 68, 42 + offset: 0, 0 + index: -1 +muzzle03 + rotate: true + xy: 956, 171 + size: 83, 53 + orig: 83, 53 + offset: 0, 0 + index: -1 +muzzle04 + rotate: false + xy: 275, 7 + size: 75, 45 + orig: 75, 45 + offset: 0, 0 + index: -1 +muzzle05 + rotate: false + xy: 140, 3 + size: 68, 38 + orig: 68, 38 + offset: 0, 0 + index: -1 +neck + rotate: false + xy: 250, 182 + size: 18, 21 + orig: 18, 21 + offset: 0, 0 + index: -1 +portal-bg + rotate: false + xy: 140, 43 + size: 133, 133 + orig: 133, 133 + offset: 0, 0 + index: -1 +portal-flare1 + rotate: false + xy: 554, 65 + size: 56, 30 + orig: 56, 30 + offset: 0, 0 + index: -1 +portal-flare2 + rotate: true + xy: 759, 112 + size: 57, 31 + orig: 57, 31 + offset: 0, 0 + index: -1 +portal-flare3 + rotate: false + xy: 554, 97 + size: 58, 30 + orig: 58, 30 + offset: 0, 0 + index: -1 +portal-shade + rotate: false + xy: 275, 121 + size: 133, 133 + orig: 133, 133 + offset: 0, 0 + index: -1 +portal-streaks1 + rotate: false + xy: 410, 126 + size: 126, 128 + orig: 126, 128 + offset: 0, 0 + index: -1 +portal-streaks2 + rotate: false + xy: 538, 129 + size: 125, 125 + orig: 125, 125 + offset: 0, 0 + index: -1 +rear-bracer + rotate: false + xy: 857, 67 + size: 28, 36 + orig: 28, 36 + offset: 0, 0 + index: -1 +rear-foot + rotate: false + xy: 663, 96 + size: 57, 30 + orig: 57, 30 + offset: 0, 0 + index: -1 +rear-shin + rotate: true + xy: 414, 86 + size: 38, 89 + orig: 38, 89 + offset: 0, 0 + index: -1 +rear-thigh + rotate: false + xy: 756, 63 + size: 28, 47 + orig: 28, 47 + offset: 0, 0 + index: -1 +rear-upper-arm + rotate: true + xy: 60, 5 + size: 20, 44 + orig: 20, 44 + offset: 0, 0 + index: -1 +torso + rotate: false + xy: 905, 164 + size: 49, 90 + orig: 49, 90 + offset: 0, 0 + index: -1 diff --git a/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy.png b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy.png new file mode 100644 index 0000000..904dc48 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/export/spineboy.png differ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/license.txt b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/license.txt new file mode 100644 index 0000000..cd3e3b4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/license.txt @@ -0,0 +1,8 @@ +Copyright (c) 2013, Esoteric Software + +The images in this project may be redistributed as long as they are accompanied +by this license file. The images may not be used for commercial use of any +kind. + +The project file is released into the public domain. It may be used as the basis +for derivative work. \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/spineboy-ess.spine b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/spineboy-ess.spine new file mode 100644 index 0000000..8cebd69 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/spineboy-ess.spine differ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/spineboy-pro.spine b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/spineboy-pro.spine new file mode 100644 index 0000000..4441c07 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/3.8/examples/spineboy/spineboy-pro.spine differ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/package-lock.json b/DateToSpine/third_party/spine-runtimes/3.8/package-lock.json new file mode 100644 index 0000000..4212bff --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/package-lock.json @@ -0,0 +1,39 @@ +{ + "name": "spine-runtimes", + "version": "3.5.35", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "spine-runtimes", + "version": "3.5.35", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@types/offscreencanvas": "^2019.6.4", + "@types/webvr-api": "^0.0.36" + } + }, + "node_modules/@types/offscreencanvas": { + "version": "2019.6.4", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.6.4.tgz", + "integrity": "sha512-u8SAgdZ8ROtkTF+mfZGOscl0or6BSj9A4g37e6nvxDc+YB/oDut0wHkK2PBBiC2bNR8TS0CPV+1gAk4fNisr1Q==" + }, + "node_modules/@types/webvr-api": { + "version": "0.0.36", + "resolved": "https://registry.npmjs.org/@types/webvr-api/-/webvr-api-0.0.36.tgz", + "integrity": "sha512-fGXlG8KA8cHOGR2BG7w40nSEKgAqg9h7cUm6zW1dSI7DCba7RvJNKGt0sgJzAXXvNzAAOcIGY6OpHEnKGhhjsQ==" + } + }, + "dependencies": { + "@types/offscreencanvas": { + "version": "2019.6.4", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.6.4.tgz", + "integrity": "sha512-u8SAgdZ8ROtkTF+mfZGOscl0or6BSj9A4g37e6nvxDc+YB/oDut0wHkK2PBBiC2bNR8TS0CPV+1gAk4fNisr1Q==" + }, + "@types/webvr-api": { + "version": "0.0.36", + "resolved": "https://registry.npmjs.org/@types/webvr-api/-/webvr-api-0.0.36.tgz", + "integrity": "sha512-fGXlG8KA8cHOGR2BG7w40nSEKgAqg9h7cUm6zW1dSI7DCba7RvJNKGt0sgJzAXXvNzAAOcIGY6OpHEnKGhhjsQ==" + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/package.json b/DateToSpine/third_party/spine-runtimes/3.8/package.json new file mode 100644 index 0000000..8d8e631 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/package.json @@ -0,0 +1,33 @@ +{ + "name": "spine-runtimes", + "version": "3.5.35", + "description": "2D skeletal animation runtimes for Spine.", + "main": "spine-ts/build/spine-all.js", + "directories": { + "example": "examples" + }, + "files": [ + "spine-ts" + ], + "repository": { + "type": "git", + "url": "git@github.com:EsotericSoftware/spine-runtimes.git" + }, + "keywords": [ + "spine", + "runtimes", + "2d", + "skeletal", + "animation" + ], + "author": "Esoteric Software", + "license": "SEE LICENSE IN LICENSE", + "bugs": { + "url": "https://github.com/EsotericSoftware/spine-runtimes/issues" + }, + "homepage": "https://github.com/EsotericSoftware/spine-runtimes#readme", + "dependencies": { + "@types/offscreencanvas": "^2019.6.4", + "@types/webvr-api": "^0.0.36" + } +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/CMakeLists.txt b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/CMakeLists.txt new file mode 100644 index 0000000..706040c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/CMakeLists.txt @@ -0,0 +1,17 @@ +if(MSVC) + message("MSCV detected") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + set (CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}") +else() + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic -std=c89") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wnon-virtual-dtor -pedantic -std=c++03 -fno-exceptions -fno-rtti") +endif() + +include_directories(include) +file(GLOB INCLUDES "spine-cpp/include/**/*.h") +file(GLOB SOURCES "spine-cpp/src/**/*.cpp") + +add_library(spine-cpp STATIC ${SOURCES} ${INCLUDES}) +target_include_directories(spine-cpp PUBLIC spine-cpp/include) +install(TARGETS spine-cpp DESTINATION dist/lib) +install(FILES ${INCLUDES} DESTINATION dist/include) \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/LICENSE b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/LICENSE new file mode 100644 index 0000000..4501a61 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/LICENSE @@ -0,0 +1,26 @@ +Spine Runtimes License Agreement +Last updated May 1, 2019. Replaces all prior versions. + +Copyright (c) 2013-2019, Esoteric Software LLC + +Integration of the Spine Runtimes into software or otherwise creating +derivative works of the Spine Runtimes is permitted under the terms and +conditions of Section 2 of the Spine Editor License Agreement: +http://esotericsoftware.com/spine-editor-license + +Otherwise, it is permitted to integrate the Spine Runtimes into software +or otherwise create derivative works of the Spine Runtimes (collectively, +"Products"), provided that each user of the Products must obtain their own +Spine Editor license and redistribution of the Products in any form must +include this license and copyright notice. + +THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS +INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/README.md b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/README.md new file mode 100644 index 0000000..0bc3060 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/README.md @@ -0,0 +1,54 @@ +# spine-cpp + +The spine-cpp runtime provides basic functionality to load and manipulate [spine](http://esotericsoftware.com) skeletal animation data using C++. It does not perform rendering but can be extended to enable spine animations for other projects that utilize C++. Note, this library uses C++03 for maximum portability and therefore does not take advantage of any C++11 or newer features such as std::unique_ptr. + +## Licensing + +You are welcome to evaluate the Spine Runtimes and the examples we provide in this repository free of charge. + +You can integrate the Spine Runtimes into your software free of charge, but users of your software must have their own [Spine license](https://esotericsoftware.com/spine-purchase). Please make your users aware of this requirement! This option is often chosen by those making development tools, such as an SDK, game toolkit, or software library. + +In order to distribute your software containing the Spine Runtimes to others that don't have a Spine license, you need a [Spine license](https://esotericsoftware.com/spine-purchase) at the time of integration. Then you can distribute your software containing the Spine Runtimes however you like, provided others don't modify it or use it to create new software. If others want to do that, they'll need their own Spine license. + +For the official legal terms governing the Spine Runtimes, please read the [Spine Runtimes License Agreement](http://esotericsoftware.com/spine-runtimes-license) and Section 2 of the [Spine Editor License Agreement](http://esotericsoftware.com/spine-editor-license#s2). + +## Spine version + +spine-cpp works with data exported from spine 3.8.xx. + +spine-cpp supports all spine features. + +## Setup + +1. Download the spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it as a zip via the download button above. +2. Copy the contents of the `spine-cpp/spine-cpp/src` and `spine-cpp/spine-cpp/include` directories into your project. Be sure your header search is configured to find the contents of the `spine-cpp/spine-cpp/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files. + +## Usage +### [Please see the spine-cpp guide for full documentation](http://esotericsoftware.com/spine-cpp) + +## Extension + +Extending spine-cpp requires implementing both the `SpineExtension` class and the TextureLoader class: + +``` +#include +void spine::SpineExtension *spine::getDefaultExtension() { + return new spine::DefaultExtension(); +} + +class MyTextureLoader : public spine::TextureLoader +{ + virtual void load(spine::AtlasPage& page, const spine::String& path) { + void* texture = ... load the texture based on path ... + page->setRendererObject(texture); // use the texture later in your rendering code + } + + virtual void unload(void* texture) { // TODO } +}; +``` + +## Runtimes extending spine-cpp + +- [spine-sfml](../spine-sfml/cpp) +- [spine-cocos2dx](../spine-cocos2dx) +- [spine-ue4](../spine-ue4) diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp-unit-tests/CMakeLists.txt b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp-unit-tests/CMakeLists.txt new file mode 100755 index 0000000..0c14d26 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp-unit-tests/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 2.8.9) +project(spine_cpp_unit_test) + +set(CMAKE_INSTALL_PREFIX "./") +set(CMAKE_VERBOSE_MAKEFILE ON) + +include_directories(../spine-cpp/include teamcity minicppunit tests memory) + +set(SRC + src/main.cpp + ) + +add_executable(spine_cpp_unit_test ${SRC}) +target_link_libraries(spine_cpp_unit_test spine-cpp) + + +######################################################### +# copy resources to build output directory +######################################################### +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/spineboy/export $/testdata/spineboy) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/raptor/export $/testdata/raptor) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/goblins/export $/testdata/goblins) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/coin/export $/testdata/coin) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/tank/export $/testdata/tank) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/stretchyman/export $/testdata/stretchyman) diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp-unit-tests/README.md b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp-unit-tests/README.md new file mode 100755 index 0000000..a7d6efb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp-unit-tests/README.md @@ -0,0 +1,67 @@ +# spine-cpp-unit-tests + +The spine-cpp-unit-tests project is to test the [spine](http://esotericsoftware.com) skeletal animation system. It does not perform rendering. It is primarily used for regression testing and leak detection. It is designed to be run from a Continuous Integration server and to passively verify changes automatically on check-in. + +## Mini CPP Unit Testing +[MiniCppUnit](https://sourceforge.net/p/minicppunit/wiki/Home/) is a minimal unit testing framework similar to JUnit. It is used here to avoid large dependancies. + +Tests are sorted into Suites, Fixtures and Cases. There is one suite, it contains many fixtures and each fixture contains test cases. To turn off a fixture, edit "TestOptions.h". To turn off specific test cases, comment out the TEST_CASE() line in the fixture's header. + +## Memory Leak Detection +This project includes a very minimal memory leak detector. It is based roughly on the leak detector in the [Popcap Framework](https://sourceforge.net/projects/popcapframework/?source=directory), but has been modified over the years. + +## Continuous Integration +The test runner includes the ability to format output messages to signal a CI server. An example interface for [Teamcity](https://www.jetbrains.com/teamcity/) is included. To implement for another server, determine the wireformat for the messages and duplicate/edit the teamcity_messages class. [Teamcity Wire Format](https://confluence.jetbrains.com/display/TCD10/Build+Script+Interaction+with+TeamCity) + +### Trigger +Your CI server should trigger on VCS check-in. + +### CMake Build Step +The first build step for the CI server should be to run CMake on the 'spine-cpp-unit-tests' folder. Follow the usage directions below. + +### Compile Build Step +This build step should not execute if the previous step did not successfully complete. +Depending on the test agent build environment, you should build the output solution or project from the cmake step. Debug is fine. + +### Test Runner Build Step +This build step should not execute if the previous step did not successfully complete. +Again, depending on the test agent build environment, you should have produced an executable. Run this executable. + + +## Usage +Make sure [CMake](https://cmake.org/download/) is installed. + +Create a 'build' directory in the 'spine-cpp-unit-tests' folder. Then switch to that folder and execute cmake: + +mkdir build +cd build +cmake .. + +### Win32 build +msbuild spine_unit_test.sln /t:spine_unit_test /p:Configuration="Debug" /p:Platform="Win32" + + +## Licensing +This spine Runtime may only be used for personal or internal use, typically to evaluate spine before purchasing. If you would like to incorporate a spine Runtime into your applications, distribute software containing a spine Runtime, or modify a spine Runtime, then you will need a valid [spine license](https://esotericsoftware.com/spine-purchase). Please see the [spine Runtimes Software License](https://github.com/EsotericSoftware/spine-runtimes/blob/master/LICENSE) for detailed information. + +The spine Runtimes are developed with the intent to be used with data exported from spine. By purchasing spine, `Section 2` of the [spine Software License](https://esotericsoftware.com/files/license.txt) grants the right to create and distribute derivative works of the spine Runtimes. + +original "walk"": 330 +second "walk": 0d0 + +queue interrupt for original walk +queue start for second walk +drain interrupt and start + +0d0 is interrupted +0d0 is ended + +"run": 0c0 + 0d0 is interrupted + second walk becomes mixingFrom of run + 0c0 is started + + queue is drained + + first walk: 6f0 + second walk: 9c0 diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp-unit-tests/src/main.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp-unit-tests/src/main.cpp new file mode 100644 index 0000000..fc0851d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp-unit-tests/src/main.cpp @@ -0,0 +1,109 @@ +#include +#include +#include + +#pragma warning ( disable : 4710 ) + +using namespace spine; + +void loadBinary(const String &binaryFile, const String &atlasFile, Atlas *&atlas, SkeletonData *&skeletonData, + AnimationStateData *&stateData, Skeleton *&skeleton, AnimationState *&state) { + atlas = new(__FILE__, __LINE__) Atlas(atlasFile, NULL); + assert(atlas != NULL); + + SkeletonBinary binary(atlas); + skeletonData = binary.readSkeletonDataFile(binaryFile); + assert(skeletonData); + + skeleton = new(__FILE__, __LINE__) Skeleton(skeletonData); + assert(skeleton != NULL); + + stateData = new(__FILE__, __LINE__) AnimationStateData(skeletonData); + assert(stateData != NULL); + stateData->setDefaultMix(0.4f); + + state = new(__FILE__, __LINE__) AnimationState(stateData); +} + +void loadJson(const String &jsonFile, const String &atlasFile, Atlas *&atlas, SkeletonData *&skeletonData, + AnimationStateData *&stateData, Skeleton *&skeleton, AnimationState *&state) { + atlas = new(__FILE__, __LINE__) Atlas(atlasFile, NULL); + assert(atlas != NULL); + + SkeletonJson json(atlas); + skeletonData = json.readSkeletonDataFile(jsonFile); + assert(skeletonData); + + skeleton = new(__FILE__, __LINE__) Skeleton(skeletonData); + assert(skeleton != NULL); + + stateData = new(__FILE__, __LINE__) AnimationStateData(skeletonData); + assert(stateData != NULL); + stateData->setDefaultMix(0.4f); + + state = new(__FILE__, __LINE__) AnimationState(stateData); +} + +void dispose(Atlas *atlas, SkeletonData *skeletonData, AnimationStateData *stateData, Skeleton *skeleton, + AnimationState *state) { + delete skeleton; + delete state; + delete stateData; + delete skeletonData; + delete atlas; +} + +struct TestData { + TestData(const String &jsonSkeleton, const String &binarySkeleton, const String &atlas) : _jsonSkeleton( + jsonSkeleton), _binarySkeleton(binarySkeleton), _atlas(atlas) {} + + String _jsonSkeleton; + String _binarySkeleton; + String _atlas; +}; + +void testLoading() { + Vector testData; + testData.add(TestData("testdata/coin/coin-pro.json", "testdata/coin/coin-pro.skel", "testdata/coin/coin.atlas")); +/*testData.add(TestData("testdata/goblins/goblins-pro.json", "testdata/goblins/goblins-pro.skel", + "testdata/goblins/goblins.atlas")); + testData.add(TestData("testdata/raptor/raptor-pro.json", "testdata/raptor/raptor-pro.skel", + "testdata/raptor/raptor.atlas")); + testData.add(TestData("testdata/spineboy/spineboy-pro.json", "testdata/spineboy/spineboy-pro.skel", + "testdata/spineboy/spineboy.atlas")); + testData.add(TestData("testdata/stretchyman/stretchyman-pro.json", "testdata/stretchyman/stretchyman-pro.skel", + "testdata/stretchyman/stretchyman.atlas")); + testData.add(TestData("testdata/tank/tank-pro.json", "testdata/tank/tank-pro.skel", "testdata/tank/tank.atlas"));*/ + + for (size_t i = 0; i < testData.size(); i++) { + TestData &data = testData[i]; + Atlas *atlas = NULL; + SkeletonData *skeletonData = NULL; + AnimationStateData *stateData = NULL; + Skeleton *skeleton = NULL; + AnimationState *state = NULL; + + printf("Loading %s\n", data._jsonSkeleton.buffer()); + loadJson(data._jsonSkeleton, data._atlas, atlas, skeletonData, stateData, skeleton, state); + dispose(atlas, skeletonData, stateData, skeleton, state); + + printf("Loading %s\n", data._binarySkeleton.buffer()); + loadBinary(data._binarySkeleton, data._atlas, atlas, skeletonData, stateData, skeleton, state); + dispose(atlas, skeletonData, stateData, skeleton, state); + } +} + +namespace spine { + SpineExtension* getDefaultExtension() { + return new DefaultSpineExtension(); + } +} + +int main(int argc, char **argv) { + DebugExtension debug(SpineExtension::getInstance()); + SpineExtension::setInstance(&debug); + + testLoading(); + + debug.reportLeaks(); +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Animation.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Animation.h new file mode 100644 index 0000000..9e4004f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Animation.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Animation_h +#define Spine_Animation_h + +#include +#include +#include +#include +#include +#include + +namespace spine { +class Timeline; + +class Skeleton; + +class Event; + +class SP_API Animation : public SpineObject { + friend class AnimationState; + + friend class TrackEntry; + + friend class AnimationStateData; + + friend class AttachmentTimeline; + + friend class ColorTimeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class RotateTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TwoColorTimeline; + +public: + Animation(const String &name, Vector &timelines, float duration); + + ~Animation(); + + /// Applies all the animation's timelines to the specified skeleton. + /// See also Timeline::apply(Skeleton&, float, float, Vector, float, MixPose, MixDirection) + void apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction); + + const String &getName(); + + Vector &getTimelines(); + + bool hasTimeline(int id); + + float getDuration(); + + void setDuration(float inValue); + + + +private: + Vector _timelines; + HashMap _timelineIds; + float _duration; + String _name; + + /// @param target After the first and before the last entry. + static int binarySearch(Vector &values, float target, int step); + + /// @param target After the first and before the last entry. + static int binarySearch(Vector &values, float target); + + static int linearSearch(Vector &values, float target, int step); +}; +} + +#endif /* Spine_Animation_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AnimationState.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AnimationState.h new file mode 100644 index 0000000..300edf0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -0,0 +1,448 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AnimationState_h +#define Spine_AnimationState_h + +#include +#include +#include +#include +#include +#include +#include "Slot.h" + +#ifdef SPINE_USE_STD_FUNCTION +#include +#endif + +namespace spine { + enum EventType { + EventType_Start, + EventType_Interrupt, + EventType_End, + EventType_Complete, + EventType_Dispose, + EventType_Event + }; + + class AnimationState; + class TrackEntry; + + class Animation; + class Event; + class AnimationStateData; + class Skeleton; + class RotateTimeline; + class AttachmentTimeline; + +#ifdef SPINE_USE_STD_FUNCTION + typedef std::function AnimationStateListener; +#else + typedef void (*AnimationStateListener) (AnimationState* state, EventType type, TrackEntry* entry, Event* event); +#endif + + /// Abstract class to inherit from to create a callback object + class SP_API AnimationStateListenerObject { + public: + AnimationStateListenerObject() { }; + virtual ~AnimationStateListenerObject() { }; + public: + /// The callback function to be called + virtual void callback(AnimationState* state, EventType type, TrackEntry* entry, Event* event) = 0; + }; + + /// State for the playback of an animation + class SP_API TrackEntry : public SpineObject, public HasRendererObject { + friend class EventQueue; + friend class AnimationState; + + public: + TrackEntry(); + + virtual ~TrackEntry(); + + /// The index of the track where this entry is either current or queued. + int getTrackIndex(); + + /// The animation to apply for this track entry. + Animation* getAnimation(); + + /// If true, the animation will repeat. If false, it will not, instead its last frame is applied if played beyond its duration. + bool getLoop(); + void setLoop(bool inValue); + + /// If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead + /// of being mixed out. + /// + /// When mixing between animations that key the same property, if a lower track also keys that property then the value will + /// briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0% + /// while the second animation mixes from 0% to 100%. Setting holdPrevious to true applies the first animation + /// at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which + /// keys the property, only when a higher track also keys the property. + /// + /// Snapping will occur if holdPrevious is true and this animation does not key all the same properties as the + /// previous animation. + bool getHoldPrevious(); + void setHoldPrevious(bool inValue); + + /// Seconds to postpone playing the animation. When a track entry is the current track entry, delay postpones incrementing + /// the track time. When a track entry is queued, delay is the time from the start of the previous animation to when the + /// track entry will become the current track entry. + float getDelay(); + void setDelay(float inValue); + + /// Current time in seconds this track entry has been the current track entry. The track time determines + /// TrackEntry.AnimationTime. The track time can be set to start the animation at a time other than 0, without affecting looping. + float getTrackTime(); + void setTrackTime(float inValue); + + /// The track time in seconds when this animation will be removed from the track. Defaults to the animation duration for + /// non-looping animations and to int.MaxValue for looping animations. If the track end time is reached and no + /// other animations are queued for playback, and mixing from any previous animations is complete, properties keyed by the animation, + /// are set to the setup pose and the track is cleared. + /// + /// It may be desired to use AnimationState.addEmptyAnimation(int, float, float) to mix the properties back to the + /// setup pose over time, rather than have it happen instantly. + float getTrackEnd(); + void setTrackEnd(float inValue); + + /// Seconds when this animation starts, both initially and after looping. Defaults to 0. + /// + /// When changing the animation start time, it often makes sense to set TrackEntry.AnimationLast to the same value to + /// prevent timeline keys before the start time from triggering. + float getAnimationStart(); + void setAnimationStart(float inValue); + + /// Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will + /// loop back to TrackEntry.AnimationStart at this time. Defaults to the animation duration. + float getAnimationEnd(); + void setAnimationEnd(float inValue); + + /// The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this + /// animation is applied, event timelines will fire all events between the animation last time (exclusive) and animation time + /// (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation is applied. + float getAnimationLast(); + void setAnimationLast(float inValue); + + /// Uses TrackEntry.TrackTime to compute the animation time between TrackEntry.AnimationStart. and + /// TrackEntry.AnimationEnd. When the track time is 0, the animation time is equal to the animation start time. + float getAnimationTime(); + + /// Multiplier for the delta time when the animation state is updated, causing time for this animation to play slower or + /// faster. Defaults to 1. + float getTimeScale(); + void setTimeScale(float inValue); + + /// Values less than 1 mix this animation with the last skeleton pose. Defaults to 1, which overwrites the last skeleton pose with + /// this animation. + /// + /// Typically track 0 is used to completely pose the skeleton, then alpha can be used on higher tracks. It doesn't make sense + /// to use alpha on track 0 if the skeleton pose is from the last frame render. + float getAlpha(); + void setAlpha(float inValue); + + /// + /// When the mix percentage (mix time / mix duration) is less than the event threshold, event timelines for the animation + /// being mixed out will be applied. Defaults to 0, so event timelines are not applied for an animation being mixed out. + float getEventThreshold(); + void setEventThreshold(float inValue); + + /// When the mix percentage (mix time / mix duration) is less than the attachment threshold, attachment timelines for the + /// animation being mixed out will be applied. Defaults to 0, so attachment timelines are not applied for an animation being + /// mixed out. + float getAttachmentThreshold(); + void setAttachmentThreshold(float inValue); + + /// When the mix percentage (mix time / mix duration) is less than the draw order threshold, draw order timelines for the + /// animation being mixed out will be applied. Defaults to 0, so draw order timelines are not applied for an animation being + /// mixed out. + float getDrawOrderThreshold(); + void setDrawOrderThreshold(float inValue); + + /// The animation queued to start after this animation, or NULL. + TrackEntry* getNext(); + + /// Returns true if at least one loop has been completed. + bool isComplete(); + + /// Seconds from 0 to the mix duration when mixing from the previous animation to this animation. May be slightly more than + /// TrackEntry.MixDuration when the mix is complete. + float getMixTime(); + void setMixTime(float inValue); + + /// Seconds for mixing from the previous animation to this animation. Defaults to the value provided by + /// AnimationStateData based on the animation before this animation (if any). + /// + /// The mix duration can be set manually rather than use the value from AnimationStateData.GetMix. + /// In that case, the mixDuration must be set before AnimationState.update(float) is next called. + /// + /// When using AnimationState::addAnimation(int, Animation, bool, float) with a delay + /// less than or equal to 0, note the Delay is set using the mix duration from the AnimationStateData + float getMixDuration(); + void setMixDuration(float inValue); + + MixBlend getMixBlend(); + void setMixBlend(MixBlend blend); + + /// The track entry for the previous animation when mixing from the previous animation to this animation, or NULL if no + /// mixing is currently occuring. When mixing from multiple animations, MixingFrom makes up a double linked list with MixingTo. + TrackEntry* getMixingFrom(); + + /// The track entry for the next animation when mixing from this animation, or NULL if no mixing is currently occuring. + /// When mixing from multiple animations, MixingTo makes up a double linked list with MixingFrom. + TrackEntry* getMixingTo(); + + /// Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the + /// long way around when using alpha and starting animations on other tracks. + /// + /// Mixing involves finding a rotation between two others, which has two possible solutions: the short way or the long way around. + /// The two rotations likely change over time, so which direction is the short or long way also changes. + /// If the short way was always chosen, bones would flip to the other side when that direction became the long way. + /// TrackEntry chooses the short way the first time it is applied and remembers that direction. + void resetRotationDirections(); + + void setListener(AnimationStateListener listener); + + void setListener(AnimationStateListenerObject* listener); + + private: + Animation* _animation; + + TrackEntry* _next; + TrackEntry* _mixingFrom; + TrackEntry* _mixingTo; + int _trackIndex; + + bool _loop, _holdPrevious; + float _eventThreshold, _attachmentThreshold, _drawOrderThreshold; + float _animationStart, _animationEnd, _animationLast, _nextAnimationLast; + float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale; + float _alpha, _mixTime, _mixDuration, _interruptAlpha, _totalAlpha; + MixBlend _mixBlend; + Vector _timelineMode; + Vector _timelineHoldMix; + Vector _timelinesRotation; + AnimationStateListener _listener; + AnimationStateListenerObject* _listenerObject; + + void reset(); + }; + + class SP_API EventQueueEntry : public SpineObject { + friend class EventQueue; + + public: + EventType _type; + TrackEntry* _entry; + Event* _event; + + EventQueueEntry(EventType eventType, TrackEntry* trackEntry, Event* event = NULL); + }; + + class SP_API EventQueue : public SpineObject { + friend class AnimationState; + + private: + Vector _eventQueueEntries; + AnimationState& _state; + Pool& _trackEntryPool; + bool _drainDisabled; + + static EventQueue* newEventQueue(AnimationState& state, Pool& trackEntryPool); + + static EventQueueEntry newEventQueueEntry(EventType eventType, TrackEntry* entry, Event* event = NULL); + + EventQueue(AnimationState& state, Pool& trackEntryPool); + + ~EventQueue(); + + void start(TrackEntry* entry); + + void interrupt(TrackEntry* entry); + + void end(TrackEntry* entry); + + void dispose(TrackEntry* entry); + + void complete(TrackEntry* entry); + + void event(TrackEntry* entry, Event* event); + + /// Raises all events in the queue and drains the queue. + void drain(); + }; + + class SP_API AnimationState : public SpineObject, public HasRendererObject { + friend class TrackEntry; + friend class EventQueue; + + public: + explicit AnimationState(AnimationStateData* data); + + ~AnimationState(); + + /// Increments the track entry times, setting queued animations as current if needed + /// @param delta delta time + void update(float delta); + + /// Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the + /// animation state can be applied to multiple skeletons to pose them identically. + bool apply(Skeleton& skeleton); + + /// Removes all animations from all tracks, leaving skeletons in their previous pose. + /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, + /// rather than leaving them in their previous pose. + void clearTracks(); + + /// Removes all animations from the tracks, leaving skeletons in their previous pose. + /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, + /// rather than leaving them in their previous pose. + void clearTrack(size_t trackIndex); + + /// Sets an animation by name. setAnimation(int, Animation, bool) + TrackEntry* setAnimation(size_t trackIndex, const String& animationName, bool loop); + + /// Sets the current animation for a track, discarding any queued animations. + /// @param loop If true, the animation will repeat. + /// If false, it will not, instead its last frame is applied if played beyond its duration. + /// In either case TrackEntry.TrackEnd determines when the track is cleared. + /// @return + /// A track entry to allow further customization of animation playback. References to the track entry must not be kept + /// after AnimationState.Dispose. + TrackEntry* setAnimation(size_t trackIndex, Animation* animation, bool loop); + + /// Queues an animation by name. + /// addAnimation(int, Animation, bool, float) + TrackEntry* addAnimation(size_t trackIndex, const String& animationName, bool loop, float delay); + + /// Adds an animation to be played delay seconds after the current or last queued animation + /// for a track. If the track is empty, it is equivalent to calling setAnimation. + /// @param delay + /// Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation + /// duration of the previous track minus any mix duration plus the negative delay. + /// + /// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + /// after AnimationState.Dispose + TrackEntry* addAnimation(size_t trackIndex, Animation* animation, bool loop, float delay); + + /// Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration. + TrackEntry* setEmptyAnimation(size_t trackIndex, float mixDuration); + + /// Adds an empty animation to be played after the current or last queued animation for a track, and mixes to it over the + /// specified mix duration. + /// @return + /// A track entry to allow further customization of animation playback. References to the track entry must not be kept after AnimationState.Dispose. + /// + /// @param trackIndex Track number. + /// @param mixDuration Mix duration. + /// @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation + /// duration of the previous track minus any mix duration plus the negative delay. + TrackEntry* addEmptyAnimation(size_t trackIndex, float mixDuration, float delay); + + /// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration. + void setEmptyAnimations(float mixDuration); + + /// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing. + TrackEntry* getCurrent(size_t trackIndex); + + AnimationStateData* getData(); + + /// A list of tracks that have animations, which may contain NULLs. + Vector &getTracks(); + + float getTimeScale(); + void setTimeScale(float inValue); + + void setListener(AnimationStateListener listener); + void setListener(AnimationStateListenerObject* listener); + + void disableQueue(); + void enableQueue(); + + private: + static const int Subsequent = 0; + static const int First = 1; + static const int HoldSubsequent = 2; + static const int HoldFirst = 3; + static const int HoldMix = 4; + + static const int Setup = 1; + static const int Current = 2; + + AnimationStateData* _data; + + Pool _trackEntryPool; + Vector _tracks; + Vector _events; + EventQueue* _queue; + + HashMap _propertyIDs; + bool _animationsChanged; + + AnimationStateListener _listener; + AnimationStateListenerObject* _listenerObject; + + int _unkeyedState; + + float _timeScale; + + static Animation* getEmptyAnimation(); + + static void applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixBlend pose, Vector& timelinesRotation, size_t i, bool firstFrame); + void applyAttachmentTimeline(AttachmentTimeline* attachmentTimeline, Skeleton& skeleton, float animationTime, MixBlend pose, bool firstFrame); + + /// Returns true when all mixing from entries are complete. + bool updateMixingFrom(TrackEntry* to, float delta); + + float applyMixingFrom(TrackEntry* to, Skeleton& skeleton, MixBlend currentPose); + + void queueEvents(TrackEntry* entry, float animationTime); + + /// Sets the active TrackEntry for a given track number. + void setCurrent(size_t index, TrackEntry *current, bool interrupt); + + TrackEntry* expandToIndex(size_t index); + + /// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values. + /// @param last May be NULL. + TrackEntry* newTrackEntry(size_t trackIndex, Animation *animation, bool loop, TrackEntry *last); + + /// Dispose all track entries queued after the given TrackEntry. + void disposeNext(TrackEntry* entry); + + void animationsChanged(); + + void computeHold(TrackEntry *entry); + + void setAttachment(Skeleton &skeleton, spine::Slot &slot, const String &attachmentName, bool attachments); + }; +} + +#endif /* Spine_AnimationState_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AnimationStateData.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AnimationStateData.h new file mode 100644 index 0000000..336f75b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AnimationStateData.h @@ -0,0 +1,85 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AnimationStateData_h +#define Spine_AnimationStateData_h + +#include +#include +#include + +#include + +namespace spine { + class SkeletonData; + class Animation; + + /// Stores mix (crossfade) durations to be applied when AnimationState animations are changed. + class SP_API AnimationStateData : public SpineObject { + friend class AnimationState; + + public: + explicit AnimationStateData(SkeletonData* skeletonData); + + /// The SkeletonData to look up animations when they are specified by name. + SkeletonData* getSkeletonData(); + + /// The mix duration to use when no mix duration has been specifically defined between two animations. + float getDefaultMix(); + void setDefaultMix(float inValue); + + /// Sets a mix duration by animation names. + void setMix(const String& fromName, const String& toName, float duration); + + /// Sets a mix duration when changing from the specified animation to the other. + /// See TrackEntry.MixDuration. + void setMix(Animation* from, Animation* to, float duration); + + /// The mix duration to use when changing from the specified animation to the other, + /// or the DefaultMix if no mix duration has been set. + float getMix(Animation* from, Animation* to); + + private: + class AnimationPair : public SpineObject { + public: + Animation* _a1; + Animation* _a2; + + explicit AnimationPair(Animation* a1 = NULL, Animation* a2 = NULL); + + bool operator==(const AnimationPair &other) const; + }; + + SkeletonData* _skeletonData; + float _defaultMix; + HashMap _animationToMixTime; + }; +} + +#endif /* Spine_AnimationStateData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Atlas.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Atlas.h new file mode 100644 index 0000000..8163661 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Atlas.h @@ -0,0 +1,157 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Atlas_h +#define Spine_Atlas_h + +#include +#include +#include +#include +#include + +namespace spine { +enum Format { + Format_Alpha, + Format_Intensity, + Format_LuminanceAlpha, + Format_RGB565, + Format_RGBA4444, + Format_RGB888, + Format_RGBA8888 +}; + +enum TextureFilter { + TextureFilter_Unknown, + TextureFilter_Nearest, + TextureFilter_Linear, + TextureFilter_MipMap, + TextureFilter_MipMapNearestNearest, + TextureFilter_MipMapLinearNearest, + TextureFilter_MipMapNearestLinear, + TextureFilter_MipMapLinearLinear +}; + +enum TextureWrap { + TextureWrap_MirroredRepeat, + TextureWrap_ClampToEdge, + TextureWrap_Repeat +}; + +class SP_API AtlasPage : public SpineObject, public HasRendererObject { +public: + String name; + String texturePath; + Format format; + TextureFilter minFilter; + TextureFilter magFilter; + TextureWrap uWrap; + TextureWrap vWrap; + int width, height; + + explicit AtlasPage(const String &inName) : name(inName), format(Format_RGBA8888), minFilter(TextureFilter_Nearest), + magFilter(TextureFilter_Nearest), uWrap(TextureWrap_ClampToEdge), + vWrap(TextureWrap_ClampToEdge), width(0), height(0) { + } +}; + +class SP_API AtlasRegion : public SpineObject { +public: + AtlasPage *page; + String name; + int x, y, width, height; + float u, v, u2, v2; + float offsetX, offsetY; + int originalWidth, originalHeight; + int index; + bool rotate; + int degrees; + Vector splits; + Vector pads; +}; + +class TextureLoader; + +class SP_API Atlas : public SpineObject { +public: + Atlas(const String &path, TextureLoader *textureLoader, bool createTexture = true); + + Atlas(const char *data, int length, const char *dir, TextureLoader *textureLoader, bool createTexture = true); + + ~Atlas(); + + void flipV(); + + /// Returns the first region found with the specified name. This method uses String comparison to find the region, so the result + /// should be cached rather than calling this method multiple times. + /// @return The region, or NULL. + AtlasRegion *findRegion(const String &name); + + Vector &getPages(); + + Vector &getRegions(); + +private: + Vector _pages; + Vector _regions; + TextureLoader *_textureLoader; + + void load(const char *begin, int length, const char *dir, bool createTexture); + + class Str { + public: + const char *begin; + const char *end; + }; + + static void trim(Str *str); + + /// Tokenize string without modification. Returns 0 on failure + static int readLine(const char **begin, const char *end, Str *str); + + /// Moves str->begin past the first occurence of c. Returns 0 on failure + static int beginPast(Str *str, char c); + + /// Returns 0 on failure + static int readValue(const char **begin, const char *end, Str *str); + + /// Returns the number of tuple values read (1, 2, 4, or 0 for failure) + static int readTuple(const char **begin, const char *end, Str tuple[]); + + static char *mallocString(Str *str); + + static int indexOf(const char **array, int count, Str *str); + + static int equals(Str *str, const char *other); + + static int toInt(Str *str); +}; +} + +#endif /* Spine_Atlas_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h new file mode 100644 index 0000000..0db41cd --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AtlasAttachmentLoader_h +#define Spine_AtlasAttachmentLoader_h + +#include +#include +#include + + +namespace spine { + class Atlas; + class AtlasRegion; + + /// An AttachmentLoader that configures attachments using texture regions from an Atlas. + /// See http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data about Loading Skeleton Data in the Spine Runtimes Guide. + class SP_API AtlasAttachmentLoader : public AttachmentLoader { + public: + RTTI_DECL + + explicit AtlasAttachmentLoader(Atlas* atlas); + + virtual RegionAttachment* newRegionAttachment(Skin& skin, const String& name, const String& path); + + virtual MeshAttachment* newMeshAttachment(Skin& skin, const String& name, const String& path); + + virtual BoundingBoxAttachment* newBoundingBoxAttachment(Skin& skin, const String& name); + + virtual PathAttachment* newPathAttachment(Skin& skin, const String& name); + + virtual PointAttachment* newPointAttachment(Skin& skin, const String& name); + + virtual ClippingAttachment* newClippingAttachment(Skin& skin, const String& name); + + virtual void configureAttachment(Attachment* attachment); + + AtlasRegion* findRegion(const String& name); + + private: + Atlas* _atlas; + }; +} + +#endif /* Spine_AtlasAttachmentLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Attachment.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Attachment.h new file mode 100644 index 0000000..5b1c4c1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Attachment.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Attachment_h +#define Spine_Attachment_h + +#include +#include +#include + +namespace spine { +class SP_API Attachment : public SpineObject { +RTTI_DECL + +public: + explicit Attachment(const String &name); + + virtual ~Attachment(); + + const String &getName() const; + + virtual Attachment* copy() = 0; + + int getRefCount(); + void reference(); + void dereference(); + +private: + const String _name; + int _refCount; +}; +} + +#endif /* Spine_Attachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h new file mode 100644 index 0000000..6201e92 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h @@ -0,0 +1,75 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentLoader_h +#define Spine_AttachmentLoader_h + +#include +#include +#include + +namespace spine { + class Skin; + class Attachment; + class RegionAttachment; + class MeshAttachment; + class BoundingBoxAttachment; + class PathAttachment; + class PointAttachment; + class ClippingAttachment; + + class SP_API AttachmentLoader : public SpineObject { + public: + RTTI_DECL + + AttachmentLoader(); + + virtual ~AttachmentLoader(); + + /// @return May be NULL to not load any attachment. + virtual RegionAttachment* newRegionAttachment(Skin& skin, const String& name, const String& path) = 0; + + /// @return May be NULL to not load any attachment. + virtual MeshAttachment* newMeshAttachment(Skin& skin, const String& name, const String& path) = 0; + + /// @return May be NULL to not load any attachment. + virtual BoundingBoxAttachment* newBoundingBoxAttachment(Skin& skin, const String& name) = 0; + + /// @return May be NULL to not load any attachment + virtual PathAttachment* newPathAttachment(Skin& skin, const String& name) = 0; + + virtual PointAttachment* newPointAttachment(Skin& skin, const String& name) = 0; + + virtual ClippingAttachment* newClippingAttachment(Skin& skin, const String& name) = 0; + + virtual void configureAttachment(Attachment* attachment) = 0; + }; +} + +#endif /* Spine_AttachmentLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h new file mode 100644 index 0000000..3aed101 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -0,0 +1,76 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentTimeline_h +#define Spine_AttachmentTimeline_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + + class Skeleton; + class Slot; + class Event; + + class SP_API AttachmentTimeline : public Timeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit AttachmentTimeline(int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, const String& attachmentName); + + size_t getSlotIndex(); + void setSlotIndex(size_t inValue); + Vector& getFrames(); + Vector& getAttachmentNames(); + size_t getFrameCount(); + private: + size_t _slotIndex; + Vector _frames; + Vector _attachmentNames; + + void setAttachment(Skeleton& skeleton, Slot& slot, String* attachmentName); + }; +} + +#endif /* Spine_AttachmentTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AttachmentType.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AttachmentType.h new file mode 100644 index 0000000..bb62f9f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/AttachmentType.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentType_h +#define Spine_AttachmentType_h + +namespace spine { + enum AttachmentType { + AttachmentType_Region, + AttachmentType_Boundingbox, + AttachmentType_Mesh, + AttachmentType_Linkedmesh, + AttachmentType_Path, + AttachmentType_Point, + AttachmentType_Clipping + }; +} + +#endif /* Spine_AttachmentType_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/BlendMode.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/BlendMode.h new file mode 100644 index 0000000..eca09cf --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/BlendMode.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BlendMode_h +#define Spine_BlendMode_h + +namespace spine { +enum BlendMode { + BlendMode_Normal = 0, + BlendMode_Additive, + BlendMode_Multiply, + BlendMode_Screen +}; +} + +#endif /* Spine_BlendMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Bone.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Bone.h new file mode 100644 index 0000000..148c6c5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Bone.h @@ -0,0 +1,251 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Bone_h +#define Spine_Bone_h + +#include +#include +#include + +namespace spine { +class BoneData; + +class Skeleton; + +/// Stores a bone's current pose. +/// +/// A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a +/// local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a +/// constraint or application code modifies the world transform after it was computed from the local transform. +class SP_API Bone : public Updatable { + friend class AnimationState; + + friend class RotateTimeline; + + friend class IkConstraint; + + friend class TransformConstraint; + + friend class VertexAttachment; + + friend class PathConstraint; + + friend class Skeleton; + + friend class RegionAttachment; + + friend class PointAttachment; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TranslateTimeline; + +RTTI_DECL + +public: + static void setYDown(bool inValue); + + static bool isYDown(); + + /// @param parent May be NULL. + Bone(BoneData &data, Skeleton &skeleton, Bone *parent = NULL); + + /// Same as updateWorldTransform. This method exists for Bone to implement Spine::Updatable. + virtual void update(); + + /// Computes the world transform using the parent bone and this bone's local transform. + void updateWorldTransform(); + + /// Computes the world transform using the parent bone and the specified local transform. + void updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY); + + void setToSetupPose(); + + void worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY); + + void localToWorld(float localX, float localY, float &outWorldX, float &outWorldY); + + float worldToLocalRotation(float worldRotation); + + float localToWorldRotation(float localRotation); + + /// Rotates the world transform the specified amount and sets isAppliedValid to false. + /// @param degrees Degrees. + void rotateWorld(float degrees); + + float getWorldToLocalRotationX(); + + float getWorldToLocalRotationY(); + + BoneData &getData(); + + Skeleton &getSkeleton(); + + Bone *getParent(); + + Vector &getChildren(); + + /// The local X translation. + float getX(); + + void setX(float inValue); + + /// The local Y translation. + float getY(); + + void setY(float inValue); + + /// The local rotation. + float getRotation(); + + void setRotation(float inValue); + + /// The local scaleX. + float getScaleX(); + + void setScaleX(float inValue); + + /// The local scaleY. + float getScaleY(); + + void setScaleY(float inValue); + + /// The local shearX. + float getShearX(); + + void setShearX(float inValue); + + /// The local shearY. + float getShearY(); + + void setShearY(float inValue); + + /// The rotation, as calculated by any constraints. + float getAppliedRotation(); + + void setAppliedRotation(float inValue); + + /// The applied local x translation. + float getAX(); + + void setAX(float inValue); + + /// The applied local y translation. + float getAY(); + + void setAY(float inValue); + + /// The applied local scaleX. + float getAScaleX(); + + void setAScaleX(float inValue); + + /// The applied local scaleY. + float getAScaleY(); + + void setAScaleY(float inValue); + + /// The applied local shearX. + float getAShearX(); + + void setAShearX(float inValue); + + /// The applied local shearY. + float getAShearY(); + + void setAShearY(float inValue); + + float getA(); + + void setA(float inValue); + + float getB(); + + void setB(float inValue); + + float getC(); + + void setC(float inValue); + + float getD(); + + void setD(float inValue); + + float getWorldX(); + + void setWorldX(float inValue); + + float getWorldY(); + + void setWorldY(float inValue); + + float getWorldRotationX(); + + float getWorldRotationY(); + + /// Returns the magnitide (always positive) of the world scale X. + float getWorldScaleX(); + + /// Returns the magnitide (always positive) of the world scale Y. + float getWorldScaleY(); + + bool isAppliedValid(); + void setAppliedValid(bool valid); + + bool isActive(); + + void setActive(bool inValue); + +private: + static bool yDown; + + BoneData &_data; + Skeleton &_skeleton; + Bone *_parent; + Vector _children; + float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; + float _ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY; + bool _appliedValid; + float _a, _b, _worldX; + float _c, _d, _worldY; + bool _sorted; + bool _active; + + /// Computes the individual applied transform values from the world transform. This can be useful to perform processing using + /// the applied transform after the world transform has been modified directly (eg, by a constraint).. + /// + /// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. + void updateAppliedTransform(); +}; +} + +#endif /* Spine_Bone_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/BoneData.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/BoneData.h new file mode 100644 index 0000000..bd997f6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -0,0 +1,123 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BoneData_h +#define Spine_BoneData_h + +#include +#include +#include + +namespace spine { +class SP_API BoneData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + + friend class RotateTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TranslateTimeline; + +public: + BoneData(int index, const String &name, BoneData *parent = NULL); + + /// The index of the bone in Skeleton.Bones + int getIndex(); + + /// The name of the bone, which is unique within the skeleton. + const String &getName(); + + /// May be NULL. + BoneData *getParent(); + + float getLength(); + + void setLength(float inValue); + + /// Local X translation. + float getX(); + + void setX(float inValue); + + /// Local Y translation. + float getY(); + + void setY(float inValue); + + /// Local rotation. + float getRotation(); + + void setRotation(float inValue); + + /// Local scaleX. + float getScaleX(); + + void setScaleX(float inValue); + + /// Local scaleY. + float getScaleY(); + + void setScaleY(float inValue); + + /// Local shearX. + float getShearX(); + + void setShearX(float inValue); + + /// Local shearY. + float getShearY(); + + void setShearY(float inValue); + + /// The transform mode for how parent world transforms affect this bone. + TransformMode getTransformMode(); + + void setTransformMode(TransformMode inValue); + + bool isSkinRequired(); + void setSkinRequired(bool inValue); + +private: + const int _index; + const String _name; + BoneData *_parent; + float _length; + float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; + TransformMode _transformMode; + bool _skinRequired; +}; +} + +#endif /* Spine_BoneData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h new file mode 100644 index 0000000..7118c70 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h @@ -0,0 +1,47 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BoundingBoxAttachment_h +#define Spine_BoundingBoxAttachment_h + +#include +#include + +namespace spine { + /// Attachment that has a polygon for bounds checking. + class SP_API BoundingBoxAttachment : public VertexAttachment { + RTTI_DECL + + explicit BoundingBoxAttachment(const String& name); + + virtual Attachment* copy(); + }; +} + +#endif /* Spine_BoundingBoxAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h new file mode 100644 index 0000000..21834cb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ClippingAttachment_h +#define Spine_ClippingAttachment_h + +#include + +namespace spine { + class SlotData; + + class SP_API ClippingAttachment : public VertexAttachment { + friend class SkeletonBinary; + friend class SkeletonJson; + + friend class SkeletonClipping; + + RTTI_DECL + + public: + explicit ClippingAttachment(const String& name); + + SlotData* getEndSlot(); + void setEndSlot(SlotData* inValue); + + virtual Attachment* copy(); + + private: + SlotData* _endSlot; + }; +} + +#endif /* Spine_ClippingAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Color.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Color.h new file mode 100644 index 0000000..1f288f7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Color.h @@ -0,0 +1,94 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_COLOR_H +#define SPINE_COLOR_H + +#include + +namespace spine { +class SP_API Color : public SpineObject { +public: + Color() : r(0), g(0), b(0), a(0) { + } + + Color(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) { + clamp(); + } + + inline Color &set(float _r, float _g, float _b, float _a) { + this->r = _r; + this->g = _g; + this->b = _b; + this->a = _a; + clamp(); + return *this; + } + + inline Color &set(const Color &other) { + r = other.r; + g = other.g; + b = other.b; + a = other.a; + clamp(); + return *this; + } + + inline Color &add(float _r, float _g, float _b, float _a) { + this->r += _r; + this->g += _g; + this->b += _b; + this->a += _a; + clamp(); + return *this; + } + + inline Color &add(const Color &other) { + r += other.r; + g += other.g; + b += other.b; + a += other.a; + clamp(); + return *this; + } + + inline Color &clamp() { + r = MathUtil::clamp(this->r, 0, 1); + g = MathUtil::clamp(this->g, 0, 1); + b = MathUtil::clamp(this->b, 0, 1); + a = MathUtil::clamp(this->a, 0, 1); + return *this; + } + + float r, g, b, a; +}; +} + + +#endif //SPINE_COLOR_H diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ColorTimeline.h new file mode 100644 index 0000000..3d35400 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -0,0 +1,80 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ColorTimeline_h +#define Spine_ColorTimeline_h + +#include + +namespace spine { +class SP_API ColorTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + +RTTI_DECL + +public: + static const int ENTRIES; + + explicit ColorTimeline(int frameCount); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + virtual int getPropertyId(); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, float r, float g, float b, float a); + + int getSlotIndex(); + + void setSlotIndex(int inValue); + + Vector &getFrames(); + +protected: + static const int PREV_TIME; + static const int PREV_R; + static const int PREV_G; + static const int PREV_B; + static const int PREV_A; + static const int R; + static const int G; + static const int B; + static const int A; + +private: + int _slotIndex; + Vector _frames; +}; +} + +#endif /* Spine_ColorTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ConstraintData.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ConstraintData.h new file mode 100644 index 0000000..1f928a9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ConstraintData.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Constraint_h +#define Spine_Constraint_h + +#include +#include + +namespace spine { +/// The interface for all constraints. +class SP_API ConstraintData : public SpineObject { + +public: + ConstraintData(const String& name); + + virtual ~ConstraintData(); + + /// The IK constraint's name, which is unique within the skeleton. + const String& getName(); + + /// The ordinal for the order a skeleton's constraints will be applied. + size_t getOrder(); + void setOrder(size_t inValue); + + /// Whether the constraint is only active for a specific skin. + bool isSkinRequired(); + void setSkinRequired(bool inValue); + +private: + const String _name; + size_t _order; + bool _skinRequired; +}; +} + +#endif /* Spine_Constraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ContainerUtil.h new file mode 100644 index 0000000..af0a2bc --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -0,0 +1,127 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ContainerUtil_h +#define Spine_ContainerUtil_h + +#include +#include +#include +#include +#include + +#include + +namespace spine { + class SP_API ContainerUtil : public SpineObject { + public: + /// Finds an item by comparing each item's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + template + static T* findWithName(Vector& items, const String& name) { + assert(name.length() > 0); + + for (size_t i = 0; i < items.size(); ++i) { + T* item = items[i]; + if (item->getName() == name) { + return item; + } + } + + return NULL; + } + + /// @return -1 if the item was not found. + template + static int findIndexWithName(Vector& items, const String& name) { + assert(name.length() > 0); + + for (size_t i = 0, len = items.size(); i < len; ++i) { + T* item = items[i]; + if (item->getName() == name) { + return static_cast(i); + } + } + + return -1; + } + + /// Finds an item by comparing each item's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + template + static T* findWithDataName(Vector& items, const String& name) { + assert(name.length() > 0); + + for (size_t i = 0; i < items.size(); ++i) { + T* item = items[i]; + if (item->getData().getName() == name) { + return item; + } + } + + return NULL; + } + + /// @return -1 if the item was not found. + template + static int findIndexWithDataName(Vector& items, const String& name) { + assert(name.length() > 0); + + for (size_t i = 0, len = items.size(); i < len; ++i) { + T* item = items[i]; + if (item->getData().getName() == name) { + return static_cast(i); + } + } + + return -1; + } + + template + static void cleanUpVectorOfPointers(Vector& items) { + for (int i = (int)items.size() - 1; i >= 0; i--) { + T* item = items[i]; + + delete item; + + items.removeAt(i); + } + } + + private: + // ctor, copy ctor, and assignment should be private in a Singleton + ContainerUtil(); + ContainerUtil(const ContainerUtil&); + ContainerUtil& operator=(const ContainerUtil&); + }; +} + +#endif /* Spine_ContainerUtil_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/CurveTimeline.h new file mode 100644 index 0000000..9d739d4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -0,0 +1,76 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_CurveTimeline_h +#define Spine_CurveTimeline_h + +#include +#include + +namespace spine { + /// Base class for frames that use an interpolation bezier curve. + class SP_API CurveTimeline : public Timeline { + RTTI_DECL + + public: + explicit CurveTimeline(int frameCount); + + virtual ~CurveTimeline(); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction) = 0; + + virtual int getPropertyId() = 0; + + size_t getFrameCount(); + + void setLinear(size_t frameIndex); + + void setStepped(size_t frameIndex); + + /// Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next. + /// cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of + /// the difference between the keyframe's values. + void setCurve(size_t frameIndex, float cx1, float cy1, float cx2, float cy2); + + float getCurvePercent(size_t frameIndex, float percent); + + float getCurveType(size_t frameIndex); + + protected: + static const float LINEAR; + static const float STEPPED; + static const float BEZIER; + static const int BEZIER_SIZE; + + private: + Vector _curves; // type, x, y, ... + }; +} + +#endif /* Spine_CurveTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Debug.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Debug.h new file mode 100644 index 0000000..61c3d3b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Debug.h @@ -0,0 +1,127 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_DEBUG_H +#define SPINE_DEBUG_H + +#include + +#include + +namespace spine { +class SP_API DebugExtension : public SpineExtension { + struct Allocation { + void *address; + size_t size; + const char *fileName; + int line; + + Allocation() : address(NULL), size(0), fileName(NULL), line(0) { + } + + Allocation(void *a, size_t s, const char *f, int l) : address(a), size(s), fileName(f), line(l) { + } + }; + +public: + DebugExtension(SpineExtension* extension): _extension(extension), _allocations(0), _reallocations(0), _frees(0) { + } + + void reportLeaks() { + for (std::map::iterator it = _allocated.begin(); it != _allocated.end(); it++) { + printf("\"%s:%i (%zu bytes at %p)\n", it->second.fileName, it->second.line, it->second.size, it->second.address); + } + printf("allocations: %zu, reallocations: %zu, frees: %zu\n", _allocations, _reallocations, _frees); + if (_allocated.empty()) printf("No leaks detected"); + } + + void clearAllocations() { + _allocated.clear(); + _usedMemory = 0; + } + + virtual void *_alloc(size_t size, const char *file, int line) { + void *result = _extension->_alloc(size, file, line); + _allocated[result] = Allocation(result, size, file, line); + _allocations++; + _usedMemory += size; + return result; + } + + virtual void *_calloc(size_t size, const char *file, int line) { + void *result = _extension->_calloc(size, file, line); + _allocated[result] = Allocation(result, size, file, line); + _allocations++; + _usedMemory += size; + return result; + } + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) { + if (_allocated.count(ptr)) _usedMemory -= _allocated[ptr].size; + _allocated.erase(ptr); + void *result = _extension->_realloc(ptr, size, file, line); + _reallocations++; + _allocated[result] = Allocation(result, size, file, line); + _usedMemory += size; + return result; + } + + virtual void _free(void *mem, const char *file, int line) { + if (_allocated.count(mem)) { + _extension->_free(mem, file, line); + _frees++; + _usedMemory -= _allocated[mem].size; + _allocated.erase(mem); + return; + } + + printf("%s:%i (address %p): Double free or not allocated through SpineExtension\n", file, line, mem); + _extension->_free(mem, file, line); + } + + virtual char *_readFile(const String &path, int *length) { + return _extension->_readFile(path, length); + } + + size_t getUsedMemory() { + return _usedMemory; + } + +private: + SpineExtension* _extension; + std::map _allocated; + size_t _allocations; + size_t _reallocations; + size_t _frees; + size_t _usedMemory; +}; +} + + +#endif //SPINE_DEBUG_H diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/DeformTimeline.h new file mode 100644 index 0000000..05632c3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -0,0 +1,69 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DeformTimeline_h +#define Spine_DeformTimeline_h + +#include + +namespace spine { + class VertexAttachment; + + class SP_API DeformTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit DeformTimeline(int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, Vector& vertices); + + int getSlotIndex(); + void setSlotIndex(int inValue); + Vector& getFrames(); + Vector< Vector >& getVertices(); + VertexAttachment* getAttachment(); + void setAttachment(VertexAttachment* inValue); + + private: + int _slotIndex; + Vector _frames; + Vector< Vector > _frameVertices; + VertexAttachment* _attachment; + }; +} + +#endif /* Spine_DeformTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h new file mode 100644 index 0000000..867e94e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DrawOrderTimeline_h +#define Spine_DrawOrderTimeline_h + +#include + +namespace spine { + class SP_API DrawOrderTimeline : public Timeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit DrawOrderTimeline(int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + + /// Sets the time and value of the specified keyframe. + /// @param drawOrder May be NULL to use bind pose draw order + void setFrame(size_t frameIndex, float time, Vector& drawOrder); + + Vector& getFrames(); + Vector< Vector >& getDrawOrders(); + size_t getFrameCount(); + + private: + Vector _frames; + Vector< Vector > _drawOrders; + }; +} + +#endif /* Spine_DrawOrderTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Event.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Event.h new file mode 100644 index 0000000..23d082e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Event.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Event_h +#define Spine_Event_h + +#include +#include + +namespace spine { +class EventData; + +/// Stores the current pose values for an Event. +class SP_API Event : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + +public: + Event(float time, const EventData &data); + + const EventData &getData(); + + /// The animation time this event was keyed. + float getTime(); + + int getIntValue(); + + void setIntValue(int inValue); + + float getFloatValue(); + + void setFloatValue(float inValue); + + const String &getStringValue(); + + void setStringValue(const String &inValue); + + float getVolume(); + + void setVolume(float inValue); + + float getBalance(); + + void setBalance(float inValue); + +private: + const EventData &_data; + const float _time; + int _intValue; + float _floatValue; + String _stringValue; + float _volume; + float _balance; +}; +} + +#endif /* Spine_Event_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/EventData.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/EventData.h new file mode 100644 index 0000000..58770e3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/EventData.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_EventData_h +#define Spine_EventData_h + +#include +#include + +namespace spine { +/// Stores the setup pose values for an Event. +class SP_API EventData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class Event; + +public: + explicit EventData(const String &name); + + /// The name of the event, which is unique within the skeleton. + const String &getName() const; + + int getIntValue() const; + + void setIntValue(int inValue); + + float getFloatValue() const; + + void setFloatValue(float inValue); + + const String &getStringValue() const; + + void setStringValue(const String &inValue); + + const String &getAudioPath() const; + + void setAudioPath(const String &inValue); + + float getVolume() const; + + void setVolume(float inValue); + + float getBalance() const; + + void setBalance(float inValue); + +private: + const String _name; + int _intValue; + float _floatValue; + String _stringValue; + String _audioPath; + float _volume; + float _balance; +}; +} + +#endif /* Spine_EventData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/EventTimeline.h new file mode 100644 index 0000000..f6e0ff2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_EventTimeline_h +#define Spine_EventTimeline_h + +#include + +namespace spine { + class SP_API EventTimeline : public Timeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit EventTimeline(int frameCount); + + ~EventTimeline(); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + + /// Sets the time and value of the specified keyframe. + void setFrame(size_t frameIndex, Event* event); + + const Vector& getFrames(); + Vector& getEvents(); + size_t getFrameCount(); + + private: + Vector _frames; + Vector _events; + }; +} + +#endif /* Spine_EventTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Extension.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Extension.h new file mode 100644 index 0000000..c417ef8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Extension.h @@ -0,0 +1,125 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Extension_h +#define Spine_Extension_h + + +#include +#include + +#define SP_UNUSED(x) (void)(x) + +namespace spine { +class String; + +class SP_API SpineExtension { +public: + template + static T *alloc(size_t num, const char *file, int line) { + return (T *) getInstance()->_alloc(sizeof(T) * num, file, line); + } + + template + static T *calloc(size_t num, const char *file, int line) { + return (T *) getInstance()->_calloc(sizeof(T) * num, file, line); + } + + template + static T *realloc(T *ptr, size_t num, const char *file, int line) { + return (T *) getInstance()->_realloc(ptr, sizeof(T) * num, file, line); + } + + template + static void free(T *ptr, const char *file, int line) { + getInstance()->_free((void *) ptr, file, line); + } + + template + static void beforeFree(T *ptr) { + getInstance()->_beforeFree((void *) ptr); + } + + static char *readFile(const String &path, int *length) { + return getInstance()->_readFile(path, length); + } + + static void setInstance(SpineExtension *inSpineExtension); + + static SpineExtension *getInstance(); + + virtual ~SpineExtension(); + + /// Implement this function to use your own memory allocator + virtual void *_alloc(size_t size, const char *file, int line) = 0; + + virtual void *_calloc(size_t size, const char *file, int line) = 0; + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) = 0; + + /// If you provide a spineAllocFunc, you should also provide a spineFreeFunc + virtual void _free(void *mem, const char *file, int line) = 0; + + virtual char *_readFile(const String &path, int *length) = 0; + + virtual void _beforeFree(void *ptr) { SP_UNUSED(ptr); } + +protected: + SpineExtension(); + +private: + static SpineExtension *_instance; +}; + +class SP_API DefaultSpineExtension : public SpineExtension { +public: + DefaultSpineExtension(); + + virtual ~DefaultSpineExtension(); + +protected: + virtual void *_alloc(size_t size, const char *file, int line); + + virtual void *_calloc(size_t size, const char *file, int line); + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line); + + virtual void _free(void *mem, const char *file, int line); + + virtual char *_readFile(const String &path, int *length); +}; + +// This function is to be implemented by engine specific runtimes to provide +// the default extension for that engine. It is called the first time +// SpineExtension::getInstance() is called, when no instance has been set +// yet. +extern SpineExtension *getDefaultExtension(); +} + +#endif /* Spine_Extension_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/HasRendererObject.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/HasRendererObject.h new file mode 100644 index 0000000..73162da --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/HasRendererObject.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_HasRendererObject_h +#define Spine_HasRendererObject_h + +namespace spine { + +typedef void (*DisposeRendererObject) (void* rendererObject); + +class SP_API HasRendererObject { +public: + explicit HasRendererObject() : _rendererObject(NULL), _dispose(NULL) {}; + + virtual ~HasRendererObject() { + if (_dispose && _rendererObject) + _dispose(_rendererObject); + } + + void* getRendererObject() { return _rendererObject; } + void setRendererObject(void* rendererObject, DisposeRendererObject dispose = NULL) { + if (_dispose && _rendererObject && _rendererObject != rendererObject) + _dispose(_rendererObject); + + _rendererObject = rendererObject; + _dispose = dispose; + } +private: + void *_rendererObject; + DisposeRendererObject _dispose; +}; + +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/HashMap.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/HashMap.h new file mode 100755 index 0000000..9a1a1ec --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -0,0 +1,190 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_HashMap_h +#define Spine_HashMap_h + +#include +#include +#include + + // Required for new with line number and file name in MSVC +#ifdef _MSC_VER +#pragma warning(disable:4291) +#endif + +namespace spine { +template +class SP_API HashMap : public SpineObject { +private: + class Entry; + +public: + class SP_API Pair { + public: + explicit Pair(K &k, V &v) : key(k), value(v) {} + + K &key; + V &value; + }; + + class SP_API Entries { + public: + friend class HashMap; + + explicit Entries(Entry *entry) : _entry(NULL), _hasChecked(false) { + _start.next = entry; + _entry = &_start; + } + + Pair next() { + assert(_entry); + assert(_hasChecked); + _entry = _entry->next; + Pair pair(_entry->_key, _entry->_value); + _hasChecked = false; + return pair; + } + + bool hasNext() { + _hasChecked = true; + return _entry->next; + } + + private: + bool _hasChecked; + Entry _start; + Entry *_entry; + }; + + HashMap() : + _head(NULL), + _size(0) { + } + + ~HashMap() { + clear(); + } + + void clear() { + for (Entry *entry = _head; entry != NULL;) { + Entry* next = entry->next; + delete entry; + entry = next; + } + _head = NULL; + _size = 0; + } + + size_t size() { + return _size; + } + + void put(const K &key, const V &value) { + Entry *entry = find(key); + if (entry) { + entry->_key = key; + entry->_value = value; + } else { + entry = new(__FILE__, __LINE__) Entry(); + entry->_key = key; + entry->_value = value; + + Entry *oldHead = _head; + + if (oldHead) { + _head = entry; + oldHead->prev = entry; + entry->next = oldHead; + } else { + _head = entry; + } + _size++; + } + } + + bool containsKey(const K &key) { + return find(key) != NULL; + } + + bool remove(const K &key) { + Entry *entry = find(key); + if (!entry) return false; + + Entry *prev = entry->prev; + Entry *next = entry->next; + + if (prev) prev->next = next; + else _head = next; + if (next) next->prev = entry->prev; + + delete entry; + _size--; + + return true; + } + + V operator[](const K &key) { + Entry *entry = find(key); + if (entry) return entry->_value; + else { + assert(false); + return 0; + } + } + + Entries getEntries() const { + return Entries(_head); + } + +private: + Entry *find(const K &key) { + for (Entry *entry = _head; entry != NULL; entry = entry->next) { + if (entry->_key == key) + return entry; + } + return NULL; + } + + class SP_API Entry : public SpineObject { + public: + K _key; + V _value; + Entry *next; + Entry *prev; + + Entry() : next(NULL), prev(NULL) {} + }; + + Entry *_head; + size_t _size; +}; +} + +#endif /* Spine_HashMap_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/IkConstraint.h new file mode 100644 index 0000000..bef4832 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraint_h +#define Spine_IkConstraint_h + +#include + +#include + +namespace spine { +class IkConstraintData; + +class Skeleton; + +class Bone; + +class SP_API IkConstraint : public Updatable { + friend class Skeleton; + + friend class IkConstraintTimeline; + +RTTI_DECL + +public: + /// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified + /// in the world coordinate system. + static void apply(Bone &bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha); + + /// Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as + /// possible. The target is specified in the world coordinate system. + /// @param child A direct descendant of the parent bone. + static void apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, float softness, float alpha); + + IkConstraint(IkConstraintData &data, Skeleton &skeleton); + + /// Applies the constraint to the constrained bones. + void apply(); + + virtual void update(); + + virtual int getOrder(); + + IkConstraintData &getData(); + + Vector &getBones(); + + Bone *getTarget(); + + void setTarget(Bone *inValue); + + int getBendDirection(); + + void setBendDirection(int inValue); + + bool getCompress(); + + void setCompress(bool inValue); + + bool getStretch(); + + void setStretch(bool inValue); + + float getMix(); + + void setMix(float inValue); + + float getSoftness(); + + void setSoftness(float inValue); + + bool isActive(); + + void setActive(bool inValue); + +private: + IkConstraintData &_data; + Vector _bones; + int _bendDirection; + bool _compress; + bool _stretch; + float _mix; + float _softness; + Bone *_target; + bool _active; +}; +} + +#endif /* Spine_IkConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/IkConstraintData.h new file mode 100644 index 0000000..cbf7cd8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -0,0 +1,89 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraintData_h +#define Spine_IkConstraintData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SP_API IkConstraintData : public ConstraintData { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class IkConstraint; + friend class Skeleton; + friend class IkConstraintTimeline; + + public: + explicit IkConstraintData(const String& name); + + /// The bones that are constrained by this IK Constraint. + Vector& getBones(); + + /// The bone that is the IK target. + BoneData* getTarget(); + void setTarget(BoneData* inValue); + + /// Controls the bend direction of the IK bones, either 1 or -1. + int getBendDirection(); + void setBendDirection(int inValue); + + bool getCompress(); + void setCompress(bool inValue); + + bool getStretch(); + void setStretch(bool inValue); + + bool getUniform(); + void setUniform(bool inValue); + + float getMix(); + void setMix(float inValue); + + float getSoftness(); + void setSoftness(float inValue); + + private: + Vector _bones; + BoneData* _target; + int _bendDirection; + bool _compress; + bool _stretch; + bool _uniform; + float _mix; + float _softness; + }; +} + +#endif /* Spine_IkConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h new file mode 100644 index 0000000..c710b78 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraintTimeline_h +#define Spine_IkConstraintTimeline_h + +#include + +namespace spine { + + class SP_API IkConstraintTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + static const int ENTRIES; + + explicit IkConstraintTimeline(int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + + /// Sets the time, mix and bend direction of the specified keyframe. + void setFrame (int frameIndex, float time, float mix, float softness, int bendDirection, bool compress, bool stretch); + + private: + static const int PREV_TIME; + static const int PREV_MIX; + static const int PREV_SOFTNESS; + static const int PREV_BEND_DIRECTION; + static const int PREV_COMPRESS; + static const int PREV_STRETCH; + static const int MIX; + static const int SOFTNESS; + static const int BEND_DIRECTION; + static const int COMPRESS; + static const int STRETCH; + + Vector _frames; + int _ikConstraintIndex; + }; +} + +#endif /* Spine_IkConstraintTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Json.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Json.h new file mode 100644 index 0000000..de676bf --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Json.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Json_h +#define Spine_Json_h + +#include + +#ifndef SPINE_JSON_HAVE_PREV +/* spine doesn't use the "prev" link in the Json sibling lists. */ +#define SPINE_JSON_HAVE_PREV 0 +#endif + +namespace spine { +class SP_API Json : public SpineObject { + friend class SkeletonJson; + +public: + /* Json Types: */ + static const int JSON_FALSE; + static const int JSON_TRUE; + static const int JSON_NULL; + static const int JSON_NUMBER; + static const int JSON_STRING; + static const int JSON_ARRAY; + static const int JSON_OBJECT; + + /* Get item "string" from object. Case insensitive. */ + static Json *getItem(Json *object, const char *string); + + static const char *getString(Json *object, const char *name, const char *defaultValue); + + static float getFloat(Json *object, const char *name, float defaultValue); + + static int getInt(Json *object, const char *name, int defaultValue); + + static bool getBoolean(Json *object, const char *name, bool defaultValue); + + /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when Json_create() returns 0. 0 when Json_create() succeeds. */ + static const char *getError(); + + /* Supply a block of JSON, and this returns a Json object you can interrogate. Call Json_dispose when finished. */ + explicit Json(const char *value); + + ~Json(); + + + +private: + static const char *_error; + + Json *_next; +#if SPINE_JSON_HAVE_PREV + Json* _prev; /* next/prev allow you to walk array/object chains. Alternatively, use getSize/getItem */ +#endif + Json *_child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int _type; /* The type of the item, as above. */ + int _size; /* The number of children. */ + + const char *_valueString; /* The item's string, if type==JSON_STRING */ + int _valueInt; /* The item's number, if type==JSON_NUMBER */ + float _valueFloat; /* The item's number, if type==JSON_NUMBER */ + + const char *_name; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + + /* Utility to jump whitespace and cr/lf */ + static const char *skip(const char *inValue); + + /* Parser core - when encountering text, process appropriately. */ + static const char *parseValue(Json *item, const char *value); + + /* Parse the input text into an unescaped cstring, and populate item. */ + static const char *parseString(Json *item, const char *str); + + /* Parse the input text to generate a number, and populate the result into item. */ + static const char *parseNumber(Json *item, const char *num); + + /* Build an array from input text. */ + static const char *parseArray(Json *item, const char *value); + + /* Build an object from the text. */ + static const char *parseObject(Json *item, const char *value); + + static int json_strcasecmp(const char *s1, const char *s2); +}; +} + +#endif /* Spine_Json_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/LinkedMesh.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/LinkedMesh.h new file mode 100644 index 0000000..10e7003 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/LinkedMesh.h @@ -0,0 +1,56 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_LinkedMesh_h +#define Spine_LinkedMesh_h + +#include +#include + +namespace spine { +class MeshAttachment; + +class SP_API LinkedMesh : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + +public: + LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, bool inheritDeform); + +private: + MeshAttachment *_mesh; + String _skin; + size_t _slotIndex; + String _parent; + bool _inheritDeform; +}; +} + +#endif /* Spine_LinkedMesh_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/MathUtil.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/MathUtil.h new file mode 100644 index 0000000..7d85c7d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MathUtil_h +#define Spine_MathUtil_h + +#include + +#include + +namespace spine { + +class SP_API MathUtil : public SpineObject { +private: + MathUtil(); + +public: + static const float Pi; + static const float Pi_2; + static const float Deg_Rad; + static const float Rad_Deg; + + template + static inline T min(T a, T b) { return a < b ? a : b; } + + template + static inline T max(T a, T b) { return a > b ? a : b; } + + static float sign(float val); + + static float clamp(float x, float lower, float upper); + + static float abs(float v); + + /// Returns the sine in radians from a lookup table. + static float sin(float radians); + + /// Returns the cosine in radians from a lookup table. + static float cos(float radians); + + /// Returns the sine in radians from a lookup table. + static float sinDeg(float degrees); + + /// Returns the cosine in radians from a lookup table. + static float cosDeg(float degrees); + + /// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 + /// degrees), largest error of 0.00488 radians (0.2796 degrees). + static float atan2(float y, float x); + + static float acos(float v); + + static float sqrt(float v); + + static float fmod(float a, float b); + + static bool isNan(float v); + + static float random(); + + static float randomTriangular(float min, float max); + + static float randomTriangular(float min, float max, float mode); + + static float pow(float a, float b); +}; + +struct SP_API Interpolation { + virtual float apply(float a) = 0; + + virtual float interpolate(float start, float end, float a) { + return start + (end - start) * apply(a); + } + + virtual ~Interpolation() {}; +}; + +struct SP_API PowInterpolation: public Interpolation { + PowInterpolation(int power): power(power) { + } + + float apply(float a) { + if (a <= 0.5f) return MathUtil::pow(a * 2.0f, (float)power) / 2.0f; + return MathUtil::pow((a - 1.0f) * 2.0f, (float)power) / (power % 2 == 0 ? -2.0f : 2.0f) + 1.0f; + } + + int power; +}; + +struct SP_API PowOutInterpolation: public Interpolation { + PowOutInterpolation(int power): power(power) { + } + + float apply(float a) { + return MathUtil::pow(a - 1, (float)power) * (power % 2 == 0 ? -1.0f : 1.0f) + 1.0f; + } + + int power; +}; + +} + +#endif /* Spine_MathUtil_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/MeshAttachment.h new file mode 100644 index 0000000..dece05f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -0,0 +1,143 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MeshAttachment_h +#define Spine_MeshAttachment_h + +#include +#include +#include +#include + +namespace spine { + /// Attachment that displays a texture region using a mesh. + class SP_API MeshAttachment : public VertexAttachment, public HasRendererObject { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class AtlasAttachmentLoader; + + RTTI_DECL + + public: + explicit MeshAttachment(const String& name); + + virtual ~MeshAttachment(); + + void updateUVs(); + + int getHullLength(); + void setHullLength(int inValue); + + Vector& getRegionUVs(); + + /// The UV pair for each vertex, normalized within the entire texture. See also MeshAttachment::updateUVs + Vector& getUVs(); + + Vector& getTriangles(); + + Color& getColor(); + + const String& getPath(); + void setPath(const String& inValue); + + float getRegionU(); + void setRegionU(float inValue); + + float getRegionV(); + void setRegionV(float inValue); + + float getRegionU2(); + void setRegionU2(float inValue); + + float getRegionV2(); + void setRegionV2(float inValue); + + bool getRegionRotate(); + void setRegionRotate(bool inValue); + + int getRegionDegrees(); + void setRegionDegrees(int inValue); + + float getRegionOffsetX(); + void setRegionOffsetX(float inValue); + + // Pixels stripped from the bottom left, unrotated. + float getRegionOffsetY(); + void setRegionOffsetY(float inValue); + + float getRegionWidth(); + void setRegionWidth(float inValue); + + // Unrotated, stripped size. + float getRegionHeight(); + void setRegionHeight(float inValue); + + float getRegionOriginalWidth(); + void setRegionOriginalWidth(float inValue); + + // Unrotated, unstripped size. + float getRegionOriginalHeight(); + void setRegionOriginalHeight(float inValue); + + MeshAttachment* getParentMesh(); + void setParentMesh(MeshAttachment* inValue); + + // Nonessential. + Vector& getEdges(); + float getWidth(); + void setWidth(float inValue); + float getHeight(); + void setHeight(float inValue); + + virtual Attachment* copy(); + + MeshAttachment* newLinkedMesh(); + + private: + float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; + MeshAttachment* _parentMesh; + Vector _uvs; + Vector _regionUVs; + Vector _triangles; + Vector _edges; + String _path; + float _regionU; + float _regionV; + float _regionU2; + float _regionV2; + float _width; + float _height; + Color _color; + int _hullLength; + bool _regionRotate; + int _regionDegrees; + }; +} + +#endif /* Spine_MeshAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/MixBlend.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/MixBlend.h new file mode 100644 index 0000000..5e709ae --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/MixBlend.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MixPose_h +#define Spine_MixPose_h + +namespace spine { + +/// Controls how a timeline is mixed with the setup or current pose. +/// See also Timeline::apply(Skeleton&, float, float, Vector&, float, Blend, MixDirection) +enum MixBlend { + MixBlend_Setup = 0, + MixBlend_First, + MixBlend_Replace, + MixBlend_Add +}; +} + +#endif /* Spine_MixPose_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/MixDirection.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/MixDirection.h new file mode 100644 index 0000000..1a61832 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/MixDirection.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MixDirection_h +#define Spine_MixDirection_h + +namespace spine { + +/// Indicates whether a timeline's alpha is mixing out over time toward 0 (the setup or current pose) or mixing in toward 1 (the timeline's pose). +/// See also Timeline::apply(Skeleton&, float, float, Vector&, float, MixPose, MixDirection) +enum MixDirection { + MixDirection_In = 0, + MixDirection_Out +}; + +} + +#endif /* Spine_MixDirection_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathAttachment.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathAttachment.h new file mode 100644 index 0000000..fd054b4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathAttachment.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathAttachment_h +#define Spine_PathAttachment_h + +#include + +namespace spine { + class SP_API PathAttachment : public VertexAttachment { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathAttachment(const String& name); + + /// The length in the setup pose from the start of the path to the end of each curve. + Vector& getLengths(); + bool isClosed(); + void setClosed(bool inValue); + bool isConstantSpeed(); + void setConstantSpeed(bool inValue); + + virtual Attachment* copy(); + private: + Vector _lengths; + bool _closed; + bool _constantSpeed; + }; +} + +#endif /* Spine_PathAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraint.h new file mode 100644 index 0000000..470d899 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraint_h +#define Spine_PathConstraint_h + +#include + +#include + +namespace spine { + class PathConstraintData; + class Skeleton; + class PathAttachment; + class Bone; + class Slot; + + class SP_API PathConstraint : public Updatable { + friend class Skeleton; + friend class PathConstraintMixTimeline; + friend class PathConstraintPositionTimeline; + friend class PathConstraintSpacingTimeline; + + RTTI_DECL + + public: + PathConstraint(PathConstraintData& data, Skeleton& skeleton); + + /// Applies the constraint to the constrained bones. + void apply(); + + virtual void update(); + + virtual int getOrder(); + + float getPosition(); + void setPosition(float inValue); + + float getSpacing(); + void setSpacing(float inValue); + + float getRotateMix(); + void setRotateMix(float inValue); + + float getTranslateMix(); + void setTranslateMix(float inValue); + + Vector& getBones(); + + Slot* getTarget(); + void setTarget(Slot* inValue); + + PathConstraintData& getData(); + + bool isActive(); + + void setActive(bool inValue); + + private: + static const float EPSILON; + static const int NONE; + static const int BEFORE; + static const int AFTER; + + PathConstraintData& _data; + Vector _bones; + Slot* _target; + float _position, _spacing, _rotateMix, _translateMix; + + Vector _spaces; + Vector _positions; + Vector _world; + Vector _curves; + Vector _lengths; + Vector _segments; + + bool _active; + + Vector& computeWorldPositions(PathAttachment& path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing); + + static void addBeforePosition(float p, Vector& temp, int i, Vector& output, int o); + + static void addAfterPosition(float p, Vector& temp, int i, Vector& output, int o); + + static void addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, Vector& output, int o, bool tangents); + }; +} + +#endif /* Spine_PathConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraintData.h new file mode 100644 index 0000000..97f8b84 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintData_h +#define Spine_PathConstraintData_h + +#include +#include +#include +#include +#include +#include +#include + +namespace spine { + class BoneData; + class SlotData; + + class SP_API PathConstraintData : public ConstraintData { + friend class SkeletonBinary; + friend class SkeletonJson; + + friend class PathConstraint; + friend class Skeleton; + friend class PathConstraintMixTimeline; + friend class PathConstraintPositionTimeline; + friend class PathConstraintSpacingTimeline; + + public: + explicit PathConstraintData(const String& name); + + Vector& getBones(); + + SlotData* getTarget(); + void setTarget(SlotData* inValue); + + PositionMode getPositionMode(); + void setPositionMode(PositionMode inValue); + + SpacingMode getSpacingMode(); + void setSpacingMode(SpacingMode inValue); + + RotateMode getRotateMode(); + void setRotateMode(RotateMode inValue); + + float getOffsetRotation(); + void setOffsetRotation(float inValue); + + float getPosition(); + void setPosition(float inValue); + + float getSpacing(); + void setSpacing(float inValue); + + float getRotateMix(); + void setRotateMix(float inValue); + + float getTranslateMix(); + void setTranslateMix(float inValue); + + private: + Vector _bones; + SlotData* _target; + PositionMode _positionMode; + SpacingMode _spacingMode; + RotateMode _rotateMode; + float _offsetRotation; + float _position, _spacing, _rotateMix, _translateMix; + }; +} + +#endif /* Spine_PathConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h new file mode 100644 index 0000000..9537ff0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintMixTimeline_h +#define Spine_PathConstraintMixTimeline_h + +#include + +namespace spine { +#define SP_PATHCONSTRAINTMIXTIMELINE_ENTRIES 5 + + class SP_API PathConstraintMixTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + static const int ENTRIES; + + explicit PathConstraintMixTimeline(int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + + private: + static const int PREV_TIME; + static const int PREV_ROTATE; + static const int PREV_TRANSLATE; + static const int ROTATE; + static const int TRANSLATE; + + Vector _frames; + int _pathConstraintIndex; + + /// Sets the time and mixes of the specified keyframe. + void setFrame(int frameIndex, float time, float rotateMix, float translateMix); + }; +} + +#endif /* Spine_PathConstraintMixTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h new file mode 100644 index 0000000..3c11bf1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintPositionTimeline_h +#define Spine_PathConstraintPositionTimeline_h + +#include + +namespace spine { + + class SP_API PathConstraintPositionTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + static const int ENTRIES; + + explicit PathConstraintPositionTimeline(int frameCount); + + virtual ~PathConstraintPositionTimeline(); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, float value); + + protected: + static const int PREV_TIME; + static const int PREV_VALUE; + static const int VALUE; + + Vector _frames; + int _pathConstraintIndex; + }; +} + +#endif /* Spine_PathConstraintPositionTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h new file mode 100644 index 0000000..d3e9bd9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintSpacingTimeline_h +#define Spine_PathConstraintSpacingTimeline_h + +#include + +namespace spine { + class SP_API PathConstraintSpacingTimeline : public PathConstraintPositionTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathConstraintSpacingTimeline(int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + }; +} + +#endif /* Spine_PathConstraintSpacingTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PointAttachment.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PointAttachment.h new file mode 100644 index 0000000..7860a99 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PointAttachment.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PointAttachment_h +#define Spine_PointAttachment_h + +#include + +namespace spine { + class Bone; + + /// An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be + /// used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a + /// skin. + /// + /// See http://esotericsoftware.com/spine-point-attachments for Point Attachments in the Spine User Guide. + /// + class SP_API PointAttachment : public Attachment { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PointAttachment(const String& name); + + void computeWorldPosition(Bone& bone, float& ox, float& oy); + + float computeWorldRotation(Bone& bone); + + float getX(); + void setX(float inValue); + + float getY(); + void setY(float inValue); + + float getRotation(); + void setRotation(float inValue); + + virtual Attachment* copy(); + + private: + float _x, _y, _rotation; + }; +} + +#endif /* Spine_PointAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Pool.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Pool.h new file mode 100644 index 0000000..54e220c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Pool.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Pool_h +#define Spine_Pool_h + +#include +#include +#include +#include + +namespace spine { +template +class SP_API Pool : public SpineObject { +public: + Pool() { + } + + ~Pool() { + ContainerUtil::cleanUpVectorOfPointers(_objects); + } + + T *obtain() { + if (_objects.size() > 0) { + T **object = &_objects[_objects.size() - 1]; + T *ret = *object; + _objects.removeAt(_objects.size() - 1); + + return ret; + } else { + T *ret = new(__FILE__, __LINE__) T(); + + return ret; + } + } + + void free(T *object) { + if (!_objects.contains(object)) { + _objects.add(object); + } + } + +private: + Vector _objects; +}; +} + +#endif /* Spine_Pool_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PositionMode.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PositionMode.h new file mode 100644 index 0000000..0c9157b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/PositionMode.h @@ -0,0 +1,40 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PositionMode_h +#define Spine_PositionMode_h + +namespace spine { +enum PositionMode { + PositionMode_Fixed = 0, + PositionMode_Percent +}; +} + +#endif /* Spine_PositionMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/RTTI.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/RTTI.h new file mode 100644 index 0000000..7f12e54 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/RTTI.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RTTI_h +#define Spine_RTTI_h + +#include + +namespace spine { +class SP_API RTTI : public SpineObject { +public: + explicit RTTI(const char *className); + + RTTI(const char *className, const RTTI &baseRTTI); + + const char *getClassName() const; + + bool isExactly(const RTTI &rtti) const; + + bool instanceOf(const RTTI &rtti) const; + +private: + // Prevent copying + RTTI(const RTTI &obj); + + RTTI &operator=(const RTTI &obj); + + const char* _className; + const RTTI *_pBaseRTTI; +}; +} + +#define RTTI_DECL \ +public: \ +static const spine::RTTI rtti; \ +virtual const spine::RTTI& getRTTI() const; + +#define RTTI_IMPL_NOPARENT(name) \ +const spine::RTTI name::rtti(#name); \ +const spine::RTTI& name::getRTTI() const { return rtti; } + +#define RTTI_IMPL(name, parent) \ +const spine::RTTI name::rtti(#name, parent::rtti); \ +const spine::RTTI& name::getRTTI() const { return rtti; } + +#endif /* Spine_RTTI_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/RegionAttachment.h new file mode 100644 index 0000000..fe87207 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RegionAttachment_h +#define Spine_RegionAttachment_h + +#include +#include +#include + +#include + +#define NUM_UVS 8 + +namespace spine { + class Bone; + + /// Attachment that displays a texture region. + class SP_API RegionAttachment : public Attachment, public HasRendererObject { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class AtlasAttachmentLoader; + + RTTI_DECL + + public: + explicit RegionAttachment(const String& name); + + void updateOffset(); + + void setUVs(float u, float v, float u2, float v2, bool rotate); + + /// Transforms the attachment's four vertices to world coordinates. + /// @param bone The parent bone. + /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8. + /// @param offset The worldVertices index to begin writing values. + /// @param stride The number of worldVertices entries between the value pairs written. + void computeWorldVertices(Bone& bone, float *worldVertices, size_t offset, size_t stride = 2); + void computeWorldVertices(Bone& bone, Vector& worldVertices, size_t offset, size_t stride = 2); + + float getX(); + void setX(float inValue); + float getY(); + void setY(float inValue); + float getRotation(); + void setRotation(float inValue); + float getScaleX(); + void setScaleX(float inValue); + float getScaleY(); + void setScaleY(float inValue); + float getWidth(); + void setWidth(float inValue); + float getHeight(); + void setHeight(float inValue); + + Color& getColor(); + + const String& getPath(); + void setPath(const String& inValue); + + float getRegionOffsetX(); + void setRegionOffsetX(float inValue); + + float getRegionOffsetY(); + void setRegionOffsetY(float inValue); + + float getRegionWidth(); + void setRegionWidth(float inValue); + + float getRegionHeight(); + void setRegionHeight(float inValue); + + float getRegionOriginalWidth(); + void setRegionOriginalWidth(float inValue); + + float getRegionOriginalHeight(); + void setRegionOriginalHeight(float inValue); + + Vector& getOffset(); + Vector& getUVs(); + + virtual Attachment* copy(); + + private: + static const int BLX; + static const int BLY; + static const int ULX; + static const int ULY; + static const int URX; + static const int URY; + static const int BRX; + static const int BRY; + + float _x, _y, _rotation, _scaleX, _scaleY, _width, _height; + float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; + Vector _vertexOffset; + Vector _uvs; + String _path; + float _regionU; + float _regionV; + float _regionU2; + float _regionV2; + Color _color; + }; +} + +#endif /* Spine_RegionAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/RotateMode.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/RotateMode.h new file mode 100644 index 0000000..42f3355 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/RotateMode.h @@ -0,0 +1,41 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RotateMode_h +#define Spine_RotateMode_h + +namespace spine { +enum RotateMode { + RotateMode_Tangent = 0, + RotateMode_Chain, + RotateMode_ChainScale +}; +} + +#endif /* Spine_RotateMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/RotateTimeline.h new file mode 100644 index 0000000..0c6f89b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RotateTimeline_h +#define Spine_RotateTimeline_h + +#include + +namespace spine { + class SP_API RotateTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class AnimationState; + + RTTI_DECL + + public: + static const int ENTRIES = 2; + + explicit RotateTimeline(int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, float degrees); + + int getBoneIndex(); + void setBoneIndex(int inValue); + + Vector& getFrames(); + + private: + static const int PREV_TIME = -2; + static const int PREV_ROTATION = -1; + static const int ROTATION = 1; + + int _boneIndex; + Vector _frames; // time, angle, ... + }; +} + +#endif /* Spine_RotateTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h new file mode 100644 index 0000000..984b9d7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ScaleTimeline_h +#define Spine_ScaleTimeline_h + +#include + +namespace spine { + class SP_API ScaleTimeline : public TranslateTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ScaleTimeline(int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + }; +} + +#endif /* Spine_ScaleTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ShearTimeline.h new file mode 100644 index 0000000..4f6f12f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ShearTimeline_h +#define Spine_ShearTimeline_h + +#include + +namespace spine { + class SP_API ShearTimeline : public TranslateTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ShearTimeline(int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + }; +} + +#endif /* Spine_ShearTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Skeleton.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Skeleton.h new file mode 100644 index 0000000..27a3d83 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -0,0 +1,243 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Skeleton_h +#define Spine_Skeleton_h + +#include +#include +#include +#include +#include + +namespace spine { +class SkeletonData; + +class Bone; + +class Updatable; + +class Slot; + +class IkConstraint; + +class PathConstraint; + +class TransformConstraint; + +class Skin; + +class Attachment; + +class SP_API Skeleton : public SpineObject { + friend class AnimationState; + + friend class SkeletonBounds; + + friend class SkeletonClipping; + + friend class AttachmentTimeline; + + friend class ColorTimeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TwoColorTimeline; + +public: + explicit Skeleton(SkeletonData *skeletonData); + + ~Skeleton(); + + /// Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added + /// or removed. + void updateCache(); + + void printUpdateCache(); + + /// Updates the world transform for each bone and applies constraints. + void updateWorldTransform(); + + /// Sets the bones, constraints, and slots to their setup pose values. + void setToSetupPose(); + + /// Sets the bones and constraints to their setup pose values. + void setBonesToSetupPose(); + + void setSlotsToSetupPose(); + + /// @return May be NULL. + Bone *findBone(const String &boneName); + + /// @return -1 if the bone was not found. + int findBoneIndex(const String &boneName); + + /// @return May be NULL. + Slot *findSlot(const String &slotName); + + /// @return -1 if the bone was not found. + int findSlotIndex(const String &slotName); + + /// Sets a skin by name (see setSkin). + void setSkin(const String &skinName); + + /// Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. + /// If there was no old skin, each slot's setup mode attachment is attached from the new skin. + /// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling + /// See Skeleton::setSlotsToSetupPose() + /// Also, often AnimationState::apply(Skeleton&) is called before the next time the + /// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. + /// @param newSkin May be NULL. + void setSkin(Skin *newSkin); + + /// @return May be NULL. + Attachment *getAttachment(const String &slotName, const String &attachmentName); + + /// @return May be NULL. + Attachment *getAttachment(int slotIndex, const String &attachmentName); + + /// @param attachmentName May be empty. + void setAttachment(const String &slotName, const String &attachmentName); + + /// @return May be NULL. + IkConstraint *findIkConstraint(const String &constraintName); + + /// @return May be NULL. + TransformConstraint *findTransformConstraint(const String &constraintName); + + /// @return May be NULL. + PathConstraint *findPathConstraint(const String &constraintName); + + void update(float delta); + + /// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. + /// @param outX The horizontal distance between the skeleton origin and the left side of the AABB. + /// @param outY The vertical distance between the skeleton origin and the bottom side of the AABB. + /// @param outWidth The width of the AABB + /// @param outHeight The height of the AABB. + /// @param outVertexBuffer Reference to hold a Vector of floats. This method will assign it with new floats as needed. + void getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector &outVertexBuffer); + + Bone *getRootBone(); + + SkeletonData *getData(); + + Vector &getBones(); + + Vector &getUpdateCacheList(); + + Vector &getSlots(); + + Vector &getDrawOrder(); + + Vector &getIkConstraints(); + + Vector &getPathConstraints(); + + Vector &getTransformConstraints(); + + Skin *getSkin(); + + Color &getColor(); + + float getTime(); + + void setTime(float inValue); + + void setPosition(float x, float y); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getScaleX(); + + void setScaleX(float inValue); + + float getScaleY(); + + void setScaleY(float inValue); + +private: + SkeletonData *_data; + Vector _bones; + Vector _slots; + Vector _drawOrder; + Vector _ikConstraints; + Vector _transformConstraints; + Vector _pathConstraints; + Vector _updateCache; + Vector _updateCacheReset; + Skin *_skin; + Color _color; + float _time; + float _scaleX, _scaleY; + float _x, _y; + + void sortIkConstraint(IkConstraint *constraint); + + void sortPathConstraint(PathConstraint *constraint); + + void sortTransformConstraint(TransformConstraint *constraint); + + void sortPathConstraintAttachment(Skin *skin, size_t slotIndex, Bone &slotBone); + + void sortPathConstraintAttachment(Attachment *attachment, Bone &slotBone); + + void sortBone(Bone *bone); + + static void sortReset(Vector &bones); +}; +} + +#endif /* Spine_Skeleton_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h new file mode 100644 index 0000000..0a59f30 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -0,0 +1,131 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonBinary_h +#define Spine_SkeletonBinary_h + +#include +#include +#include +#include +#include + +namespace spine { + class SkeletonData; + class Atlas; + class AttachmentLoader; + class LinkedMesh; + class Skin; + class Attachment; + class VertexAttachment; + class Animation; + class CurveTimeline; + + class SP_API SkeletonBinary : public SpineObject { + public: + static const int BONE_ROTATE; + static const int BONE_TRANSLATE; + static const int BONE_SCALE; + static const int BONE_SHEAR; + + static const int SLOT_ATTACHMENT; + static const int SLOT_COLOR; + static const int SLOT_TWO_COLOR; + + static const int PATH_POSITION; + static const int PATH_SPACING; + static const int PATH_MIX; + + static const int CURVE_LINEAR; + static const int CURVE_STEPPED; + static const int CURVE_BEZIER; + + explicit SkeletonBinary(Atlas* atlasArray); + + explicit SkeletonBinary(AttachmentLoader* attachmentLoader, bool ownsLoader = false); + + ~SkeletonBinary(); + + SkeletonData* readSkeletonData(const unsigned char* binary, int length); + + SkeletonData* readSkeletonDataFile(const String& path); + + void setScale(float scale) { _scale = scale; } + + String& getError() { return _error; } + + private: + struct DataInput : public SpineObject { + const unsigned char* cursor; + const unsigned char* end; + }; + + AttachmentLoader* _attachmentLoader; + Vector _linkedMeshes; + String _error; + float _scale; + const bool _ownsLoader; + + void setError(const char* value1, const char* value2); + + char* readString(DataInput* input); + + char* readStringRef(DataInput* input, SkeletonData* skeletonData); + + float readFloat(DataInput* input); + + unsigned char readByte(DataInput* input); + + signed char readSByte(DataInput* input); + + bool readBoolean(DataInput* input); + + int readInt(DataInput* input); + + void readColor(DataInput* input, Color& color); + + int readVarint(DataInput* input, bool optimizePositive); + + Skin* readSkin(DataInput* input, bool defaultSkin, SkeletonData* skeletonData, bool nonessential); + + Attachment* readAttachment(DataInput* input, Skin* skin, int slotIndex, const String& attachmentName, SkeletonData* skeletonData, bool nonessential); + + void readVertices(DataInput* input, VertexAttachment* attachment, int vertexCount); + + void readFloatArray(DataInput *input, int n, float scale, Vector& array); + + void readShortArray(DataInput *input, Vector& array); + + Animation* readAnimation(const String& name, DataInput* input, SkeletonData *skeletonData); + + void readCurve(DataInput* input, int frameIndex, CurveTimeline* timeline); + }; +} + +#endif /* Spine_SkeletonBinary_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h new file mode 100644 index 0000000..eda7362 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h @@ -0,0 +1,106 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonBounds_h +#define Spine_SkeletonBounds_h + +#include +#include +#include + +namespace spine { + class Skeleton; + class BoundingBoxAttachment; + class Polygon; + + /// Collects each BoundingBoxAttachment that is visible and computes the world vertices for its polygon. + /// The polygon vertices are provided along with convenience methods for doing hit detection. + class SP_API SkeletonBounds : public SpineObject { + public: + SkeletonBounds(); + ~SkeletonBounds(); + + /// Clears any previous polygons, finds all visible bounding box attachments, + /// and computes the world vertices for each bounding box's polygon. + /// @param skeleton The skeleton. + /// @param updateAabb + /// If true, the axis aligned bounding box containing all the polygons is computed. + /// If false, the SkeletonBounds AABB methods will always return true. + /// + void update(Skeleton& skeleton, bool updateAabb); + + /// Returns true if the axis aligned bounding box contains the point. + bool aabbcontainsPoint(float x, float y); + + /// Returns true if the axis aligned bounding box intersects the line segment. + bool aabbintersectsSegment(float x1, float y1, float x2, float y2); + + /// Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. + bool aabbIntersectsSkeleton(SkeletonBounds bounds); + + /// Returns true if the polygon contains the point. + bool containsPoint(Polygon* polygon, float x, float y); + + /// Returns the first bounding box attachment that contains the point, or NULL. When doing many checks, it is usually more + /// efficient to only call this method if {@link #aabbcontainsPoint(float, float)} returns true. + BoundingBoxAttachment* containsPoint(float x, float y); + + /// Returns the first bounding box attachment that contains the line segment, or NULL. When doing many checks, it is usually + /// more efficient to only call this method if {@link #aabbintersectsSegment(float, float, float, float)} returns true. + BoundingBoxAttachment* intersectsSegment(float x1, float y1, float x2, float y2); + + /// Returns true if the polygon contains the line segment. + bool intersectsSegment(Polygon* polygon, float x1, float y1, float x2, float y2); + + Polygon* getPolygon(BoundingBoxAttachment* attachment); + + float getWidth(); + float getHeight(); + + private: + Pool _polygonPool; + Vector _boundingBoxes; + Vector _polygons; + float _minX, _minY, _maxX, _maxY; + + void aabbCompute(); + }; + + class Polygon : public SpineObject { + public: + Vector _vertices; + int _count; + + Polygon() : _count(0) { + _vertices.ensureCapacity(16); + } + }; +} + +#endif /* Spine_SkeletonBounds_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h new file mode 100644 index 0000000..ae8bddb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonClipping_h +#define Spine_SkeletonClipping_h + +#include +#include + +namespace spine { + class Slot; + class ClippingAttachment; + + class SP_API SkeletonClipping : public SpineObject { + public: + SkeletonClipping(); + + size_t clipStart(Slot& slot, ClippingAttachment* clip); + + void clipEnd(Slot& slot); + + void clipEnd(); + + void clipTriangles(float* vertices, unsigned short* triangles, size_t trianglesLength, float* uvs, size_t stride); + + void clipTriangles(Vector& vertices, Vector& triangles, Vector& uvs, size_t stride); + + bool isClipping(); + + Vector& getClippedVertices(); + Vector& getClippedTriangles(); + Vector& getClippedUVs(); + + private: + Triangulator _triangulator; + Vector _clippingPolygon; + Vector _clipOutput; + Vector _clippedVertices; + Vector _clippedTriangles; + Vector _clippedUVs; + Vector _scratch; + ClippingAttachment* _clipAttachment; + Vector< Vector* > *_clippingPolygons; + + /** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping + * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */ + bool clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector* clippingArea, Vector* output); + + static void makeClockwise(Vector& polygon); + }; +} + +#endif /* Spine_SkeletonClipping_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonData.h new file mode 100644 index 0000000..90e629b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonData.h @@ -0,0 +1,191 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonData_h +#define Spine_SkeletonData_h + +#include +#include + +namespace spine { +class BoneData; + +class SlotData; + +class Skin; + +class EventData; + +class Animation; + +class IkConstraintData; + +class TransformConstraintData; + +class PathConstraintData; + +/// Stores the setup pose and all of the stateless data for a skeleton. +class SP_API SkeletonData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class Skeleton; + +public: + SkeletonData(); + + ~SkeletonData(); + + /// Finds a bone by comparing each bone's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + BoneData *findBone(const String &boneName); + + /// @return -1 if the bone was not found. + int findBoneIndex(const String &boneName); + + /// @return May be NULL. + SlotData *findSlot(const String &slotName); + + /// @return -1 if the slot was not found. + int findSlotIndex(const String &slotName); + + /// @return May be NULL. + Skin *findSkin(const String &skinName); + + /// @return May be NULL. + spine::EventData *findEvent(const String &eventDataName); + + /// @return May be NULL. + Animation *findAnimation(const String &animationName); + + /// @return May be NULL. + IkConstraintData *findIkConstraint(const String &constraintName); + + /// @return May be NULL. + TransformConstraintData *findTransformConstraint(const String &constraintName); + + /// @return May be NULL. + PathConstraintData *findPathConstraint(const String &constraintName); + + /// @return -1 if the path constraint was not found. + int findPathConstraintIndex(const String &pathConstraintName); + + const String &getName(); + + void setName(const String &inValue); + + /// The skeleton's bones, sorted parent first. The root bone is always the first bone. + Vector &getBones(); + + Vector &getSlots(); + + /// All skins, including the default skin. + Vector &getSkins(); + + /// The skeleton's default skin. + /// By default this skin contains all attachments that were not in a skin in Spine. + /// @return May be NULL. + Skin *getDefaultSkin(); + + void setDefaultSkin(Skin *inValue); + + Vector &getEvents(); + + Vector &getAnimations(); + + Vector &getIkConstraints(); + + Vector &getTransformConstraints(); + + Vector &getPathConstraints(); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getWidth(); + + void setWidth(float inValue); + + float getHeight(); + + void setHeight(float inValue); + + /// The Spine version used to export this data, or NULL. + const String &getVersion(); + + void setVersion(const String &inValue); + + const String &getHash(); + + void setHash(const String &inValue); + + const String &getImagesPath(); + + void setImagesPath(const String &inValue); + + const String &getAudioPath(); + + void setAudioPath(const String &inValue); + + /// The dopesheet FPS in Spine. Available only when nonessential data was exported. + float getFps(); + + void setFps(float inValue); + +private: + String _name; + Vector _bones; // Ordered parents first + Vector _slots; // Setup pose draw order. + Vector _skins; + Skin *_defaultSkin; + Vector _events; + Vector _animations; + Vector _ikConstraints; + Vector _transformConstraints; + Vector _pathConstraints; + float _x, _y, _width, _height; + String _version; + String _hash; + Vector _strings; + + // Nonessential. + float _fps; + String _imagesPath; + String _audioPath; +}; +} + +#endif /* Spine_SkeletonData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonJson.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonJson.h new file mode 100644 index 0000000..aeb60f5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SkeletonJson.h @@ -0,0 +1,91 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonJson_h +#define Spine_SkeletonJson_h + +#include +#include +#include + +namespace spine { +class CurveTimeline; + +class VertexAttachment; + +class Animation; + +class Json; + +class SkeletonData; + +class Atlas; + +class AttachmentLoader; + +class LinkedMesh; + +class String; + +class SP_API SkeletonJson : public SpineObject { +public: + explicit SkeletonJson(Atlas *atlas); + + explicit SkeletonJson(AttachmentLoader *attachmentLoader, bool ownsLoader = false); + + ~SkeletonJson(); + + SkeletonData *readSkeletonDataFile(const String &path); + + SkeletonData *readSkeletonData(const char *json); + + void setScale(float scale) { _scale = scale; } + + String &getError() { return _error; } + +private: + AttachmentLoader *_attachmentLoader; + Vector _linkedMeshes; + float _scale; + const bool _ownsLoader; + String _error; + + static float toColor(const char *value, size_t index); + + static void readCurve(Json *frame, CurveTimeline *timeline, size_t frameIndex); + + Animation *readAnimation(Json *root, SkeletonData *skeletonData); + + void readVertices(Json *attachmentMap, VertexAttachment *attachment, size_t verticesLength); + + void setError(Json *root, const String &value1, const String &value2); +}; +} + +#endif /* Spine_SkeletonJson_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Skin.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Skin.h new file mode 100644 index 0000000..18dadba --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Skin.h @@ -0,0 +1,164 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Skin_h +#define Spine_Skin_h + +#include +#include + +namespace spine { +class Attachment; + +class Skeleton; +class BoneData; +class ConstraintData; + +/// Stores attachments by slot index and attachment name. +/// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and +/// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide. +class SP_API Skin : public SpineObject { + friend class Skeleton; + +public: + class SP_API AttachmentMap : public SpineObject { + friend class Skin; + + public: + struct SP_API Entry { + size_t _slotIndex; + String _name; + Attachment *_attachment; + + Entry(size_t slotIndex, const String &name, Attachment *attachment) : + _slotIndex(slotIndex), + _name(name), + _attachment(attachment) { + } + }; + + class SP_API Entries { + friend class AttachmentMap; + + public: + bool hasNext() { + while(true) { + if (_slotIndex >= _buckets.size()) return false; + if (_bucketIndex >= _buckets[_slotIndex].size()) { + _bucketIndex = 0; + ++_slotIndex; + continue; + }; + return true; + } + } + + Entry &next() { + Entry &result = _buckets[_slotIndex][_bucketIndex]; + ++_bucketIndex; + return result; + } + + protected: + Entries(Vector< Vector > &buckets) : _buckets(buckets), _slotIndex(0), _bucketIndex(0) { + } + + private: + Vector< Vector > &_buckets; + size_t _slotIndex; + size_t _bucketIndex; + }; + + void put(size_t slotIndex, const String &attachmentName, Attachment *attachment); + + Attachment *get(size_t slotIndex, const String &attachmentName); + + void remove(size_t slotIndex, const String &attachmentName); + + Entries getEntries(); + + protected: + AttachmentMap(); + + private: + + int findInBucket(Vector &, const String &attachmentName); + + Vector > _buckets; + }; + + explicit Skin(const String &name); + + ~Skin(); + + /// Adds an attachment to the skin for the specified slot index and name. + /// If the name already exists for the slot, the previous value is replaced. + void setAttachment(size_t slotIndex, const String &name, Attachment *attachment); + + /// Returns the attachment for the specified slot index and name, or NULL. + Attachment *getAttachment(size_t slotIndex, const String &name); + + // Removes the attachment from the skin. + void removeAttachment(size_t slotIndex, const String& name); + + /// Finds the skin keys for a given slot. The results are added to the passed array of names. + /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex + /// @param names Found skin key names will be added to this array. + void findNamesForSlot(size_t slotIndex, Vector &names); + + /// Finds the attachments for a given slot. The results are added to the passed array of Attachments. + /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex + /// @param attachments Found Attachments will be added to this array. + void findAttachmentsForSlot(size_t slotIndex, Vector &attachments); + + const String &getName(); + + /// Adds all attachments, bones, and constraints from the specified skin to this skin. + void addSkin(Skin* other); + + /// Adds all attachments, bones, and constraints from the specified skin to this skin. Attachments are deep copied. + void copySkin(Skin* other); + + AttachmentMap::Entries getAttachments(); + + Vector& getBones(); + + Vector& getConstraints(); +private: + const String _name; + AttachmentMap _attachments; + Vector _bones; + Vector _constraints; + + /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. + void attachAll(Skeleton &skeleton, Skin &oldSkin); +}; +} + +#endif /* Spine_Skin_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Slot.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Slot.h new file mode 100644 index 0000000..f75fbbf --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Slot.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Slot_h +#define Spine_Slot_h + +#include +#include +#include + +namespace spine { +class SlotData; + +class Bone; + +class Skeleton; + +class Attachment; + +class SP_API Slot : public SpineObject { + friend class VertexAttachment; + + friend class Skeleton; + + friend class SkeletonBounds; + + friend class SkeletonClipping; + + friend class AttachmentTimeline; + + friend class ColorTimeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TwoColorTimeline; + +public: + Slot(SlotData &data, Bone &bone); + + void setToSetupPose(); + + SlotData &getData(); + + Bone &getBone(); + + Skeleton &getSkeleton(); + + Color &getColor(); + + Color &getDarkColor(); + + bool hasDarkColor(); + + /// May be NULL. + Attachment *getAttachment(); + + void setAttachment(Attachment *inValue); + + int getAttachmentState(); + + void setAttachmentState(int state); + + float getAttachmentTime(); + + void setAttachmentTime(float inValue); + + Vector &getDeform(); + +private: + SlotData &_data; + Bone &_bone; + Skeleton &_skeleton; + Color _color; + Color _darkColor; + bool _hasDarkColor; + Attachment *_attachment; + int _attachmentState; + float _attachmentTime; + Vector _deform; +}; +} + +#endif /* Spine_Slot_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SlotData.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SlotData.h new file mode 100644 index 0000000..24919be --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SlotData_h +#define Spine_SlotData_h + +#include +#include +#include +#include + +namespace spine { +class BoneData; + +class SP_API SlotData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AttachmentTimeline; + + friend class ColorTimeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TwoColorTimeline; + +public: + SlotData(int index, const String &name, BoneData &boneData); + + int getIndex(); + + const String &getName(); + + BoneData &getBoneData(); + + Color &getColor(); + + Color &getDarkColor(); + + bool hasDarkColor(); + + void setHasDarkColor(bool inValue); + + /// May be empty. + const String &getAttachmentName(); + + void setAttachmentName(const String &inValue); + + BlendMode getBlendMode(); + + void setBlendMode(BlendMode inValue); + +private: + const int _index; + String _name; + BoneData &_boneData; + Color _color; + Color _darkColor; + + bool _hasDarkColor; + String _attachmentName; + BlendMode _blendMode; +}; +} + +#endif /* Spine_SlotData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SpacingMode.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SpacingMode.h new file mode 100644 index 0000000..c76d6db --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SpacingMode.h @@ -0,0 +1,41 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SpacingMode_h +#define Spine_SpacingMode_h + +namespace spine { +enum SpacingMode { + SpacingMode_Length = 0, + SpacingMode_Fixed, + SpacingMode_Percent +}; +} + +#endif /* Spine_SpacingMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SpineObject.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SpineObject.h new file mode 100644 index 0000000..896a8ae --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SpineObject.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Object_h +#define Spine_Object_h + +#include +#include + +#include + +namespace spine { +class String; + +class SP_API SpineObject { +public: + void *operator new(size_t sz); + + void *operator new(size_t sz, const char *file, int line); + + void *operator new(size_t sz, void *ptr); + + void operator delete(void *p, const char *file, int line); + + void operator delete(void *p, void *mem); + + void operator delete(void *p); + + virtual ~SpineObject(); +}; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SpineString.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SpineString.h new file mode 100644 index 0000000..06479fc --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/SpineString.h @@ -0,0 +1,212 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_STRING_H +#define SPINE_STRING_H + +#include +#include + +#include +#include + +// Required for sprintf on MSVC +#ifdef _MSC_VER +#pragma warning(disable:4996) +#endif + +namespace spine { +class SP_API String : public SpineObject { +public: + String() : _length(0), _buffer(NULL) { + } + + String(const char *chars, bool own = false) { + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + if (!own) { + _buffer = SpineExtension::calloc(_length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, chars, _length + 1); + } else { + _buffer = (char *) chars; + } + } + } + + String(const String &other) { + if (!other._buffer) { + _length = 0; + _buffer = NULL; + } else { + _length = other._length; + _buffer = SpineExtension::calloc(other._length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, other._buffer, other._length + 1); + } + } + + size_t length() const { + return _length; + } + + bool isEmpty() const { + return _length == 0; + } + + const char *buffer() const { + return _buffer; + } + + void own(const String &other) { + if (this == &other) return; + if (_buffer) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + _length = other._length; + _buffer = other._buffer; + other._length = 0; + other._buffer = NULL; + } + + void own(const char *chars) { + if (_buffer == chars) return; + if (_buffer) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + _buffer = (char *) chars; + } + } + + void unown() { + _length = 0; + _buffer = NULL; + } + + String &operator=(const String &other) { + if (this == &other) return *this; + if (_buffer) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + if (!other._buffer) { + _length = 0; + _buffer = NULL; + } else { + _length = other._length; + _buffer = SpineExtension::calloc(other._length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, other._buffer, other._length + 1); + } + return *this; + } + + String &operator=(const char *chars) { + if (_buffer == chars) return *this; + if (_buffer) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + _buffer = SpineExtension::calloc(_length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, chars, _length + 1); + } + return *this; + } + + String &append(const char *chars) { + size_t len = strlen(chars); + size_t thisLen = _length; + _length = _length + len; + bool same = chars == _buffer; + _buffer = SpineExtension::realloc(_buffer, _length + 1, __FILE__, __LINE__); + memcpy((void *) (_buffer + thisLen), (void *) (same ? _buffer : chars), len + 1); + return *this; + } + + String &append(const String &other) { + size_t len = other.length(); + size_t thisLen = _length; + _length = _length + len; + bool same = other._buffer == _buffer; + _buffer = SpineExtension::realloc(_buffer, _length + 1, __FILE__, __LINE__); + memcpy((void *) (_buffer + thisLen), (void *) (same ? _buffer : other._buffer), len + 1); + return *this; + } + + String &append(int other) { + char str[100]; + sprintf(str, "%i", other); + append(str); + return *this; + } + + String &append(float other) { + char str[100]; + sprintf(str, "%f", other); + append(str); + return *this; + } + + friend bool operator==(const String &a, const String &b) { + if (a._buffer == b._buffer) return true; + if (a._length != b._length) return false; + if (a._buffer && b._buffer) { + return strcmp(a._buffer, b._buffer) == 0; + } else { + return false; + } + } + + friend bool operator!=(const String &a, const String &b) { + return !(a == b); + } + + ~String() { + if (_buffer) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + } + +private: + mutable size_t _length; + mutable char *_buffer; +}; +} + + +#endif //SPINE_STRING_H diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TextureLoader.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TextureLoader.h new file mode 100644 index 0000000..fa305a3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TextureLoader.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TextureLoader_h +#define Spine_TextureLoader_h + +#include +#include + +namespace spine { + class AtlasPage; + + class SP_API TextureLoader : public SpineObject { + public: + TextureLoader(); + + virtual ~TextureLoader(); + + virtual void load(AtlasPage& page, const String& path) = 0; + + virtual void unload(void* texture) = 0; + }; +} + +#endif /* Spine_TextureLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Timeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Timeline.h new file mode 100644 index 0000000..cc98353 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Timeline_h +#define Spine_Timeline_h + +#include +#include +#include +#include +#include + +namespace spine { +class Skeleton; + +class Event; + +class SP_API Timeline : public SpineObject { +RTTI_DECL + +public: + Timeline(); + + virtual ~Timeline(); + + /// Sets the value(s) for the specified time. + /// @param skeleton The skeleton the timeline is being applied to. This provides access to the bones, slots, and other skeleton components the timeline may change. + /// @param lastTime lastTime The time this timeline was last applied. Timelines such as EventTimeline trigger only at specific times rather than every frame. In that case, the timeline triggers everything between lastTime (exclusive) and time (inclusive). + /// @param time The time within the animation. Most timelines find the key before and the key after this time so they can interpolate between the keys. + /// @param pEvents If any events are fired, they are added to this array. Can be NULL to ignore firing events or if the timeline does not fire events. May be NULL. + /// @param alpha alpha 0 applies the current or setup pose value (depending on pose parameter). 1 applies the timeline + /// value. Between 0 and 1 applies a value between the current or setup pose and the timeline value. By adjusting alpha over + /// time, an animation can be mixed in or out. alpha can also be useful to apply animations on top of each other (layered). + /// @param blend Controls how mixing is applied when alpha is than 1. + /// @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions such as DrawOrderTimeline and AttachmentTimeline. + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction) = 0; + + virtual int getPropertyId() = 0; +}; +} + +#endif /* Spine_Timeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TimelineType.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TimelineType.h new file mode 100644 index 0000000..b1f0781 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TimelineType.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TimelineType_h +#define Spine_TimelineType_h + +namespace spine { +enum TimelineType { + TimelineType_Rotate = 0, + TimelineType_Translate, + TimelineType_Scale, + TimelineType_Shear, + TimelineType_Attachment, + TimelineType_Color, + TimelineType_Deform, + TimelineType_Event, + TimelineType_DrawOrder, + TimelineType_IkConstraint, + TimelineType_TransformConstraint, + TimelineType_PathConstraintPosition, + TimelineType_PathConstraintSpacing, + TimelineType_PathConstraintMix, + TimelineType_TwoColor +}; +} + +#endif /* Spine_TimelineType_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TransformConstraint.h new file mode 100644 index 0000000..e271e5c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraint_h +#define Spine_TransformConstraint_h + +#include + +#include + +namespace spine { + class TransformConstraintData; + class Skeleton; + class Bone; + + class SP_API TransformConstraint : public Updatable { + friend class Skeleton; + friend class TransformConstraintTimeline; + + RTTI_DECL + + public: + TransformConstraint(TransformConstraintData& data, Skeleton& skeleton); + + void apply(); + + virtual void update(); + + virtual int getOrder(); + + TransformConstraintData& getData(); + + Vector& getBones(); + + Bone* getTarget(); + void setTarget(Bone* inValue); + + float getRotateMix(); + void setRotateMix(float inValue); + + float getTranslateMix(); + void setTranslateMix(float inValue); + + float getScaleMix(); + void setScaleMix(float inValue); + + float getShearMix(); + void setShearMix(float inValue); + + bool isActive(); + + void setActive(bool inValue); + + private: + TransformConstraintData& _data; + Vector _bones; + Bone* _target; + float _rotateMix, _translateMix, _scaleMix, _shearMix; + bool _active; + + void applyAbsoluteWorld(); + + void applyRelativeWorld(); + + void applyAbsoluteLocal(); + + void applyRelativeLocal(); + }; +} + +#endif /* Spine_TransformConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h new file mode 100644 index 0000000..783eaac --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -0,0 +1,78 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraintData_h +#define Spine_TransformConstraintData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SP_API TransformConstraintData : public ConstraintData { + friend class SkeletonBinary; + friend class SkeletonJson; + + friend class TransformConstraint; + friend class Skeleton; + friend class TransformConstraintTimeline; + + public: + explicit TransformConstraintData(const String& name); + + Vector& getBones(); + BoneData* getTarget(); + float getRotateMix(); + float getTranslateMix(); + float getScaleMix(); + float getShearMix(); + + float getOffsetRotation(); + float getOffsetX(); + float getOffsetY(); + float getOffsetScaleX(); + float getOffsetScaleY(); + float getOffsetShearY(); + + bool isRelative(); + bool isLocal(); + + private: + Vector _bones; + BoneData* _target; + float _rotateMix, _translateMix, _scaleMix, _shearMix; + float _offsetRotation, _offsetX, _offsetY, _offsetScaleX, _offsetScaleY, _offsetShearY; + bool _relative, _local; + }; +} + +#endif /* Spine_TransformConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h new file mode 100644 index 0000000..3173238 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraintTimeline_h +#define Spine_TransformConstraintTimeline_h + +#include + +namespace spine { + + class SP_API TransformConstraintTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + static const int ENTRIES; + + explicit TransformConstraintTimeline(int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + + void setFrame(size_t frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix); + + private: + static const int PREV_TIME; + static const int PREV_ROTATE; + static const int PREV_TRANSLATE; + static const int PREV_SCALE; + static const int PREV_SHEAR; + static const int ROTATE; + static const int TRANSLATE; + static const int SCALE; + static const int SHEAR; + + Vector _frames; + int _transformConstraintIndex; + }; +} + +#endif /* Spine_TransformConstraintTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TransformMode.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TransformMode.h new file mode 100644 index 0000000..c4da701 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TransformMode.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformMode_h +#define Spine_TransformMode_h + +namespace spine { + enum TransformMode { + TransformMode_Normal = 0, + TransformMode_OnlyTranslation, + TransformMode_NoRotationOrReflection, + TransformMode_NoScale, + TransformMode_NoScaleOrReflection + }; +} + +#endif /* Spine_TransformMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h new file mode 100644 index 0000000..88f1dfb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TranslateTimeline_h +#define Spine_TranslateTimeline_h + +#include + +#include +#include + +namespace spine { + + class SP_API TranslateTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + static const int ENTRIES; + + explicit TranslateTimeline(int frameCount); + + virtual ~TranslateTimeline(); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, float x, float y); + + protected: + static const int PREV_TIME; + static const int PREV_X; + static const int PREV_Y; + static const int X; + static const int Y; + + Vector _frames; + int _boneIndex; + }; +} + +#endif /* Spine_TranslateTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Triangulator.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Triangulator.h new file mode 100644 index 0000000..6a6d881 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Triangulator.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Triangulator_h +#define Spine_Triangulator_h + +#include +#include + +namespace spine { +class SP_API Triangulator : public SpineObject { +public: + ~Triangulator(); + + Vector &triangulate(Vector &vertices); + + Vector< Vector* > &decompose(Vector &vertices, Vector &triangles); + +private: + Vector* > _convexPolygons; + Vector* > _convexPolygonsIndices; + + Vector _indices; + Vector _isConcaveArray; + Vector _triangles; + + Pool > _polygonPool; + Pool > _polygonIndicesPool; + + static bool isConcave(int index, int vertexCount, Vector &vertices, Vector &indices); + + static bool positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y); + + static int winding(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y); +}; +} + +#endif /* Spine_Triangulator_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h new file mode 100644 index 0000000..6cc1104 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -0,0 +1,80 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TwoColorTimeline_h +#define Spine_TwoColorTimeline_h + +#include + +namespace spine { + + class SP_API TwoColorTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + static const int ENTRIES; + + explicit TwoColorTimeline(int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixBlend blend, MixDirection direction); + + virtual int getPropertyId(); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2); + + int getSlotIndex(); + void setSlotIndex(int inValue); + + private: + static const int PREV_TIME; + static const int PREV_R; + static const int PREV_G; + static const int PREV_B; + static const int PREV_A; + static const int PREV_R2; + static const int PREV_G2; + static const int PREV_B2; + static const int R; + static const int G; + static const int B; + static const int A; + static const int R2; + static const int G2; + static const int B2; + + Vector _frames; // time, r, g, b, a, r2, g2, b2, ... + int _slotIndex; + }; +} + +#endif /* Spine_TwoColorTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Updatable.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Updatable.h new file mode 100644 index 0000000..51f8cec --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Updatable.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Updatable_h +#define Spine_Updatable_h + +#include +#include + +namespace spine { +class SP_API Updatable : public SpineObject { +RTTI_DECL + +public: + Updatable(); + + virtual ~Updatable(); + + virtual void update() = 0; + + virtual bool isActive() = 0; + + virtual void setActive(bool inValue) = 0; +}; +} + +#endif /* Spine_Updatable_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Vector.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Vector.h new file mode 100644 index 0000000..4d26372 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Vector.h @@ -0,0 +1,222 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Vector_h +#define Spine_Vector_h + +#include +#include +#include +#include + +namespace spine { +template +class SP_API Vector : public SpineObject { +public: + Vector() : _size(0), _capacity(0), _buffer(NULL) { + } + + Vector(const Vector &inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL) { + if (_capacity > 0) { + _buffer = allocate(_capacity); + for (size_t i = 0; i < _size; ++i) { + construct(_buffer + i, inVector._buffer[i]); + } + } + } + + ~Vector() { + clear(); + deallocate(_buffer); + } + + inline void clear() { + for (size_t i = 0; i < _size; ++i) { + destroy(_buffer + (_size - 1 - i)); + } + + _size = 0; + } + + inline size_t getCapacity() const { + return _capacity; + } + + inline size_t size() const { + return _size; + } + + inline void setSize(size_t newSize, const T &defaultValue) { + assert(newSize >= 0); + size_t oldSize = _size; + _size = newSize; + if (_capacity < newSize) { + _capacity = (int) (_size * 1.75f); + if (_capacity < 8) _capacity = 8; + _buffer = spine::SpineExtension::realloc(_buffer, _capacity, __FILE__, __LINE__); + } + if (oldSize < _size) { + for (size_t i = oldSize; i < _size; i++) { + construct(_buffer + i, defaultValue); + } + } + } + + inline void ensureCapacity(size_t newCapacity = 0) { + if (_capacity >= newCapacity) return; + _capacity = newCapacity; + _buffer = SpineExtension::realloc(_buffer, newCapacity, __FILE__, __LINE__); + } + + inline void add(const T &inValue) { + if (_size == _capacity) { + // inValue might reference an element in this buffer + // When we reallocate, the reference becomes invalid. + // We thus need to create a defensive copy before + // reallocating. + T valueCopy = inValue; + _capacity = (int) (_size * 1.75f); + if (_capacity < 8) _capacity = 8; + _buffer = spine::SpineExtension::realloc(_buffer, _capacity, __FILE__, __LINE__); + construct(_buffer + _size++, valueCopy); + } else { + construct(_buffer + _size++, inValue); + } + } + + inline void addAll(Vector &inValue) { + ensureCapacity(this->size() + inValue.size()); + for (size_t i = 0; i < inValue.size(); i++) { + add(inValue[i]); + } + } + + inline void clearAndAddAll(Vector &inValue) { + this->clear(); + this->addAll(inValue); + } + + inline void removeAt(size_t inIndex) { + assert(inIndex < _size); + + --_size; + + if (inIndex != _size) { + for (size_t i = inIndex; i < _size; ++i) { + T tmp(_buffer[i]); + _buffer[i] = _buffer[i + 1]; + _buffer[i + 1] = tmp; + } + } + + destroy(_buffer + _size); + } + + inline bool contains(const T &inValue) { + for (size_t i = 0; i < _size; ++i) { + if (_buffer[i] == inValue) { + return true; + } + } + + return false; + } + + inline int indexOf(const T &inValue) { + for (size_t i = 0; i < _size; ++i) { + if (_buffer[i] == inValue) { + return (int)i; + } + } + + return -1; + } + + inline T &operator[](size_t inIndex) { + assert(inIndex < _size); + + return _buffer[inIndex]; + } + + inline friend bool operator==(Vector &lhs, Vector &rhs) { + if (lhs.size() != rhs.size()) { + return false; + } + + for (size_t i = 0, n = lhs.size(); i < n; ++i) { + if (lhs[i] != rhs[i]) { + return false; + } + } + + return true; + } + + inline friend bool operator!=(Vector &lhs, Vector &rhs) { + return !(lhs == rhs); + } + + inline T *buffer() { + return _buffer; + } + +private: + size_t _size; + size_t _capacity; + T *_buffer; + + inline T *allocate(size_t n) { + assert(n > 0); + + T *ptr = SpineExtension::calloc(n, __FILE__, __LINE__); + + assert(ptr); + + return ptr; + } + + inline void deallocate(T *buffer) { + if (_buffer) { + SpineExtension::free(buffer, __FILE__, __LINE__); + } + } + + inline void construct(T *buffer, const T &val) { + new(buffer) T(val); + } + + inline void destroy(T *buffer) { + buffer->~T(); + } + + // Vector &operator=(const Vector &inVector) {}; +}; +} + +#endif /* Spine_Vector_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/VertexAttachment.h new file mode 100644 index 0000000..5cf8f00 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -0,0 +1,93 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_VertexAttachment_h +#define Spine_VertexAttachment_h + +#include + +#include + +namespace spine { + class Slot; + + /// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices. + class SP_API VertexAttachment : public Attachment { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class DeformTimeline; + + RTTI_DECL + + public: + explicit VertexAttachment(const String& name); + + virtual ~VertexAttachment(); + + void computeWorldVertices(Slot& slot, float* worldVertices); + void computeWorldVertices(Slot& slot, Vector& worldVertices); + + /// Transforms local vertices to world coordinates. + /// @param start The index of the first Vertices value to transform. Each vertex has 2 values, x and y. + /// @param count The number of world vertex values to output. Must be less than or equal to WorldVerticesLength - start. + /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + count. + /// @param offset The worldVertices index to begin writing values. + /// @param stride The number of worldVertices entries between the value pairs written. + void computeWorldVertices(Slot& slot, size_t start, size_t count, float* worldVertices, size_t offset, size_t stride = 2); + void computeWorldVertices(Slot& slot, size_t start, size_t count, Vector& worldVertices, size_t offset, size_t stride = 2); + + /// Gets a unique ID for this attachment. + int getId(); + + Vector& getBones(); + + Vector& getVertices(); + + size_t getWorldVerticesLength(); + void setWorldVerticesLength(size_t inValue); + + VertexAttachment* getDeformAttachment(); + void setDeformAttachment(VertexAttachment* attachment); + + void copyTo(VertexAttachment* other); + + protected: + Vector _bones; + Vector _vertices; + size_t _worldVerticesLength; + VertexAttachment* _deformAttachment; + + private: + const int _id; + + static int getNextID(); + }; +} + +#endif /* Spine_VertexAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/VertexEffect.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/VertexEffect.h new file mode 100644 index 0000000..dbe7ae5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/VertexEffect.h @@ -0,0 +1,105 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_VertexEffect_h +#define Spine_VertexEffect_h + +#include +#include + +namespace spine { + +class Skeleton; +class Color; + +class SP_API VertexEffect: public SpineObject { +public: + virtual void begin(Skeleton& skeleton) = 0; + virtual void transform(float& x, float& y, float &u, float &v, Color &light, Color &dark) = 0; + virtual void end() = 0; +}; + +class SP_API JitterVertexEffect: public VertexEffect { +public: + JitterVertexEffect(float jitterX, float jitterY); + + void begin(Skeleton& skeleton); + void transform(float& x, float& y, float &u, float &v, Color &light, Color &dark); + void end(); + + void setJitterX(float jitterX); + float getJitterX(); + + void setJitterY(float jitterY); + float getJitterY(); + +protected: + float _jitterX; + float _jitterY; +}; + +class SP_API SwirlVertexEffect: public VertexEffect { +public: + SwirlVertexEffect(float radius, Interpolation &interpolation); + + void begin(Skeleton& skeleton); + void transform(float& x, float& y, float &u, float &v, Color &light, Color &dark); + void end(); + + void setCenterX(float centerX); + float getCenterX(); + + void setCenterY(float centerY); + float getCenterY(); + + void setRadius(float radius); + float getRadius(); + + void setAngle(float angle); + float getAngle(); + + void setWorldX(float worldX); + float getWorldX(); + + void setWorldY(float worldY); + float getWorldY(); + +protected: + float _centerX; + float _centerY; + float _radius; + float _angle; + float _worldX; + float _worldY; + + Interpolation& _interpolation; +}; +} + +#endif /* Spine_VertexEffect_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Vertices.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Vertices.h new file mode 100644 index 0000000..fa2b0f5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/Vertices.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Vertices_h +#define Spine_Vertices_h + +#include + +namespace spine { +class SP_API Vertices : public SpineObject { +public: + Vector _bones; + Vector _vertices; +}; +} + +#endif /* Spine_Vertices_h */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/dll.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/dll.h new file mode 100644 index 0000000..2fe0160 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/dll.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SHAREDLIB_H +#define SPINE_SHAREDLIB_H + +#ifdef _WIN32 +#define DLLIMPORT __declspec(dllimport) +#define DLLEXPORT __declspec(dllexport) +#else +#ifndef DLLIMPORT +#define DLLIMPORT +#endif +#ifndef DLLEXPORT +#define DLLEXPORT +#endif +#endif + +#ifdef SPINEPLUGIN_API +#define SP_API SPINEPLUGIN_API +#else +#define SP_API +#endif + +#endif /* SPINE_SHAREDLIB_H */ diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/spine.h b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/spine.h new file mode 100644 index 0000000..39d989b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/include/spine/spine.h @@ -0,0 +1,112 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SPINE_H_ +#define SPINE_SPINE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Animation.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Animation.cpp new file mode 100644 index 0000000..bc4156c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Animation.cpp @@ -0,0 +1,142 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include +#include + +#include + +#include + +using namespace spine; + +Animation::Animation(const String &name, Vector &timelines, float duration) : + _timelines(timelines), + _timelineIds(), + _duration(duration), + _name(name) { + assert(_name.length() > 0); + for (int i = 0; i < (int)timelines.size(); i++) + _timelineIds.put(timelines[i]->getPropertyId(), true); +} + +bool Animation::hasTimeline(int id) { + return _timelineIds.containsKey(id); +} + +Animation::~Animation() { + ContainerUtil::cleanUpVectorOfPointers(_timelines); +} + +void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction +) { + if (loop && _duration != 0) { + time = MathUtil::fmod(time, _duration); + if (lastTime > 0) { + lastTime = MathUtil::fmod(lastTime, _duration); + } + } + + for (size_t i = 0, n = _timelines.size(); i < n; ++i) { + _timelines[i]->apply(skeleton, lastTime, time, pEvents, alpha, blend, direction); + } +} + +const String &Animation::getName() { + return _name; +} + +Vector &Animation::getTimelines() { + return _timelines; +} + +float Animation::getDuration() { + return _duration; +} + +void Animation::setDuration(float inValue) { + _duration = inValue; +} + +int Animation::binarySearch(Vector &values, float target, int step) { + int low = 0; + int size = (int)values.size(); + int high = size / step - 2; + if (high == 0) { + return step; + } + + int current = (int) (static_cast(high) >> 1); + while (true) { + if (values[(current + 1) * step] <= target) + low = current + 1; + else + high = current; + + if (low == high) return (low + 1) * step; + + current = (int) (static_cast(low + high) >> 1); + } +} + +int Animation::binarySearch(Vector &values, float target) { + int low = 0; + int size = (int)values.size(); + int high = size - 2; + if (high == 0) return 1; + + int current = (int) (static_cast(high) >> 1); + while (true) { + if (values[(current + 1)] <= target) + low = current + 1; + else + high = current; + + if (low == high) return (low + 1); + + current = (int) (static_cast(low + high) >> 1); + } +} + +int Animation::linearSearch(Vector &values, float target, int step) { + for (int i = 0, last = (int)values.size() - step; i <= last; i += step) { + if (values[i] > target) { + return i; + } + } + + return -1; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AnimationState.cpp new file mode 100644 index 0000000..6185b88 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -0,0 +1,1046 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +void dummyOnAnimationEventFunc(AnimationState *state, spine::EventType type, TrackEntry *entry, Event *event = NULL) { + SP_UNUSED(state); + SP_UNUSED(type); + SP_UNUSED(entry); + SP_UNUSED(event); +} + +TrackEntry::TrackEntry() : _animation(NULL), _next(NULL), _mixingFrom(NULL), _mixingTo(0), _trackIndex(0), _loop(false), _holdPrevious(false), + _eventThreshold(0), _attachmentThreshold(0), _drawOrderThreshold(0), _animationStart(0), + _animationEnd(0), _animationLast(0), _nextAnimationLast(0), _delay(0), _trackTime(0), + _trackLast(0), _nextTrackLast(0), _trackEnd(0), _timeScale(1.0f), _alpha(0), _mixTime(0), + _mixDuration(0), _interruptAlpha(0), _totalAlpha(0), _mixBlend(MixBlend_Replace), + _listener(dummyOnAnimationEventFunc), _listenerObject(NULL) { +} + +TrackEntry::~TrackEntry() { } + +int TrackEntry::getTrackIndex() { return _trackIndex; } + +Animation *TrackEntry::getAnimation() { return _animation; } + +bool TrackEntry::getLoop() { return _loop; } + +void TrackEntry::setLoop(bool inValue) { _loop = inValue; } + +bool TrackEntry::getHoldPrevious() { return _holdPrevious; } + +void TrackEntry::setHoldPrevious(bool inValue) { _holdPrevious = inValue; } + +float TrackEntry::getDelay() { return _delay; } + +void TrackEntry::setDelay(float inValue) { _delay = inValue; } + +float TrackEntry::getTrackTime() { return _trackTime; } + +void TrackEntry::setTrackTime(float inValue) { _trackTime = inValue; } + +float TrackEntry::getTrackEnd() { return _trackEnd; } + +void TrackEntry::setTrackEnd(float inValue) { _trackEnd = inValue; } + +float TrackEntry::getAnimationStart() { return _animationStart; } + +void TrackEntry::setAnimationStart(float inValue) { _animationStart = inValue; } + +float TrackEntry::getAnimationEnd() { return _animationEnd; } + +void TrackEntry::setAnimationEnd(float inValue) { _animationEnd = inValue; } + +float TrackEntry::getAnimationLast() { return _animationLast; } + +void TrackEntry::setAnimationLast(float inValue) { + _animationLast = inValue; + _nextAnimationLast = inValue; +} + +float TrackEntry::getAnimationTime() { + if (_loop) { + float duration = _animationEnd - _animationStart; + if (duration == 0) return _animationStart; + return MathUtil::fmod(_trackTime, duration) + _animationStart; + } + + return MathUtil::min(_trackTime + _animationStart, _animationEnd); +} + +float TrackEntry::getTimeScale() { return _timeScale; } + +void TrackEntry::setTimeScale(float inValue) { _timeScale = inValue; } + +float TrackEntry::getAlpha() { return _alpha; } + +void TrackEntry::setAlpha(float inValue) { _alpha = inValue; } + +float TrackEntry::getEventThreshold() { return _eventThreshold; } + +void TrackEntry::setEventThreshold(float inValue) { _eventThreshold = inValue; } + +float TrackEntry::getAttachmentThreshold() { return _attachmentThreshold; } + +void TrackEntry::setAttachmentThreshold(float inValue) { _attachmentThreshold = inValue; } + +float TrackEntry::getDrawOrderThreshold() { return _drawOrderThreshold; } + +void TrackEntry::setDrawOrderThreshold(float inValue) { _drawOrderThreshold = inValue; } + +TrackEntry *TrackEntry::getNext() { return _next; } + +bool TrackEntry::isComplete() { + return _trackTime >= _animationEnd - _animationStart; +} + +float TrackEntry::getMixTime() { return _mixTime; } + +void TrackEntry::setMixTime(float inValue) { _mixTime = inValue; } + +float TrackEntry::getMixDuration() { return _mixDuration; } + +void TrackEntry::setMixDuration(float inValue) { _mixDuration = inValue; } + +TrackEntry *TrackEntry::getMixingFrom() { return _mixingFrom; } + +TrackEntry *TrackEntry::getMixingTo() { return _mixingTo; } + +void TrackEntry::setMixBlend(MixBlend blend) { _mixBlend = blend; } + +MixBlend TrackEntry::getMixBlend() { return _mixBlend; } + +void TrackEntry::resetRotationDirections() { + _timelinesRotation.clear(); +} + +void TrackEntry::setListener(AnimationStateListener inValue) { + _listener = inValue; + _listenerObject = NULL; +} + +void TrackEntry::setListener(AnimationStateListenerObject* inValue) { + _listener = dummyOnAnimationEventFunc; + _listenerObject = inValue; +} + +void TrackEntry::reset() { + _animation = NULL; + _next = NULL; + _mixingFrom = NULL; + _mixingTo = NULL; + + setRendererObject(NULL); + + _timelineMode.clear(); + _timelineHoldMix.clear(); + _timelinesRotation.clear(); + + _listener = dummyOnAnimationEventFunc; + _listenerObject = NULL; +} + +EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry *trackEntry, Event *event) : + _type(eventType), + _entry(trackEntry), + _event(event) { +} + +EventQueue *EventQueue::newEventQueue(AnimationState &state, Pool &trackEntryPool) { + return new(__FILE__, __LINE__) EventQueue(state, trackEntryPool); +} + +EventQueueEntry EventQueue::newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event) { + return EventQueueEntry(eventType, entry, event); +} + +EventQueue::EventQueue(AnimationState &state, Pool &trackEntryPool) : _state(state), + _trackEntryPool(trackEntryPool), + _drainDisabled(false) { +} + +EventQueue::~EventQueue() { +} + +void EventQueue::start(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Start, entry)); + _state._animationsChanged = true; +} + +void EventQueue::interrupt(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Interrupt, entry)); +} + +void EventQueue::end(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_End, entry)); + _state._animationsChanged = true; +} + +void EventQueue::dispose(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Dispose, entry)); +} + +void EventQueue::complete(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Complete, entry)); +} + +void EventQueue::event(TrackEntry *entry, Event *event) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Event, entry, event)); +} + +/// Raises all events in the queue and drains the queue. +void EventQueue::drain() { + if (_drainDisabled) { + return; + } + + _drainDisabled = true; + + AnimationState &state = _state; + + // Don't cache _eventQueueEntries.size() so callbacks can queue their own events (eg, call setAnimation in AnimationState_Complete). + for (size_t i = 0; i < _eventQueueEntries.size(); ++i) { + EventQueueEntry *queueEntry = &_eventQueueEntries[i]; + TrackEntry *trackEntry = queueEntry->_entry; + + switch (queueEntry->_type) { + case EventType_Start: + case EventType_Interrupt: + case EventType_Complete: + if (!trackEntry->_listenerObject) trackEntry->_listener(&state, queueEntry->_type, trackEntry, NULL); + else trackEntry->_listenerObject->callback(&state, queueEntry->_type, trackEntry, NULL); + if(!state._listenerObject) state._listener(&state, queueEntry->_type, trackEntry, NULL); + else state._listenerObject->callback(&state, queueEntry->_type, trackEntry, NULL); + break; + case EventType_End: + if (!trackEntry->_listenerObject) trackEntry->_listener(&state, queueEntry->_type, trackEntry, NULL); + else trackEntry->_listenerObject->callback(&state, queueEntry->_type, trackEntry, NULL); + if (!state._listenerObject) state._listener(&state, queueEntry->_type, trackEntry, NULL); + else state._listenerObject->callback(&state, queueEntry->_type, trackEntry, NULL); + /* Fall through. */ + case EventType_Dispose: + if (!trackEntry->_listenerObject) trackEntry->_listener(&state, EventType_Dispose, trackEntry, NULL); + else trackEntry->_listenerObject->callback(&state, EventType_Dispose, trackEntry, NULL); + if (!state._listenerObject) state._listener(&state, EventType_Dispose, trackEntry, NULL); + else state._listenerObject->callback(&state, EventType_Dispose, trackEntry, NULL); + + trackEntry->reset(); + _trackEntryPool.free(trackEntry); + break; + case EventType_Event: + if (!trackEntry->_listenerObject) trackEntry->_listener(&state, queueEntry->_type, trackEntry, queueEntry->_event); + else trackEntry->_listenerObject->callback(&state, queueEntry->_type, trackEntry, queueEntry->_event); + if (!state._listenerObject) state._listener(&state, queueEntry->_type, trackEntry, queueEntry->_event); + else state._listenerObject->callback(&state, queueEntry->_type, trackEntry, queueEntry->_event); + break; + } + } + _eventQueueEntries.clear(); + + _drainDisabled = false; +} + +AnimationState::AnimationState(AnimationStateData *data) : + _data(data), + _queue(EventQueue::newEventQueue(*this, _trackEntryPool)), + _animationsChanged(false), + _listener(dummyOnAnimationEventFunc), + _listenerObject(NULL), + _unkeyedState(0), + _timeScale(1) { +} + +AnimationState::~AnimationState() { + for (size_t i = 0; i < _tracks.size(); i++) { + TrackEntry* entry = _tracks[i]; + if (entry) { + TrackEntry* from = entry->_mixingFrom; + while (from) { + TrackEntry* curr = from; + from = curr->_mixingFrom; + delete curr; + } + TrackEntry* next = entry->_next; + while (next) { + TrackEntry* curr = next; + next = curr->_next; + delete curr; + } + delete entry; + } + } + delete _queue; +} + +void AnimationState::update(float delta) { + delta *= _timeScale; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *currentP = _tracks[i]; + if (currentP == NULL) { + continue; + } + + TrackEntry ¤t = *currentP; + + current._animationLast = current._nextAnimationLast; + current._trackLast = current._nextTrackLast; + + float currentDelta = delta * current._timeScale; + + if (current._delay > 0) { + current._delay -= currentDelta; + if (current._delay > 0) { + continue; + } + currentDelta = -current._delay; + current._delay = 0; + } + + TrackEntry *next = current._next; + if (next != NULL) { + // When the next entry's delay is passed, change to the next entry, preserving leftover time. + float nextTime = current._trackLast - next->_delay; + if (nextTime >= 0) { + next->_delay = 0; + next->_trackTime += current._timeScale == 0 ? 0 : (nextTime / current._timeScale + delta) * next->_timeScale; + current._trackTime += currentDelta; + setCurrent(i, next, true); + while (next->_mixingFrom != NULL) { + next->_mixTime += delta; + next = next->_mixingFrom; + } + continue; + } + } else if (current._trackLast >= current._trackEnd && current._mixingFrom == NULL) { + // clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. + _tracks[i] = NULL; + + _queue->end(currentP); + disposeNext(currentP); + continue; + } + + if (current._mixingFrom != NULL && updateMixingFrom(currentP, delta)) { + // End mixing from entries once all have completed. + TrackEntry *from = current._mixingFrom; + current._mixingFrom = NULL; + if (from != NULL) from->_mixingTo = NULL; + while (from != NULL) { + _queue->end(from); + from = from->_mixingFrom; + } + } + + current._trackTime += currentDelta; + } + + _queue->drain(); +} + +bool AnimationState::apply(Skeleton &skeleton) { + if (_animationsChanged) { + animationsChanged(); + } + + bool applied = false; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *currentP = _tracks[i]; + if (currentP == NULL || currentP->_delay > 0) { + continue; + } + + TrackEntry ¤t = *currentP; + + applied = true; + MixBlend blend = i == 0 ? MixBlend_First : current._mixBlend; + + // apply mixing from entries first. + float mix = current._alpha; + if (current._mixingFrom != NULL) { + mix *= applyMixingFrom(currentP, skeleton, blend); + } else if (current._trackTime >= current._trackEnd && current._next == NULL) { + mix = 0; // Set to setup pose the last time the entry will be applied. + } + + // apply current entry. + float animationLast = current._animationLast, animationTime = current.getAnimationTime(); + size_t timelineCount = current._animation->_timelines.size(); + Vector &timelines = current._animation->_timelines; + if ((i == 0 && mix == 1) || blend == MixBlend_Add) { + for (size_t ii = 0; ii < timelineCount; ++ii) { + Timeline *timeline = timelines[ii]; + if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) + applyAttachmentTimeline(static_cast(timeline), skeleton, animationTime, blend, true); + else + timeline->apply(skeleton, animationLast, animationTime, &_events, mix, blend, MixDirection_In); + } + } else { + Vector &timelineMode = current._timelineMode; + + bool firstFrame = current._timelinesRotation.size() == 0; + if (firstFrame) current._timelinesRotation.setSize(timelines.size() << 1, 0); + Vector &timelinesRotation = current._timelinesRotation; + + for (size_t ii = 0; ii < timelineCount; ++ii) { + Timeline *timeline = timelines[ii]; + assert(timeline); + + MixBlend timelineBlend = timelineMode[ii] == Subsequent ? blend : MixBlend_Setup; + + if (timeline->getRTTI().isExactly(RotateTimeline::rtti)) + applyRotateTimeline(static_cast(timeline), skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame); + else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) + applyAttachmentTimeline(static_cast(timeline), skeleton, animationTime, timelineBlend, true); + else + timeline->apply(skeleton, animationLast, animationTime, &_events, mix, timelineBlend, MixDirection_In); + } + } + + queueEvents(currentP, animationTime); + _events.clear(); + current._nextAnimationLast = animationTime; + current._nextTrackLast = current._trackTime; + } + + int setupState = _unkeyedState + Setup; + Vector& slots = skeleton.getSlots(); + for (int i = 0, n = slots.size(); i < n; i++) { + Slot* slot = slots[i]; + if (slot->getAttachmentState() == setupState) { + const String& attachmentName = slot->getData().getAttachmentName(); + slot->setAttachment(attachmentName.isEmpty() ? NULL : skeleton.getAttachment(slot->getData().getIndex(), attachmentName)); + } + } + _unkeyedState += 2; + + _queue->drain(); + return applied; +} + +void AnimationState::clearTracks() { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) + clearTrack(i); + _tracks.clear(); + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); +} + +void AnimationState::clearTrack(size_t trackIndex) { + if (trackIndex >= _tracks.size()) return; + + TrackEntry *current = _tracks[trackIndex]; + if (current == NULL) return; + + _queue->end(current); + + disposeNext(current); + + TrackEntry *entry = current; + while (true) { + TrackEntry *from = entry->_mixingFrom; + if (from == NULL) break; + + _queue->end(from); + entry->_mixingFrom = NULL; + entry->_mixingTo = NULL; + entry = from; + } + + _tracks[current->_trackIndex] = NULL; + + _queue->drain(); +} + +TrackEntry *AnimationState::setAnimation(size_t trackIndex, const String &animationName, bool loop) { + Animation *animation = _data->_skeletonData->findAnimation(animationName); + assert(animation != NULL); + return setAnimation(trackIndex, animation, loop); +} + +TrackEntry *AnimationState::setAnimation(size_t trackIndex, Animation *animation, bool loop) { + assert(animation != NULL); + + bool interrupt = true; + TrackEntry *current = expandToIndex(trackIndex); + if (current != NULL) { + if (current->_nextTrackLast == -1) { + // Don't mix from an entry that was never applied. + _tracks[trackIndex] = current->_mixingFrom; + _queue->interrupt(current); + _queue->end(current); + disposeNext(current); + current = current->_mixingFrom; + interrupt = false; + } else { + disposeNext(current); + } + } + + TrackEntry *entry = newTrackEntry(trackIndex, animation, loop, current); + setCurrent(trackIndex, entry, interrupt); + _queue->drain(); + + return entry; +} + +TrackEntry *AnimationState::addAnimation(size_t trackIndex, const String &animationName, bool loop, float delay) { + Animation *animation = _data->_skeletonData->findAnimation(animationName); + assert(animation != NULL); + return addAnimation(trackIndex, animation, loop, delay); +} + +TrackEntry *AnimationState::addAnimation(size_t trackIndex, Animation *animation, bool loop, float delay) { + assert(animation != NULL); + + TrackEntry *last = expandToIndex(trackIndex); + if (last != NULL) { + while (last->_next != NULL) + last = last->_next; + } + + TrackEntry *entry = newTrackEntry(trackIndex, animation, loop, last); + + if (last == NULL) { + setCurrent(trackIndex, entry, true); + _queue->drain(); + } else { + last->_next = entry; + if (delay <= 0) { + float duration = last->_animationEnd - last->_animationStart; + if (duration != 0) { + if (last->_loop) { + delay += duration * (1 + (int) (last->_trackTime / duration)); + } else { + delay += MathUtil::max(duration, last->_trackTime); + } + delay -= _data->getMix(last->_animation, animation); + } else { + delay = last->_trackTime; + } + } + } + + entry->_delay = delay; + return entry; +} + +TrackEntry *AnimationState::setEmptyAnimation(size_t trackIndex, float mixDuration) { + TrackEntry *entry = setAnimation(trackIndex, AnimationState::getEmptyAnimation(), false); + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; +} + +TrackEntry *AnimationState::addEmptyAnimation(size_t trackIndex, float mixDuration, float delay) { + if (delay <= 0) { + delay -= mixDuration; + } + + TrackEntry *entry = addAnimation(trackIndex, AnimationState::getEmptyAnimation(), false, delay); + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; +} + +void AnimationState::setEmptyAnimations(float mixDuration) { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *current = _tracks[i]; + if (current != NULL) { + setEmptyAnimation(i, mixDuration); + } + } + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); +} + +TrackEntry *AnimationState::getCurrent(size_t trackIndex) { + return trackIndex >= _tracks.size() ? NULL : _tracks[trackIndex]; +} + +AnimationStateData *AnimationState::getData() { + return _data; +} + +Vector &AnimationState::getTracks() { + return _tracks; +} + +float AnimationState::getTimeScale() { + return _timeScale; +} + +void AnimationState::setTimeScale(float inValue) { + _timeScale = inValue; +} + +void AnimationState::setListener(AnimationStateListener inValue) { + _listener = inValue; + _listenerObject = NULL; +} + +void AnimationState::setListener(AnimationStateListenerObject* inValue) { + _listener = dummyOnAnimationEventFunc; + _listenerObject = inValue; +} + +void AnimationState::disableQueue() { + _queue->_drainDisabled = true; +} +void AnimationState::enableQueue() { + _queue->_drainDisabled = false; +} + +Animation *AnimationState::getEmptyAnimation() { + static Vector timelines; + static Animation ret(String(""), timelines, 0); + return &ret; +} + +void AnimationState::applyAttachmentTimeline(AttachmentTimeline* attachmentTimeline, Skeleton& skeleton, float time, MixBlend blend, bool attachments) { + Slot* slot = skeleton.getSlots()[attachmentTimeline->getSlotIndex()]; + if (!slot->getBone().isActive()) return; + + Vector& frames = attachmentTimeline->getFrames(); + if (time < frames[0]) { + if (blend == MixBlend_Setup || blend == MixBlend_First) + setAttachment(skeleton, *slot, slot->getData().getAttachmentName(), attachments); + } else { + int frameIndex = 0; + if (time >= frames[attachmentTimeline->getFrames().size() - 1]) + frameIndex = attachmentTimeline->getFrames().size() - 1; + else + frameIndex = Animation::binarySearch(frames, time) - 1; + setAttachment(skeleton, *slot, attachmentTimeline->getAttachmentNames()[frameIndex], attachments); + } + + /* If an attachment wasn't set (ie before the first frame or attachments is false), set the setup attachment later.*/ + if (slot->getAttachmentState() <= _unkeyedState) slot->setAttachmentState(_unkeyedState + Setup); +} + + +void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, + MixBlend blend, Vector &timelinesRotation, size_t i, bool firstFrame +) { + if (firstFrame) timelinesRotation[i] = 0; + + if (alpha == 1) { + rotateTimeline->apply(skeleton, 0, time, NULL, 1, blend, MixDirection_In); + return; + } + + Bone *bone = skeleton._bones[rotateTimeline->_boneIndex]; + if (!bone->isActive()) return; + Vector& frames = rotateTimeline->_frames; + float r1, r2; + if (time < frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_rotation = bone->_data._rotation; + default: + return; + case MixBlend_First: + r1 = bone->_rotation; + r2 = bone->_data._rotation; + } + } else { + r1 = blend == MixBlend_Setup ? bone->_data._rotation : bone->_rotation; + if (time >= frames[frames.size() - RotateTimeline::ENTRIES]) { + // Time is after last frame. + r2 = bone->_data._rotation + frames[frames.size() + RotateTimeline::PREV_ROTATION]; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(frames, time, RotateTimeline::ENTRIES); + float prevRotation = frames[frame + RotateTimeline::PREV_ROTATION]; + float frameTime = frames[frame]; + float percent = rotateTimeline->getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + + RotateTimeline::PREV_TIME] - frameTime)); + r2 = frames[frame + RotateTimeline::ROTATION] - prevRotation; + r2 -= (16384 - (int) (16384.499999999996 - r2 / 360)) * 360; + r2 = prevRotation + r2 * percent + bone->_data._rotation; + r2 -= (16384 - (int) (16384.499999999996 - r2 / 360)) * 360; + } + } + + // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. + float total, diff = r2 - r1; + diff -= (16384 - (int) (16384.499999999996 - diff / 360)) * 360; + if (diff == 0) { + total = timelinesRotation[i]; + } else { + float lastTotal, lastDiff; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } else { + lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops. + lastDiff = timelinesRotation[i + 1]; // Difference between bones. + } + + bool current = diff > 0, dir = lastTotal >= 0; + // Detect cross at 0 (not 180). + if (MathUtil::sign(lastDiff) != MathUtil::sign(diff) && MathUtil::abs(lastDiff) <= 90) { + // A cross after a 360 rotation is a loop. + if (MathUtil::abs(lastTotal) > 180) lastTotal += 360 * MathUtil::sign(lastTotal); + dir = current; + } + + total = diff + lastTotal - MathUtil::fmod(lastTotal, 360); // Store loops as part of lastTotal. + if (dir != current) { + total += 360 * MathUtil::sign(lastTotal); + } + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + r1 += total * alpha; + bone->_rotation = r1 - (16384 - (int) (16384.499999999996 - r1 / 360)) * 360; +} + +bool AnimationState::updateMixingFrom(TrackEntry *to, float delta) { + TrackEntry *from = to->_mixingFrom; + if (from == NULL) { + return true; + } + + bool finished = updateMixingFrom(from, delta); + + from->_animationLast = from->_nextAnimationLast; + from->_trackLast = from->_nextTrackLast; + + // Require mixTime > 0 to ensure the mixing from entry was applied at least once. + if (to->_mixTime > 0 && to->_mixTime >= to->_mixDuration) { + // Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). + if (from->_totalAlpha == 0 || to->_mixDuration == 0) { + to->_mixingFrom = from->_mixingFrom; + if (from->_mixingFrom != NULL) from->_mixingFrom->_mixingTo = to; + to->_interruptAlpha = from->_interruptAlpha; + _queue->end(from); + } + return finished; + } + + from->_trackTime += delta * from->_timeScale; + to->_mixTime += delta; + + return false; +} + +float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBlend blend) { + TrackEntry *from = to->_mixingFrom; + if (from->_mixingFrom != NULL) applyMixingFrom(from, skeleton, blend); + + float mix; + if (to->_mixDuration == 0) { + // Single frame mix to undo mixingFrom changes. + mix = 1; + if (blend == MixBlend_First) blend = MixBlend_Setup; + } else { + mix = to->_mixTime / to->_mixDuration; + if (mix > 1) { + mix = 1; + } + if (blend != MixBlend_First) blend = from->_mixBlend; + } + + Vector *eventBuffer = mix < from->_eventThreshold ? &_events : NULL; + bool attachments = mix < from->_attachmentThreshold, drawOrder = mix < from->_drawOrderThreshold; + float animationLast = from->_animationLast, animationTime = from->getAnimationTime(); + Vector &timelines = from->_animation->_timelines; + size_t timelineCount = timelines.size(); + float alphaHold = from->_alpha * to->_interruptAlpha, alphaMix = alphaHold * (1 - mix); + + if (blend == MixBlend_Add) { + for (size_t i = 0; i < timelineCount; i++) + timelines[i]->apply(skeleton, animationLast, animationTime, eventBuffer, alphaMix, blend, MixDirection_Out); + } else { + Vector &timelineMode = from->_timelineMode; + Vector &timelineHoldMix = from->_timelineHoldMix; + + bool firstFrame = from->_timelinesRotation.size() == 0; + if (firstFrame) from->_timelinesRotation.setSize(timelines.size() << 1, 0); + + Vector &timelinesRotation = from->_timelinesRotation; + + from->_totalAlpha = 0; + for (size_t i = 0; i < timelineCount; i++) { + Timeline *timeline = timelines[i]; + MixDirection direction = MixDirection_Out; + MixBlend timelineBlend; + float alpha; + switch (timelineMode[i]) { + case Subsequent: + if (!drawOrder && (timeline->getRTTI().isExactly(DrawOrderTimeline::rtti))) continue; + timelineBlend = blend; + alpha = alphaMix; + break; + case First: + timelineBlend = MixBlend_Setup; + alpha = alphaMix; + break; + case HoldSubsequent: + timelineBlend = blend; + alpha = alphaHold; + break; + case HoldFirst: + timelineBlend = MixBlend_Setup; + alpha = alphaHold; + break; + default: + timelineBlend = MixBlend_Setup; + TrackEntry *holdMix = timelineHoldMix[i]; + alpha = alphaHold * MathUtil::max(0.0f, 1.0f - holdMix->_mixTime / holdMix->_mixDuration); + break; + } + from->_totalAlpha += alpha; + if ((timeline->getRTTI().isExactly(RotateTimeline::rtti))) { + applyRotateTimeline((RotateTimeline*)timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i << 1, firstFrame); + } else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) { + applyAttachmentTimeline(static_cast(timeline), skeleton, animationTime, timelineBlend, attachments); + } else { + if (drawOrder && timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) && timelineBlend == MixBlend_Setup) + direction = MixDirection_In; + timeline->apply(skeleton, animationLast, animationTime, eventBuffer, alpha, timelineBlend, direction); + } + } + } + + if (to->_mixDuration > 0) { + queueEvents(from, animationTime); + } + + _events.clear(); + from->_nextAnimationLast = animationTime; + from->_nextTrackLast = from->_trackTime; + + return mix; +} + +void AnimationState::setAttachment(Skeleton& skeleton, Slot& slot, const String& attachmentName, bool attachments) { + slot.setAttachment(attachmentName.isEmpty() ? NULL : skeleton.getAttachment(slot.getData().getIndex(), attachmentName)); + if (attachments) slot.setAttachmentState(_unkeyedState + Current); +} + +void AnimationState::queueEvents(TrackEntry *entry, float animationTime) { + float animationStart = entry->_animationStart, animationEnd = entry->_animationEnd; + float duration = animationEnd - animationStart; + float trackLastWrapped = MathUtil::fmod(entry->_trackLast, duration); + + // Queue events before complete. + size_t i = 0, n = _events.size(); + for (; i < n; ++i) { + Event *e = _events[i]; + if (e->_time < trackLastWrapped) break; + if (e->_time > animationEnd) continue; // Discard events outside animation start/end. + _queue->event(entry, e); + } + + // Queue complete if completed a loop iteration or the animation. + bool complete = false; + if (entry->_loop) + complete = duration == 0 || (trackLastWrapped > MathUtil::fmod(entry->_trackTime, duration)); + else + complete = animationTime >= animationEnd && entry->_animationLast < animationEnd; + if (complete) _queue->complete(entry); + + // Queue events after complete. + for (; i < n; ++i) { + Event *e = _events[i]; + if (e->_time < animationStart) continue; // Discard events outside animation start/end. + _queue->event(entry, _events[i]); + } +} + +void AnimationState::setCurrent(size_t index, TrackEntry *current, bool interrupt) { + TrackEntry *from = expandToIndex(index); + _tracks[index] = current; + + if (from != NULL) { + if (interrupt) _queue->interrupt(from); + + current->_mixingFrom = from; + from->_mixingTo = current; + current->_mixTime = 0; + + // Store interrupted mix percentage. + if (from->_mixingFrom != NULL && from->_mixDuration > 0) { + current->_interruptAlpha *= MathUtil::min(1.0f, from->_mixTime / from->_mixDuration); + } + + from->_timelinesRotation.clear(); // Reset rotation for mixing out, in case entry was mixed in. + } + + _queue->start(current); // triggers animationsChanged +} + +TrackEntry *AnimationState::expandToIndex(size_t index) { + if (index < _tracks.size()) return _tracks[index]; + while (index >= _tracks.size()) + _tracks.add(NULL); + return NULL; +} + +TrackEntry *AnimationState::newTrackEntry(size_t trackIndex, Animation *animation, bool loop, TrackEntry *last) { + TrackEntry *entryP = _trackEntryPool.obtain(); // Pooling + TrackEntry &entry = *entryP; + + entry._trackIndex = trackIndex; + entry._animation = animation; + entry._loop = loop; + entry._holdPrevious = 0; + + entry._eventThreshold = 0; + entry._attachmentThreshold = 0; + entry._drawOrderThreshold = 0; + + entry._animationStart = 0; + entry._animationEnd = animation->getDuration(); + entry._animationLast = -1; + entry._nextAnimationLast = -1; + + entry._delay = 0; + entry._trackTime = 0; + entry._trackLast = -1; + entry._nextTrackLast = -1; // nextTrackLast == -1 signifies a TrackEntry that wasn't applied yet. + entry._trackEnd = FLT_MAX; // loop ? float.MaxValue : animation.Duration; + entry._timeScale = 1; + + entry._alpha = 1; + entry._interruptAlpha = 1; + entry._mixTime = 0; + entry._mixDuration = (last == NULL) ? 0 : _data->getMix(last->_animation, animation); + + return entryP; +} + +void AnimationState::disposeNext(TrackEntry *entry) { + TrackEntry *next = entry->_next; + while (next != NULL) { + _queue->dispose(next); + next = next->_next; + } + entry->_next = NULL; +} + +void AnimationState::animationsChanged() { + _animationsChanged = false; + + _propertyIDs.clear(); + + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *entry = _tracks[i]; + if (!entry) continue; + + while (entry->_mixingFrom != NULL) + entry = entry->_mixingFrom; + + do { + if (entry->_mixingTo == NULL || entry->_mixBlend != MixBlend_Add) computeHold(entry); + entry = entry->_mixingTo; + } while (entry != NULL); + } +} + +void AnimationState::computeHold(TrackEntry *entry) { + TrackEntry* to = entry->_mixingTo; + Vector &timelines = entry->_animation->_timelines; + size_t timelinesCount = timelines.size(); + Vector &timelineMode = entry->_timelineMode; + timelineMode.setSize(timelinesCount, 0); + Vector &timelineHoldMix = entry->_timelineHoldMix; + timelineHoldMix.setSize(timelinesCount, 0); + + if (to != NULL && to->_holdPrevious) { + for (size_t i = 0; i < timelinesCount; i++) { + int id = timelines[i]->getPropertyId(); + if (!_propertyIDs.containsKey(id)) { + _propertyIDs.put(id, true); + timelineMode[i] = HoldFirst; + } else { + timelineMode[i] = HoldSubsequent; + } + } + return; + } + + // outer: + size_t i = 0; + continue_outer: + for (; i < timelinesCount; ++i) { + Timeline *timeline = timelines[i]; + int id = timeline->getPropertyId(); + if (_propertyIDs.containsKey(id)) { + timelineMode[i] = Subsequent; + } else { + _propertyIDs.put(id, true); + + if (to == NULL || timeline->getRTTI().isExactly(AttachmentTimeline::rtti) || + timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) || + timeline->getRTTI().isExactly(EventTimeline::rtti) || !to->_animation->hasTimeline(id)) { + timelineMode[i] = First; + } else { + for (TrackEntry *next = to->_mixingTo; next != NULL; next = next->_mixingTo) { + if (next->_animation->hasTimeline(id)) continue; + if (next->_mixDuration > 0) { + timelineMode[i] = HoldMix; + timelineHoldMix[i] = next; + i++; + goto continue_outer; // continue outer; + } + break; + } + timelineMode[i] = HoldFirst; + } + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp new file mode 100644 index 0000000..afd1d2b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp @@ -0,0 +1,85 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include + +using namespace spine; + +AnimationStateData::AnimationStateData(SkeletonData *skeletonData) : _skeletonData(skeletonData), _defaultMix(0) { +} + +void AnimationStateData::setMix(const String &fromName, const String &toName, float duration) { + Animation *from = _skeletonData->findAnimation(fromName); + Animation *to = _skeletonData->findAnimation(toName); + + setMix(from, to, duration); +} + +void AnimationStateData::setMix(Animation *from, Animation *to, float duration) { + assert(from != NULL); + assert(to != NULL); + + AnimationPair key(from, to); + _animationToMixTime.put(key, duration); +} + +float AnimationStateData::getMix(Animation *from, Animation *to) { + assert(from != NULL); + assert(to != NULL); + + AnimationPair key(from, to); + + if (_animationToMixTime.containsKey(key)) return _animationToMixTime[key]; + return _defaultMix; +} + +SkeletonData *AnimationStateData::getSkeletonData() { + return _skeletonData; +} + +float AnimationStateData::getDefaultMix() { + return _defaultMix; +} + +void AnimationStateData::setDefaultMix(float inValue) { + _defaultMix = inValue; +} + +AnimationStateData::AnimationPair::AnimationPair(Animation *a1, Animation *a2) : _a1(a1), _a2(a2) { +} + +bool AnimationStateData::AnimationPair::operator==(const AnimationPair &other) const { + return _a1->_name == other._a1->_name && _a2->_name == other._a2->_name; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Atlas.cpp new file mode 100644 index 0000000..e658c9c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -0,0 +1,333 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include + +#include + +using namespace spine; + +Atlas::Atlas(const String &path, TextureLoader *textureLoader, bool createTexture) : _textureLoader(textureLoader) { + int dirLength; + char *dir; + int length; + const char *data; + + /* Get directory from atlas path. */ + const char *lastForwardSlash = strrchr(path.buffer(), '/'); + const char *lastBackwardSlash = strrchr(path.buffer(), '\\'); + const char *lastSlash = lastForwardSlash > lastBackwardSlash ? lastForwardSlash : lastBackwardSlash; + if (lastSlash == path) lastSlash++; /* Never drop starting slash. */ + dirLength = (int) (lastSlash ? lastSlash - path.buffer() : 0); + dir = SpineExtension::calloc(dirLength + 1, __FILE__, __LINE__); + memcpy(dir, path.buffer(), dirLength); + dir[dirLength] = '\0'; + + data = SpineExtension::readFile(path, &length); + if (data) { + load(data, length, dir, createTexture); + } + + SpineExtension::free(data, __FILE__, __LINE__); + SpineExtension::free(dir, __FILE__, __LINE__); +} + +Atlas::Atlas(const char *data, int length, const char *dir, TextureLoader *textureLoader, bool createTexture) : _textureLoader( + textureLoader) { + load(data, length, dir, createTexture); +} + +Atlas::~Atlas() { + if (_textureLoader) { + for (size_t i = 0, n = _pages.size(); i < n; ++i) { + _textureLoader->unload(_pages[i]->getRendererObject()); + } + } + ContainerUtil::cleanUpVectorOfPointers(_pages); + ContainerUtil::cleanUpVectorOfPointers(_regions); +} + +void Atlas::flipV() { + for (size_t i = 0, n = _regions.size(); i < n; ++i) { + AtlasRegion *regionP = _regions[i]; + AtlasRegion ®ion = *regionP; + region.v = 1 - region.v; + region.v2 = 1 - region.v2; + } +} + +AtlasRegion *Atlas::findRegion(const String &name) { + for (size_t i = 0, n = _regions.size(); i < n; ++i) + if (_regions[i]->name == name) return _regions[i]; + return NULL; +} + +Vector &Atlas::getPages() { + return _pages; +} + +Vector &Atlas::getRegions() { + return _regions; +} + +void Atlas::load(const char *begin, int length, const char *dir, bool createTexture) { + static const char *formatNames[] = {"", "Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888", "RGBA8888"}; + static const char *textureFilterNames[] = {"", "Nearest", "Linear", "MipMap", "MipMapNearestNearest", "MipMapLinearNearest", + "MipMapNearestLinear", "MipMapLinearLinear"}; + + int count; + const char *end = begin + length; + int dirLength = (int) strlen(dir); + int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\'; + + AtlasPage *page = NULL; + Str str; + Str tuple[4]; + + while (readLine(&begin, end, &str)) { + if (str.end - str.begin == 0) { + page = 0; + } else if (!page) { + char *name = mallocString(&str); + char *path = SpineExtension::calloc(dirLength + needsSlash + strlen(name) + 1, __FILE__, __LINE__); + memcpy(path, dir, dirLength); + if (needsSlash) path[dirLength] = '/'; + strcpy(path + dirLength + needsSlash, name); + + page = new(__FILE__, __LINE__) AtlasPage(String(name, true)); + + int tupleVal = readTuple(&begin, end, tuple); + assert(tupleVal == 2); + + /* size is only optional for an atlas packed with an old TexturePacker. */ + page->width = toInt(tuple); + page->height = toInt(tuple + 1); + readTuple(&begin, end, tuple); + + page->format = (Format) indexOf(formatNames, 8, tuple); + + readTuple(&begin, end, tuple); + page->minFilter = (TextureFilter) indexOf(textureFilterNames, 8, tuple); + page->magFilter = (TextureFilter) indexOf(textureFilterNames, 8, tuple + 1); + + readValue(&begin, end, &str); + + page->uWrap = TextureWrap_ClampToEdge; + page->vWrap = TextureWrap_ClampToEdge; + if (!equals(&str, "none")) { + if (str.end - str.begin == 1) { + if (*str.begin == 'x') { + page->uWrap = TextureWrap_Repeat; + } else if (*str.begin == 'y') { + page->vWrap = TextureWrap_Repeat; + } + } else if (equals(&str, "xy")) { + page->uWrap = TextureWrap_Repeat; + page->vWrap = TextureWrap_Repeat; + } + } + + if (createTexture) { + if (_textureLoader) _textureLoader->load(*page, String(path)); + SpineExtension::free(path, __FILE__, __LINE__); + } else + page->texturePath = String(path, true); + + _pages.add(page); + } else { + AtlasRegion *region = new(__FILE__, __LINE__) AtlasRegion(); + + region->page = page; + region->name = String(mallocString(&str), true); + + readValue(&begin, end, &str); + if (equals(&str, "true")) region->degrees = 90; + else if (equals(&str, "false")) region->degrees = 0; + else region->degrees = toInt(&str); + region->rotate = region->degrees == 90; + + readTuple(&begin, end, tuple); + region->x = toInt(tuple); + region->y = toInt(tuple + 1); + + readTuple(&begin, end, tuple); + region->width = toInt(tuple); + region->height = toInt(tuple + 1); + + region->u = region->x / (float) page->width; + region->v = region->y / (float) page->height; + if (region->rotate) { + region->u2 = (region->x + region->height) / (float) page->width; + region->v2 = (region->y + region->width) / (float) page->height; + } else { + region->u2 = (region->x + region->width) / (float) page->width; + region->v2 = (region->y + region->height) / (float) page->height; + } + + count = readTuple(&begin, end, tuple); + assert(count); + + if (count == 4) { + /* split is optional */ + region->splits.setSize(4, 0); + region->splits[0] = toInt(tuple); + region->splits[1] = toInt(tuple + 1); + region->splits[2] = toInt(tuple + 2); + region->splits[3] = toInt(tuple + 3); + + count = readTuple(&begin, end, tuple); + assert(count); + + if (count == 4) { + /* pad is optional, but only present with splits */ + region->pads.setSize(4, 0); + region->pads[0] = toInt(tuple); + region->pads[1] = toInt(tuple + 1); + region->pads[2] = toInt(tuple + 2); + region->pads[3] = toInt(tuple + 3); + + readTuple(&begin, end, tuple); + } + } + + region->originalWidth = toInt(tuple); + region->originalHeight = toInt(tuple + 1); + + readTuple(&begin, end, tuple); + region->offsetX = (float)toInt(tuple); + region->offsetY = (float)toInt(tuple + 1); + + readValue(&begin, end, &str); + + region->index = toInt(&str); + + _regions.add(region); + } + } +} + +void Atlas::trim(Str *str) { + while (isspace((unsigned char) *str->begin) && str->begin < str->end) + (str->begin)++; + + if (str->begin == str->end) return; + + str->end--; + + while (((unsigned char)*str->end == '\r') && str->end >= str->begin) + str->end--; + + str->end++; +} + +int Atlas::readLine(const char **begin, const char *end, Str *str) { + if (*begin == end) return 0; + + str->begin = *begin; + + /* Find next delimiter. */ + while (*begin != end && **begin != '\n') + (*begin)++; + + str->end = *begin; + trim(str); + + if (*begin != end) (*begin)++; + + return 1; +} + +int Atlas::beginPast(Str *str, char c) { + const char *begin = str->begin; + while (true) { + char lastSkippedChar = *begin; + if (begin == str->end) return 0; + begin++; + if (lastSkippedChar == c) break; + } + str->begin = begin; + return 1; +} + +int Atlas::readValue(const char **begin, const char *end, Str *str) { + readLine(begin, end, str); + if (!beginPast(str, ':')) return 0; + trim(str); + return 1; +} + +int Atlas::readTuple(const char **begin, const char *end, Str tuple[]) { + int i; + Str str = {NULL, NULL}; + readLine(begin, end, &str); + if (!beginPast(&str, ':')) return 0; + + for (i = 0; i < 3; ++i) { + tuple[i].begin = str.begin; + if (!beginPast(&str, ',')) break; + tuple[i].end = str.begin - 2; + trim(&tuple[i]); + } + + tuple[i].begin = str.begin; + tuple[i].end = str.end; + trim(&tuple[i]); + + return i + 1; +} + +char *Atlas::mallocString(Str *str) { + int length = (int) (str->end - str->begin); + char *string = SpineExtension::calloc(length + 1, __FILE__, __LINE__); + memcpy(string, str->begin, length); + string[length] = '\0'; + return string; +} + +int Atlas::indexOf(const char **array, int count, Str *str) { + int length = (int) (str->end - str->begin); + int i; + for (i = count - 1; i >= 0; i--) + if (strncmp(array[i], str->begin, length) == 0) return i; + return 0; +} + +int Atlas::equals(Str *str, const char *other) { + return strncmp(other, str->begin, str->end - str->begin) == 0; +} + +int Atlas::toInt(Str *str) { + return (int) strtol(str->begin, (char **) &str->end, 10); +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp new file mode 100644 index 0000000..92e4d16 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp @@ -0,0 +1,129 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace spine { +RTTI_IMPL(AtlasAttachmentLoader, AttachmentLoader) + +AtlasAttachmentLoader::AtlasAttachmentLoader(Atlas *atlas) : AttachmentLoader(), _atlas(atlas) { +} + +RegionAttachment *AtlasAttachmentLoader::newRegionAttachment(Skin &skin, const String &name, const String &path) { + SP_UNUSED(skin); + + AtlasRegion *regionP = findRegion(path); + if (!regionP) return NULL; + + AtlasRegion ®ion = *regionP; + + RegionAttachment *attachmentP = new(__FILE__, __LINE__) RegionAttachment(name); + + RegionAttachment &attachment = *attachmentP; + attachment.setRendererObject(regionP); + attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate); + attachment._regionOffsetX = region.offsetX; + attachment._regionOffsetY = region.offsetY; + attachment._regionWidth = (float)region.width; + attachment._regionHeight = (float)region.height; + attachment._regionOriginalWidth = (float)region.originalWidth; + attachment._regionOriginalHeight = (float)region.originalHeight; + return attachmentP; +} + +MeshAttachment *AtlasAttachmentLoader::newMeshAttachment(Skin &skin, const String &name, const String &path) { + SP_UNUSED(skin); + + AtlasRegion *regionP = findRegion(path); + if (!regionP) return NULL; + + AtlasRegion ®ion = *regionP; + + MeshAttachment *attachmentP = new(__FILE__, __LINE__) MeshAttachment(name); + + MeshAttachment &attachment = *attachmentP; + attachment.setRendererObject(regionP); + attachment._regionU = region.u; + attachment._regionV = region.v; + attachment._regionU2 = region.u2; + attachment._regionV2 = region.v2; + attachment._regionRotate = region.rotate; + attachment._regionDegrees = region.degrees; + attachment._regionOffsetX = region.offsetX; + attachment._regionOffsetY = region.offsetY; + attachment._regionWidth = (float)region.width; + attachment._regionHeight = (float)region.height; + attachment._regionOriginalWidth = (float)region.originalWidth; + attachment._regionOriginalHeight = (float)region.originalHeight; + + return attachmentP; +} + +BoundingBoxAttachment *AtlasAttachmentLoader::newBoundingBoxAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new(__FILE__, __LINE__) BoundingBoxAttachment(name); +} + +PathAttachment *AtlasAttachmentLoader::newPathAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new(__FILE__, __LINE__) PathAttachment(name); +} + +PointAttachment *AtlasAttachmentLoader::newPointAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new(__FILE__, __LINE__) PointAttachment(name); +} + +ClippingAttachment *AtlasAttachmentLoader::newClippingAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new(__FILE__, __LINE__) ClippingAttachment(name); +} + +void AtlasAttachmentLoader::configureAttachment(Attachment* attachment) { + SP_UNUSED(attachment); +} + +AtlasRegion *AtlasAttachmentLoader::findRegion(const String &name) { + return _atlas->findRegion(name); +} + +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Attachment.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Attachment.cpp new file mode 100644 index 0000000..fd83f2f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Attachment.cpp @@ -0,0 +1,63 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(Attachment) + +Attachment::Attachment(const String &name) : _name(name), _refCount(0) { + assert(_name.length() > 0); +} + +Attachment::~Attachment() { +} + +const String &Attachment::getName() const { + return _name; +} + +int Attachment::getRefCount() { + return _refCount; +} + +void Attachment::reference() { + _refCount++; +} + +void Attachment::dereference() { + _refCount--; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp new file mode 100644 index 0000000..5875f7e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp @@ -0,0 +1,52 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(AttachmentLoader) + +AttachmentLoader::AttachmentLoader() { +} + +AttachmentLoader::~AttachmentLoader() { +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp new file mode 100644 index 0000000..06e8301 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -0,0 +1,130 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(AttachmentTimeline, Timeline) + +AttachmentTimeline::AttachmentTimeline(int frameCount) : Timeline(), _slotIndex(0) { + _frames.ensureCapacity(frameCount); + _attachmentNames.ensureCapacity(frameCount); + + _frames.setSize(frameCount, 0); + + for (int i = 0; i < frameCount; ++i) { + _attachmentNames.add(String()); + } +} + +void AttachmentTimeline::setAttachment(Skeleton& skeleton, Slot& slot, String* attachmentName) { + slot.setAttachment(attachmentName == NULL || attachmentName->isEmpty() ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName)); +} + +void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction +) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(alpha); + + assert(_slotIndex < skeleton._slots.size()); + + String *attachmentName; + Slot *slotP = skeleton._slots[_slotIndex]; + Slot &slot = *slotP; + if (!slot._bone.isActive()) return; + + if (direction == MixDirection_Out) { + if (blend == MixBlend_Setup) setAttachment(skeleton, slot, &slot._data._attachmentName); + return; + } + + if (time < _frames[0]) { + // Time is before first frame. + if (blend == MixBlend_Setup || blend == MixBlend_First) { + setAttachment(skeleton, slot, &slot._data._attachmentName); + } + return; + } + + size_t frameIndex; + if (time >= _frames[_frames.size() - 1]) { + // Time is after last frame. + frameIndex = _frames.size() - 1; + } else { + frameIndex = Animation::binarySearch(_frames, time, 1) - 1; + } + + attachmentName = &_attachmentNames[frameIndex]; + slot.setAttachment(attachmentName->length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName)); +} + +int AttachmentTimeline::getPropertyId() { + return ((int) TimelineType_Attachment << 24) + _slotIndex; +} + +void AttachmentTimeline::setFrame(int frameIndex, float time, const String &attachmentName) { + _frames[frameIndex] = time; + _attachmentNames[frameIndex] = attachmentName; +} + +size_t AttachmentTimeline::getSlotIndex() { + return _slotIndex; +} + +void AttachmentTimeline::setSlotIndex(size_t inValue) { + _slotIndex = inValue; +} + +Vector &AttachmentTimeline::getFrames() { + return _frames; +} + +Vector &AttachmentTimeline::getAttachmentNames() { + return _attachmentNames; +} + +size_t AttachmentTimeline::getFrameCount() { + return _frames.size(); +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Bone.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Bone.cpp new file mode 100644 index 0000000..7c0627d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -0,0 +1,551 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL(Bone, Updatable) + +bool Bone::yDown = false; + +void Bone::setYDown(bool inValue) { + yDown = inValue; +} + +bool Bone::isYDown() { + return yDown; +} + +Bone::Bone(BoneData &data, Skeleton &skeleton, Bone *parent) : Updatable(), + _data(data), + _skeleton(skeleton), + _parent(parent), + _x(0), + _y(0), + _rotation(0), + _scaleX(0), + _scaleY(0), + _shearX(0), + _shearY(0), + _ax(0), + _ay(0), + _arotation(0), + _ascaleX(0), + _ascaleY(0), + _ashearX(0), + _ashearY(0), + _appliedValid(false), + _a(1), + _b(0), + _worldX(0), + _c(0), + _d(1), + _worldY(0), + _sorted(false), + _active(false) +{ + setToSetupPose(); +} + +void Bone::update() { + updateWorldTransform(_x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY); +} + +void Bone::updateWorldTransform() { + updateWorldTransform(_x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY); +} + +void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { + float cosine, sine; + float pa, pb, pc, pd; + Bone *parent = _parent; + + _ax = x; + _ay = y; + _arotation = rotation; + _ascaleX = scaleX; + _ascaleY = scaleY; + _ashearX = shearX; + _ashearY = shearY; + _appliedValid = true; + + if (!parent) { /* Root bone. */ + float rotationY = rotation + 90 + shearY; + float sx = _skeleton.getScaleX(); + float sy = _skeleton.getScaleY(); + _a = MathUtil::cosDeg(rotation + shearX) * scaleX * sx; + _b = MathUtil::cosDeg(rotationY) * scaleY * sx; + _c = MathUtil::sinDeg(rotation + shearX) * scaleX * sy; + _d = MathUtil::sinDeg(rotationY) * scaleY * sy; + _worldX = x * sx + _skeleton.getX(); + _worldY = y * sy + _skeleton.getY(); + return; + } + + pa = parent->_a; + pb = parent->_b; + pc = parent->_c; + pd = parent->_d; + + _worldX = pa * x + pb * y + parent->_worldX; + _worldY = pc * x + pd * y + parent->_worldY; + + switch (_data.getTransformMode()) { + case TransformMode_Normal: { + float rotationY = rotation + 90 + shearY; + float la = MathUtil::cosDeg(rotation + shearX) * scaleX; + float lb = MathUtil::cosDeg(rotationY) * scaleY; + float lc = MathUtil::sinDeg(rotation + shearX) * scaleX; + float ld = MathUtil::sinDeg(rotationY) * scaleY; + _a = pa * la + pb * lc; + _b = pa * lb + pb * ld; + _c = pc * la + pd * lc; + _d = pc * lb + pd * ld; + return; + } + case TransformMode_OnlyTranslation: { + float rotationY = rotation + 90 + shearY; + _a = MathUtil::cosDeg(rotation + shearX) * scaleX; + _b = MathUtil::cosDeg(rotationY) * scaleY; + _c = MathUtil::sinDeg(rotation + shearX) * scaleX; + _d = MathUtil::sinDeg(rotationY) * scaleY; + break; + } + case TransformMode_NoRotationOrReflection: { + float s = pa * pa + pc * pc; + float prx, rx, ry, la, lb, lc, ld; + if (s > 0.0001f) { + s = MathUtil::abs(pa * pd - pb * pc) / s; + pa /= _skeleton.getScaleX(); + pc /= _skeleton.getScaleY(); + pb = pc * s; + pd = pa * s; + prx = MathUtil::atan2(pc, pa) * MathUtil::Rad_Deg; + } else { + pa = 0; + pc = 0; + prx = 90 - MathUtil::atan2(pd, pb) * MathUtil::Rad_Deg; + } + rx = rotation + shearX - prx; + ry = rotation + shearY - prx + 90; + la = MathUtil::cosDeg(rx) * scaleX; + lb = MathUtil::cosDeg(ry) * scaleY; + lc = MathUtil::sinDeg(rx) * scaleX; + ld = MathUtil::sinDeg(ry) * scaleY; + _a = pa * la - pb * lc; + _b = pa * lb - pb * ld; + _c = pc * la + pd * lc; + _d = pc * lb + pd * ld; + break; + } + case TransformMode_NoScale: + case TransformMode_NoScaleOrReflection: { + float za, zc, s; + float r, zb, zd, la, lb, lc, ld; + cosine = MathUtil::cosDeg(rotation); + sine = MathUtil::sinDeg(rotation); + za = (pa * cosine + pb * sine) / _skeleton.getScaleX(); + zc = (pc * cosine + pd * sine) / _skeleton.getScaleY(); + s = MathUtil::sqrt(za * za + zc * zc); + if (s > 0.00001f) s = 1 / s; + za *= s; + zc *= s; + s = MathUtil::sqrt(za * za + zc * zc); + if (_data.getTransformMode() == TransformMode_NoScale + && (pa * pd - pb * pc < 0) != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0)) + s = -s; + r = MathUtil::Pi / 2 + MathUtil::atan2(zc, za); + zb = MathUtil::cos(r) * s; + zd = MathUtil::sin(r) * s; + la = MathUtil::cosDeg(shearX) * scaleX; + lb = MathUtil::cosDeg(90 + shearY) * scaleY; + lc = MathUtil::sinDeg(shearX) * scaleX; + ld = MathUtil::sinDeg(90 + shearY) * scaleY; + _a = za * la + zb * lc; + _b = za * lb + zb * ld; + _c = zc * la + zd * lc; + _d = zc * lb + zd * ld; + break; + } + } + _a *= _skeleton.getScaleX(); + _b *= _skeleton.getScaleX(); + _c *= _skeleton.getScaleY(); + _d *= _skeleton.getScaleY(); +} + +void Bone::setToSetupPose() { + BoneData &data = _data; + _x = data.getX(); + _y = data.getY(); + _rotation = data.getRotation(); + _scaleX = data.getScaleX(); + _scaleY = data.getScaleY(); + _shearX = data.getShearX(); + _shearY = data.getShearY(); +} + +void Bone::worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY) { + float a = _a; + float b = _b; + float c = _c; + float d = _d; + + float invDet = 1 / (a * d - b * c); + float x = worldX - _worldX; + float y = worldY - _worldY; + + outLocalX = (x * d * invDet - y * b * invDet); + outLocalY = (y * a * invDet - x * c * invDet); +} + +void Bone::localToWorld(float localX, float localY, float &outWorldX, float &outWorldY) { + outWorldX = localX * _a + localY * _b + _worldX; + outWorldY = localX * _c + localY * _d + _worldY; +} + +float Bone::worldToLocalRotation(float worldRotation) { + float sin = MathUtil::sinDeg(worldRotation); + float cos = MathUtil::cosDeg(worldRotation); + + return MathUtil::atan2(_a * sin - _c * cos, _d * cos - _b * sin) * MathUtil::Rad_Deg + this->_rotation - this->_shearX; +} + +float Bone::localToWorldRotation(float localRotation) { + localRotation -= this->_rotation - this->_shearX; + float sin = MathUtil::sinDeg(localRotation); + float cos = MathUtil::cosDeg(localRotation); + + return MathUtil::atan2(cos * _c + sin * _d, cos * _a + sin * _b) * MathUtil::Rad_Deg; +} + +void Bone::rotateWorld(float degrees) { + float a = _a; + float b = _b; + float c = _c; + float d = _d; + + float cos = MathUtil::cosDeg(degrees); + float sin = MathUtil::sinDeg(degrees); + + _a = cos * a - sin * c; + _b = cos * b - sin * d; + _c = sin * a + cos * c; + _d = sin * b + cos * d; + + _appliedValid = false; +} + +float Bone::getWorldToLocalRotationX() { + Bone *parent = _parent; + if (!parent) { + return _arotation; + } + + float pa = parent->_a; + float pb = parent->_b; + float pc = parent->_c; + float pd = parent->_d; + float a = _a; + float c = _c; + + return MathUtil::atan2(pa * c - pc * a, pd * a - pb * c) * MathUtil::Rad_Deg; +} + +float Bone::getWorldToLocalRotationY() { + Bone *parent = _parent; + if (!parent) { + return _arotation; + } + + float pa = parent->_a; + float pb = parent->_b; + float pc = parent->_c; + float pd = parent->_d; + float b = _b; + float d = _d; + + return MathUtil::atan2(pa * d - pc * b, pd * b - pb * d) * MathUtil::Rad_Deg; +} + +BoneData &Bone::getData() { + return _data; +} + +Skeleton &Bone::getSkeleton() { + return _skeleton; +} + +Bone *Bone::getParent() { + return _parent; +} + +Vector &Bone::getChildren() { + return _children; +} + +float Bone::getX() { + return _x; +} + +void Bone::setX(float inValue) { + _x = inValue; +} + +float Bone::getY() { + return _y; +} + +void Bone::setY(float inValue) { + _y = inValue; +} + +float Bone::getRotation() { + return _rotation; +} + +void Bone::setRotation(float inValue) { + _rotation = inValue; +} + +float Bone::getScaleX() { + return _scaleX; +} + +void Bone::setScaleX(float inValue) { + _scaleX = inValue; +} + +float Bone::getScaleY() { + return _scaleY; +} + +void Bone::setScaleY(float inValue) { + _scaleY = inValue; +} + +float Bone::getShearX() { + return _shearX; +} + +void Bone::setShearX(float inValue) { + _shearX = inValue; +} + +float Bone::getShearY() { + return _shearY; +} + +void Bone::setShearY(float inValue) { + _shearY = inValue; +} + +float Bone::getAppliedRotation() { + return _arotation; +} + +void Bone::setAppliedRotation(float inValue) { + _arotation = inValue; +} + +float Bone::getAX() { + return _ax; +} + +void Bone::setAX(float inValue) { + _ax = inValue; +} + +float Bone::getAY() { + return _ay; +} + +void Bone::setAY(float inValue) { + _ay = inValue; +} + +float Bone::getAScaleX() { + return _ascaleX; +} + +void Bone::setAScaleX(float inValue) { + _ascaleX = inValue; +} + +float Bone::getAScaleY() { + return _ascaleY; +} + +void Bone::setAScaleY(float inValue) { + _ascaleY = inValue; +} + +float Bone::getAShearX() { + return _ashearX; +} + +void Bone::setAShearX(float inValue) { + _ashearX = inValue; +} + +float Bone::getAShearY() { + return _ashearY; +} + +void Bone::setAShearY(float inValue) { + _ashearY = inValue; +} + +float Bone::getA() { + return _a; +} + +void Bone::setA(float inValue) { + _a = inValue; +} + +float Bone::getB() { + return _b; +} + +void Bone::setB(float inValue) { + _b = inValue; +} + +float Bone::getC() { + return _c; +} + +void Bone::setC(float inValue) { + _c = inValue; +} + +float Bone::getD() { + return _d; +} + +void Bone::setD(float inValue) { + _d = inValue; +} + +float Bone::getWorldX() { + return _worldX; +} + +void Bone::setWorldX(float inValue) { + _worldX = inValue; +} + +float Bone::getWorldY() { + return _worldY; +} + +void Bone::setWorldY(float inValue) { + _worldY = inValue; +} + +float Bone::getWorldRotationX() { + return MathUtil::atan2(_c, _a) * MathUtil::Rad_Deg; +} + +float Bone::getWorldRotationY() { + return MathUtil::atan2(_d, _b) * MathUtil::Rad_Deg; +} + +float Bone::getWorldScaleX() { + return MathUtil::sqrt(_a * _a + _c * _c); +} + +float Bone::getWorldScaleY() { + return MathUtil::sqrt(_b * _b + _d * _d); +} + +bool Bone::isAppliedValid() { + return _appliedValid; +} +void Bone::setAppliedValid(bool valid) { + _appliedValid = valid; +} + +void Bone::updateAppliedTransform() { + Bone *parent = _parent; + _appliedValid = 1; + if (!parent) { + _ax = _worldX; + _ay = _worldY; + _arotation = MathUtil::atan2(_c, _a) * MathUtil::Rad_Deg; + _ascaleX = MathUtil::sqrt(_a * _a + _c * _c); + _ascaleY = MathUtil::sqrt(_b * _b + _d * _d); + _ashearX = 0; + _ashearY = MathUtil::atan2(_a * _b + _c * _d, _a * _d - _b * _c) * MathUtil::Rad_Deg; + } else { + float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d; + float pid = 1 / (pa * pd - pb * pc); + float dx = _worldX - parent->_worldX, dy = _worldY - parent->_worldY; + float ia = pid * pd; + float id = pid * pa; + float ib = pid * pb; + float ic = pid * pc; + float ra = ia * _a - ib * _c; + float rb = ia * _b - ib * _d; + float rc = id * _c - ic * _a; + float rd = id * _d - ic * _b; + _ax = (dx * pd * pid - dy * pb * pid); + _ay = (dy * pa * pid - dx * pc * pid); + _ashearX = 0; + _ascaleX = MathUtil::sqrt(ra * ra + rc * rc); + if (_ascaleX > 0.0001f) { + float det = ra * rd - rb * rc; + _ascaleY = det / _ascaleX; + _ashearY = MathUtil::atan2(ra * rb + rc * rd, det) * MathUtil::Rad_Deg; + _arotation = MathUtil::atan2(rc, ra) * MathUtil::Rad_Deg; + } else { + _ascaleX = 0; + _ascaleY = MathUtil::sqrt(rb * rb + rd * rd); + _ashearY = 0; + _arotation = 90 - MathUtil::atan2(rd, rb) * MathUtil::Rad_Deg; + } + } +} + +bool Bone::isActive() { + return _active; +} + +void Bone::setActive(bool inValue) { + _active = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/BoneData.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/BoneData.cpp new file mode 100644 index 0000000..36a3221 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/BoneData.cpp @@ -0,0 +1,148 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +BoneData::BoneData(int index, const String &name, BoneData *parent) : + _index(index), + _name(name), + _parent(parent), + _length(0), + _x(0), + _y(0), + _rotation(0), + _scaleX(1), + _scaleY(1), + _shearX(0), + _shearY(0), + _transformMode(TransformMode_Normal), + _skinRequired(false) { + assert(index >= 0); + assert(_name.length() > 0); +} + +int BoneData::getIndex() { + return _index; +} + +const String &BoneData::getName() { + return _name; +} + +BoneData *BoneData::getParent() { + return _parent; +} + +float BoneData::getLength() { + return _length; +} + +void BoneData::setLength(float inValue) { + _length = inValue; +} + +float BoneData::getX() { + return _x; +} + +void BoneData::setX(float inValue) { + _x = inValue; +} + +float BoneData::getY() { + return _y; +} + +void BoneData::setY(float inValue) { + _y = inValue; +} + +float BoneData::getRotation() { + return _rotation; +} + +void BoneData::setRotation(float inValue) { + _rotation = inValue; +} + +float BoneData::getScaleX() { + return _scaleX; +} + +void BoneData::setScaleX(float inValue) { + _scaleX = inValue; +} + +float BoneData::getScaleY() { + return _scaleY; +} + +void BoneData::setScaleY(float inValue) { + _scaleY = inValue; +} + +float BoneData::getShearX() { + return _shearX; +} + +void BoneData::setShearX(float inValue) { + _shearX = inValue; +} + +float BoneData::getShearY() { + return _shearY; +} + +void BoneData::setShearY(float inValue) { + _shearY = inValue; +} + +TransformMode BoneData::getTransformMode() { + return _transformMode; +} + +void BoneData::setTransformMode(TransformMode inValue) { + _transformMode = inValue; +} + +bool BoneData::isSkinRequired() { + return _skinRequired; +} + +void BoneData::setSkinRequired(bool inValue) { + _skinRequired = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp new file mode 100644 index 0000000..918493a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp @@ -0,0 +1,47 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +using namespace spine; + +RTTI_IMPL(BoundingBoxAttachment, VertexAttachment) + +BoundingBoxAttachment::BoundingBoxAttachment(const String &name) : VertexAttachment(name) { +} + +Attachment* BoundingBoxAttachment::copy() { + BoundingBoxAttachment* copy = new (__FILE__, __LINE__) BoundingBoxAttachment(getName()); + copyTo(copy); + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp new file mode 100644 index 0000000..b1a5461 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp @@ -0,0 +1,58 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +RTTI_IMPL(ClippingAttachment, VertexAttachment) + +ClippingAttachment::ClippingAttachment(const String &name) : VertexAttachment(name), _endSlot(NULL) { +} + +SlotData *ClippingAttachment::getEndSlot() { + return _endSlot; +} + +void ClippingAttachment::setEndSlot(SlotData *inValue) { + _endSlot = inValue; +} + +Attachment* ClippingAttachment::copy() { + ClippingAttachment* copy = new (__FILE__, __LINE__) ClippingAttachment(getName()); + copyTo(copy); + copy->_endSlot = _endSlot; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp new file mode 100644 index 0000000..b01bd29 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -0,0 +1,145 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(ColorTimeline, CurveTimeline) + +const int ColorTimeline::ENTRIES = 5; +const int ColorTimeline::PREV_TIME = -5; +const int ColorTimeline::PREV_R = -4; +const int ColorTimeline::PREV_G = -3; +const int ColorTimeline::PREV_B = -2; +const int ColorTimeline::PREV_A = -1; +const int ColorTimeline::R = 1; +const int ColorTimeline::G = 2; +const int ColorTimeline::B = 3; +const int ColorTimeline::A = 4; + +ColorTimeline::ColorTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0) { + _frames.setSize(frameCount * ENTRIES, 0); +} + +void ColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction +) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slotP = skeleton._slots[_slotIndex]; + Slot &slot = *slotP; + if (!slot._bone.isActive()) return; + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + slot._color.set(slot._data._color); + return; + case MixBlend_First: { + Color &color = slot._color, setup = slot._data._color; + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, + (setup.a - color.a) * alpha); + } + default: ; + } + return; + } + + float r, g, b, a; + if (time >= _frames[_frames.size() - ENTRIES]) { + // Time is after last frame. + size_t i = _frames.size(); + r = _frames[i + PREV_R]; + g = _frames[i + PREV_G]; + b = _frames[i + PREV_B]; + a = _frames[i + PREV_A]; + } else { + // Interpolate between the previous frame and the current frame. + size_t frame = (size_t)Animation::binarySearch(_frames, time, ENTRIES); + r = _frames[frame + PREV_R]; + g = _frames[frame + PREV_G]; + b = _frames[frame + PREV_B]; + a = _frames[frame + PREV_A]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + r += (_frames[frame + R] - r) * percent; + g += (_frames[frame + G] - g) * percent; + b += (_frames[frame + B] - b) * percent; + a += (_frames[frame + A] - a) * percent; + } + + if (alpha == 1) { + slot.getColor().set(r, g, b, a); + } else { + Color &color = slot.getColor(); + if (blend == MixBlend_Setup) color.set(slot.getData().getColor()); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } +} + +int ColorTimeline::getPropertyId() { + return ((int) TimelineType_Color << 24) + _slotIndex; +} + +void ColorTimeline::setFrame(int frameIndex, float time, float r, float g, float b, float a) { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + R] = r; + _frames[frameIndex + G] = g; + _frames[frameIndex + B] = b; + _frames[frameIndex + A] = a; +} + +int ColorTimeline::getSlotIndex() { + return _slotIndex; +} + +void ColorTimeline::setSlotIndex(int inValue) { + _slotIndex = inValue; +} + +Vector &ColorTimeline::getFrames() { + return _frames; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp new file mode 100644 index 0000000..9e4e313 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp @@ -0,0 +1,62 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +using namespace spine; + +ConstraintData::ConstraintData(const String& name): _name(name), _order(0), _skinRequired(false) { +} + +ConstraintData::~ConstraintData() { +} + +const String& ConstraintData::getName() { + return _name; +} + +size_t ConstraintData::getOrder() { + return _order; +} + +void ConstraintData::setOrder(size_t inValue) { + _order = inValue; +} + +bool ConstraintData::isSkinRequired() { + return _skinRequired; +} + +void ConstraintData::setSkinRequired(bool inValue) { + _skinRequired = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp new file mode 100644 index 0000000..92e9a08 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp @@ -0,0 +1,127 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +RTTI_IMPL(CurveTimeline, Timeline) + +const float CurveTimeline::LINEAR = 0; +const float CurveTimeline::STEPPED = 1; +const float CurveTimeline::BEZIER = 2; +const int CurveTimeline::BEZIER_SIZE = 10 * 2 - 1; + +CurveTimeline::CurveTimeline(int frameCount) { + assert(frameCount > 0); + + _curves.setSize((frameCount - 1) * BEZIER_SIZE, 0); +} + +CurveTimeline::~CurveTimeline() { +} + +size_t CurveTimeline::getFrameCount() { + return _curves.size() / BEZIER_SIZE + 1; +} + +void CurveTimeline::setLinear(size_t frameIndex) { + _curves[frameIndex * BEZIER_SIZE] = LINEAR; +} + +void CurveTimeline::setStepped(size_t frameIndex) { + _curves[frameIndex * BEZIER_SIZE] = STEPPED; +} + +void CurveTimeline::setCurve(size_t frameIndex, float cx1, float cy1, float cx2, float cy2) { + float tmpx = (-cx1 * 2 + cx2) * 0.03f, tmpy = (-cy1 * 2 + cy2) * 0.03f; + float dddfx = ((cx1 - cx2) * 3 + 1) * 0.006f, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006f; + float ddfx = tmpx * 2 + dddfx, ddfy = tmpy * 2 + dddfy; + float dfx = cx1 * 0.3f + tmpx + dddfx * 0.16666667f, dfy = cy1 * 0.3f + tmpy + dddfy * 0.16666667f; + + size_t i = frameIndex * BEZIER_SIZE; + _curves[i++] = BEZIER; + + float x = dfx, y = dfy; + for (size_t n = i + BEZIER_SIZE - 1; i < n; i += 2) { + _curves[i] = x; + _curves[i + 1] = y; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + x += dfx; + y += dfy; + } +} + +float CurveTimeline::getCurvePercent(size_t frameIndex, float percent) { + percent = MathUtil::clamp(percent, 0, 1); + size_t i = frameIndex * BEZIER_SIZE; + float type = _curves[i]; + + if (type == LINEAR) { + return percent; + } + + if (type == STEPPED) { + return 0; + } + + i++; + float x = 0; + for (size_t start = i, n = i + BEZIER_SIZE - 1; i < n; i += 2) { + x = _curves[i]; + if (x >= percent) { + float prevX, prevY; + if (i == start) { + prevX = 0; + prevY = 0; + } else { + prevX = _curves[i - 2]; + prevY = _curves[i - 1]; + } + return prevY + (_curves[i + 1] - prevY) * (percent - prevX) / (x - prevX); + } + } + + float y = _curves[i - 1]; + + return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. +} + +float CurveTimeline::getCurveType(size_t frameIndex) { + return _curves[frameIndex * BEZIER_SIZE]; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp new file mode 100644 index 0000000..bdec6e4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -0,0 +1,298 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(DeformTimeline, CurveTimeline) + +DeformTimeline::DeformTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0), _attachment(NULL) { + _frames.ensureCapacity(frameCount); + _frameVertices.ensureCapacity(frameCount); + + _frames.setSize(frameCount, 0); + + for (int i = 0; i < frameCount; ++i) { + Vector vec; + _frameVertices.add(vec); + } +} + +void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction +) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slotP = skeleton._slots[_slotIndex]; + Slot &slot = *slotP; + if (!slot._bone.isActive()) return; + + Attachment *slotAttachment = slot.getAttachment(); + if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) { + return; + } + + VertexAttachment *attachment = static_cast(slotAttachment); + if (attachment->_deformAttachment != _attachment) { + return; + } + + Vector &deformArray = slot._deform; + if (deformArray.size() == 0) { + blend = MixBlend_Setup; + } + + Vector< Vector > &frameVertices = _frameVertices; + size_t vertexCount = frameVertices[0].size(); + + Vector &frames = _frames; + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + deformArray.clear(); + return; + case MixBlend_First: { + if (alpha == 1) { + deformArray.clear(); + return; + } + deformArray.setSize(vertexCount, 0); + Vector &deformInner = deformArray; + if (attachment->getBones().size() == 0) { + // Unweighted vertex positions. + Vector &setupVertices = attachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) + deformInner[i] += (setupVertices[i] - deformInner[i]) * alpha; + } else { + // Weighted deform offsets. + alpha = 1 - alpha; + for (size_t i = 0; i < vertexCount; i++) + deformInner[i] *= alpha; + } + } + case MixBlend_Replace: + case MixBlend_Add: + return; + } + } + + deformArray.setSize(vertexCount, 0); + Vector &deform = deformArray; + + if (time >= frames[frames.size() - 1]) { // Time is after last frame. + Vector &lastVertices = frameVertices[frames.size() - 1]; + if (alpha == 1) { + if (blend == MixBlend_Add) { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, no alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) + deform[i] += lastVertices[i] - setupVertices[i]; + } else { + // Weighted deform offsets, no alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] += lastVertices[i]; + } + } else { + // Vertex positions or deform offsets, no alpha. + memcpy(deform.buffer(), lastVertices.buffer(), vertexCount * sizeof(float)); + } + } else { + switch (blend) { + case MixBlend_Setup: { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, with alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float setup = setupVertices[i]; + deform[i] = setup + (lastVertices[i] - setup) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] = lastVertices[i] * alpha; + } + break; + } + case MixBlend_First: + case MixBlend_Replace: + // Vertex positions or deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] += (lastVertices[i] - deform[i]) * alpha; + break; + case MixBlend_Add: + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, no alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) + deform[i] += (lastVertices[i] - setupVertices[i]) * alpha; + } else { + // Weighted deform offsets, alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] += lastVertices[i] * alpha; + } + } + } + return; + } + + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(frames, time); + Vector &prevVertices = frameVertices[frame - 1]; + Vector &nextVertices = frameVertices[frame]; + float frameTime = frames[frame]; + float percent = getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); + + if (alpha == 1) { + if (blend == MixBlend_Add) { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, no alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i]; + } + } else { + // Weighted deform offsets, no alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += prev + (nextVertices[i] - prev) * percent; + } + } + } else { + // Vertex positions or deform offsets, no alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] = prev + (nextVertices[i] - prev) * percent; + } + } + } else { + switch (blend) { + case MixBlend_Setup: { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, with alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i], setup = setupVertices[i]; + deform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } + break; + } + case MixBlend_First: + case MixBlend_Replace: + // Vertex positions or deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha; + } + break; + case MixBlend_Add: + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, with alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } + } + } +} + +int DeformTimeline::getPropertyId() { + assert(_attachment != NULL); + return ((int) TimelineType_Deform << 24) + _attachment->_id + _slotIndex; +} + +void DeformTimeline::setFrame(int frameIndex, float time, Vector &vertices) { + _frames[frameIndex] = time; + _frameVertices[frameIndex].clear(); + _frameVertices[frameIndex].addAll(vertices); +} + +int DeformTimeline::getSlotIndex() { + return _slotIndex; +} + +void DeformTimeline::setSlotIndex(int inValue) { + _slotIndex = inValue; +} + +Vector &DeformTimeline::getFrames() { + return _frames; +} + +Vector > &DeformTimeline::getVertices() { + return _frameVertices; +} + +VertexAttachment *DeformTimeline::getAttachment() { + return _attachment; +} + +void DeformTimeline::setAttachment(VertexAttachment *inValue) { + _attachment = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp new file mode 100644 index 0000000..c0c2c8d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -0,0 +1,127 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(DrawOrderTimeline, Timeline) + +DrawOrderTimeline::DrawOrderTimeline(int frameCount) : Timeline() { + _frames.ensureCapacity(frameCount); + _drawOrders.ensureCapacity(frameCount); + + _frames.setSize(frameCount, 0); + + for (int i = 0; i < frameCount; ++i) { + Vector vec; + _drawOrders.add(vec); + } +} + +void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction +) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(alpha); + + Vector &drawOrder = skeleton._drawOrder; + Vector &slots = skeleton._slots; + if (direction == MixDirection_Out) { + if (blend == MixBlend_Setup) { + drawOrder.clear(); + drawOrder.ensureCapacity(slots.size()); + for (size_t i = 0, n = slots.size(); i < n; ++i) + drawOrder.add(slots[i]); + } + return; + } + + if (time < _frames[0]) { + if (blend == MixBlend_Setup || blend == MixBlend_First) { + drawOrder.clear(); + drawOrder.ensureCapacity(slots.size()); + for (size_t i = 0, n = slots.size(); i < n; ++i) + drawOrder.add(slots[i]); + } + return; + } + + size_t frame; + if (time >= _frames[_frames.size() - 1]) { + // Time is after last frame. + frame = _frames.size() - 1; + } else + frame = (size_t)Animation::binarySearch(_frames, time) - 1; + + Vector &drawOrderToSetupIndex = _drawOrders[frame]; + if (drawOrderToSetupIndex.size() == 0) { + drawOrder.clear(); + for (size_t i = 0, n = slots.size(); i < n; ++i) + drawOrder.add(slots[i]); + } else { + for (size_t i = 0, n = drawOrderToSetupIndex.size(); i < n; ++i) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } +} + +int DrawOrderTimeline::getPropertyId() { + return ((int) TimelineType_DrawOrder << 24); +} + +void DrawOrderTimeline::setFrame(size_t frameIndex, float time, Vector &drawOrder) { + _frames[frameIndex] = time; + _drawOrders[frameIndex].clear(); + _drawOrders[frameIndex].addAll(drawOrder); +} + +Vector &DrawOrderTimeline::getFrames() { + return _frames; +} + +Vector > &DrawOrderTimeline::getDrawOrders() { + return _drawOrders; +} + +size_t DrawOrderTimeline::getFrameCount() { + return _frames.size(); +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Event.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Event.cpp new file mode 100644 index 0000000..4f1c1e8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Event.cpp @@ -0,0 +1,95 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +spine::Event::Event(float time, const spine::EventData &data) : + _data(data), + _time(time), + _intValue(0), + _floatValue(0), + _stringValue(), + _volume(1), + _balance(0) { +} + +const spine::EventData &spine::Event::getData() { + return _data; +} + +float spine::Event::getTime() { + return _time; +} + +int spine::Event::getIntValue() { + return _intValue; +} + +void spine::Event::setIntValue(int inValue) { + _intValue = inValue; +} + +float spine::Event::getFloatValue() { + return _floatValue; +} + +void spine::Event::setFloatValue(float inValue) { + _floatValue = inValue; +} + +const spine::String &spine::Event::getStringValue() { + return _stringValue; +} + +void spine::Event::setStringValue(const spine::String &inValue) { + _stringValue = inValue; +} + + +float spine::Event::getVolume() { + return _volume; +} + +void spine::Event::setVolume(float inValue) { + _volume = inValue; +} + +float spine::Event::getBalance() { + return _balance; +} + +void spine::Event::setBalance(float inValue) { + _balance = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/EventData.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/EventData.cpp new file mode 100644 index 0000000..433f03a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/EventData.cpp @@ -0,0 +1,101 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +spine::EventData::EventData(const spine::String &name) : + _name(name), + _intValue(0), + _floatValue(0), + _stringValue(), + _audioPath(), + _volume(1), + _balance(0) { + assert(_name.length() > 0); +} + +/// The name of the event, which is unique within the skeleton. +const spine::String &spine::EventData::getName() const { + return _name; +} + +int spine::EventData::getIntValue() const { + return _intValue; +} + +void spine::EventData::setIntValue(int inValue) { + _intValue = inValue; +} + +float spine::EventData::getFloatValue() const { + return _floatValue; +} + +void spine::EventData::setFloatValue(float inValue) { + _floatValue = inValue; +} + +const spine::String &spine::EventData::getStringValue() const { + return _stringValue; +} + +void spine::EventData::setStringValue(const spine::String &inValue) { + this->_stringValue = inValue; +} + +const spine::String &spine::EventData::getAudioPath() const { + return _audioPath; +} + +void spine::EventData::setAudioPath(const spine::String &inValue) { + _audioPath = inValue; +} + + +float spine::EventData::getVolume() const { + return _volume; +} + +void spine::EventData::setVolume(float inValue) { + _volume = inValue; +} + +float spine::EventData::getBalance() const { + return _balance; +} + +void spine::EventData::setBalance(float inValue) { + _balance = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp new file mode 100644 index 0000000..29a7797 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -0,0 +1,111 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(EventTimeline, Timeline) + +EventTimeline::EventTimeline(int frameCount) : Timeline() { + _frames.setSize(frameCount, 0); + _events.setSize(frameCount, NULL); +} + +EventTimeline::~EventTimeline() { + ContainerUtil::cleanUpVectorOfPointers(_events); +} + +void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction +) { + if (pEvents == NULL) return; + + Vector &events = *pEvents; + + size_t frameCount = _frames.size(); + + if (lastTime > time) { + // Fire events after last time for looped animations. + apply(skeleton, lastTime, FLT_MAX, pEvents, alpha, blend, direction); + lastTime = -1.0f; + } else if (lastTime >= _frames[frameCount - 1]) { + // Last time is after last frame. + return; + } + + if (time < _frames[0]) return; // Time is before first frame. + + int frame; + if (lastTime < _frames[0]) { + frame = 0; + } else { + frame = Animation::binarySearch(_frames, lastTime); + float frameTime = _frames[frame]; + while (frame > 0) { + // Fire multiple events with the same frame. + if (_frames[frame - 1] != frameTime) break; + frame--; + } + } + + for (; (size_t)frame < frameCount && time >= _frames[frame]; ++frame) + events.add(_events[frame]); +} + +int EventTimeline::getPropertyId() { + return ((int) TimelineType_Event << 24); +} + +void EventTimeline::setFrame(size_t frameIndex, Event *event) { + _frames[frameIndex] = event->getTime(); + _events[frameIndex] = event; +} + +const Vector& EventTimeline::getFrames() { return _frames; } + +Vector &EventTimeline::getEvents() { return _events; } + +size_t EventTimeline::getFrameCount() { return _frames.size(); } diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Extension.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Extension.cpp new file mode 100644 index 0000000..e19f273 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Extension.cpp @@ -0,0 +1,127 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include + +#include + +using namespace spine; + +SpineExtension *SpineExtension::_instance = NULL; + +void SpineExtension::setInstance(SpineExtension *inValue) { + assert(inValue); + + _instance = inValue; +} + +SpineExtension *SpineExtension::getInstance() { + if (!_instance) _instance = spine::getDefaultExtension(); + assert(_instance); + + return _instance; +} + +SpineExtension::~SpineExtension() { +} + +SpineExtension::SpineExtension() { +} + +DefaultSpineExtension::~DefaultSpineExtension() { +} + +void *DefaultSpineExtension::_alloc(size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + if (size == 0) + return 0; + void *ptr = ::malloc(size); + return ptr; +} + +void *DefaultSpineExtension::_calloc(size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + if (size == 0) + return 0; + + void *ptr = ::malloc(size); + if (ptr) { + memset(ptr, 0, size); + } + return ptr; +} + +void *DefaultSpineExtension::_realloc(void *ptr, size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + void *mem = NULL; + if (size == 0) + return 0; + if (ptr == NULL) + mem = ::malloc(size); + else + mem = ::realloc(ptr, size); + return mem; +} + +void DefaultSpineExtension::_free(void *mem, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + ::free(mem); +} + +char *DefaultSpineExtension::_readFile(const String &path, int *length) { + char *data; + FILE *file = fopen(path.buffer(), "rb"); + if (!file) return 0; + + fseek(file, 0, SEEK_END); + *length = (int) ftell(file); + fseek(file, 0, SEEK_SET); + + data = SpineExtension::alloc(*length, __FILE__, __LINE__); + fread(data, 1, *length, file); + fclose(file); + + return data; +} + +DefaultSpineExtension::DefaultSpineExtension() : SpineExtension() { +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp new file mode 100644 index 0000000..b90499c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -0,0 +1,358 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(IkConstraint, Updatable) + +void IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha) { + if (!bone._appliedValid) bone.updateAppliedTransform(); + Bone *p = bone.getParent(); + float pa = p->_a, pb = p->_b, pc = p->_c, pd = p->_d; + float rotationIK = -bone._ashearX - bone._arotation; + float tx = 0, ty = 0; + + switch(bone._data.getTransformMode()) { + case TransformMode_OnlyTranslation: + tx = targetX - bone._worldX; + ty = targetY - bone._worldY; + break; + case TransformMode_NoRotationOrReflection: { + float s = MathUtil::abs(pa * pd - pb * pc) / (pa * pa + pc * pc); + float sa = pa / bone._skeleton.getScaleX(); + float sc = pc / bone._skeleton.getScaleY(); + pb = -sc * s * bone._skeleton.getScaleX(); + pd = sa * s * bone._skeleton.getScaleY(); + rotationIK += MathUtil::atan2(sc, sa) * MathUtil::Rad_Deg; + } + default: + float x = targetX - p->_worldX, y = targetY - p->_worldY; + float d = pa * pd - pb * pc; + tx = (x * pd - y * pb) / d - bone._ax; + ty = (y * pa - x * pc) / d - bone._ay; + } + rotationIK += MathUtil::atan2(ty, tx) * MathUtil::Rad_Deg; + if (bone._ascaleX < 0) rotationIK += 180; + if (rotationIK > 180) rotationIK -= 360; + else if (rotationIK < -180) rotationIK += 360; + float sx = bone._ascaleX; + float sy = bone._ascaleY; + if (compress || stretch) { + switch(bone._data.getTransformMode()) { + case TransformMode_NoScale: + case TransformMode_NoScaleOrReflection: + tx = targetX - bone._worldX; + ty = targetY - bone._worldY; + default: ; + } + float b = bone._data.getLength() * sx, dd = MathUtil::sqrt(tx * tx + ty * ty); + if (((compress && dd < b) || (stretch && dd > b)) && (b > 0.0001f)) { + float s = (dd / b - 1) * alpha + 1; + sx *= s; + if (uniform) sy *= s; + } + } + bone.updateWorldTransform(bone._ax, bone._ay, bone._arotation + rotationIK * alpha, sx, sy, bone._ashearX, bone._ashearY); +} + +void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, float softness, float alpha) { + float a, b, c, d; + float px, py, psx, sx, psy; + float cx, cy, csx, cwx, cwy; + int o1, o2, s2, u; + Bone *pp = parent.getParent(); + float tx, ty, dx, dy, dd, l1, l2, a1, a2, r, td, sd, p; + float id, x, y; + if (alpha == 0) { + child.updateWorldTransform(); + return; + } + if (!parent._appliedValid) parent.updateAppliedTransform(); + if (!child._appliedValid) child.updateAppliedTransform(); + px = parent._ax; + py = parent._ay; + psx = parent._ascaleX; + sx = psx; + psy = parent._ascaleY; + csx = child._ascaleX; + if (psx < 0) { + psx = -psx; + o1 = 180; + s2 = -1; + } else { + o1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + o2 = 180; + } else + o2 = 0; + r = psx - psy; + cx = child._ax; + u = (r < 0 ? -r : r) <= 0.0001f; + if (!u) { + cy = 0; + cwx = parent._a * cx + parent._worldX; + cwy = parent._c * cx + parent._worldY; + } else { + cy = child._ay; + cwx = parent._a * cx + parent._b * cy + parent._worldX; + cwy = parent._c * cx + parent._d * cy + parent._worldY; + } + a = pp->_a; + b = pp->_b; + c = pp->_c; + d = pp->_d; + id = 1 / (a * d - b * c); + x = cwx - pp->_worldX; + y = cwy - pp->_worldY; + dx = (x * d - y * b) * id - px; + dy = (y * a - x * c) * id - py; + l1 = MathUtil::sqrt(dx * dx + dy * dy); + l2 = child._data.getLength() * csx; + if (l1 < 0.0001) { + apply(parent, targetX, targetY, false, stretch, false, alpha); + child.updateWorldTransform(cx, cy, 0, child._ascaleX, child._ascaleY, child._ashearX, child._ashearY); + return; + } + x = targetX - pp->_worldX; + y = targetY - pp->_worldY; + tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + dd = tx * tx + ty * ty; + if (softness != 0) { + softness *= psx * (csx + 1) / 2; + td = MathUtil::sqrt(dd), sd = td - l1 - l2 * psx + softness; + if (sd > 0) { + p = MathUtil::min(1.0f, sd / (softness * 2)) - 1; + p = (sd - softness * (1 - p * p)) / td; + tx -= p * tx; + ty -= p * ty; + dd = tx * tx + ty * ty; + } + } + if (u) { + float cosine; + l2 *= psx; + cosine = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cosine < -1) cosine = -1; + else if (cosine > 1) { + cosine = 1; + if (stretch) sx *= (MathUtil::sqrt(dd) / (l1 + l2) - 1) * alpha + 1; + } + a2 = MathUtil::acos(cosine) * bendDir; + a = l1 + l2 * cosine; + b = l2 * MathUtil::sin(a2); + a1 = MathUtil::atan2(ty * a - tx * b, tx * a + ty * b); + } else { + a = psx * l2, b = psy * l2; + float aa = a * a, bb = b * b, ll = l1 * l1, ta = MathUtil::atan2(ty, tx); + float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c0; + if (d >= 0) { + float q = MathUtil::sqrt(d), r0, r1; + if (c1 < 0) q = -q; + q = -(c1 + q) / 2; + r0 = q / c2; + r1 = c0 / q; + r = MathUtil::abs(r0) < MathUtil::abs(r1) ? r0 : r1; + if (r * r <= dd) { + y = MathUtil::sqrt(dd - r * r) * bendDir; + a1 = ta - MathUtil::atan2(y, r); + a2 = MathUtil::atan2(y / psy, (r - l1) / psx); + goto break_outer; + } + } + { + float minAngle = MathUtil::Pi, minX = l1 - a, minDist = minX * minX, minY = 0; + float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c0 = -a * l1 / (aa - bb); + if (c0 >= -1 && c0 <= 1) { + c0 = MathUtil::acos(c0); + x = a * MathUtil::cos(c0) + l1; + y = b * MathUtil::sin(c0); + d = x * x + y * y; + if (d < minDist) { + minAngle = c0; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c0; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) / 2) { + a1 = ta - MathUtil::atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } else { + a1 = ta - MathUtil::atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + } + break_outer: + { + float os = MathUtil::atan2(cy, cx) * s2; + a1 = (a1 - os) * MathUtil::Rad_Deg + o1 - parent._arotation; + if (a1 > 180) a1 -= 360; + else if (a1 < -180) a1 += 360; + parent.updateWorldTransform(px, py, parent._arotation + a1 * alpha, sx, parent._ascaleY, 0, 0); + a2 = ((a2 + os) * MathUtil::Rad_Deg - child._ashearX) * s2 + o2 - child._arotation; + if (a2 > 180) a2 -= 360; + else if (a2 < -180) a2 += 360; + child.updateWorldTransform(cx, cy, child._arotation + a2 * alpha, child._ascaleX, child._ascaleY, child._ashearX, child._ashearY); + } +} + +IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Updatable(), + _data(data), + _bendDirection(data.getBendDirection()), + _compress(data.getCompress()), + _stretch(data.getStretch()), + _mix(data.getMix()), + _softness(data.getSoftness()), + _target(skeleton.findBone( + data.getTarget()->getName())), + _active(false) +{ + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); i++) { + BoneData *boneData = _data.getBones()[i]; + _bones.add(skeleton.findBone(boneData->getName())); + } +} + +/// Applies the constraint to the constrained bones. +void IkConstraint::apply() { + update(); +} + +void IkConstraint::update() { + switch (_bones.size()) { + case 1: { + Bone *bone0 = _bones[0]; + apply(*bone0, _target->getWorldX(), _target->getWorldY(), _compress, _stretch, _data._uniform, _mix); + } + break; + case 2: { + Bone *bone0 = _bones[0]; + Bone *bone1 = _bones[1]; + apply(*bone0, *bone1, _target->getWorldX(), _target->getWorldY(), _bendDirection, _stretch, _softness, _mix); + } + break; + } +} + +int IkConstraint::getOrder() { + return _data.getOrder(); +} + +IkConstraintData &IkConstraint::getData() { + return _data; +} + +Vector &IkConstraint::getBones() { + return _bones; +} + +Bone *IkConstraint::getTarget() { + return _target; +} + +void IkConstraint::setTarget(Bone *inValue) { + _target = inValue; +} + +int IkConstraint::getBendDirection() { + return _bendDirection; +} + +void IkConstraint::setBendDirection(int inValue) { + _bendDirection = inValue; +} + +float IkConstraint::getMix() { + return _mix; +} + +void IkConstraint::setMix(float inValue) { + _mix = inValue; +} + +bool IkConstraint::getStretch() { + return _stretch; +} + +void IkConstraint::setStretch(bool inValue) { + _stretch = inValue; +} + +bool IkConstraint::getCompress() { + return _compress; +} + +void IkConstraint::setCompress(bool inValue) { + _compress = inValue; +} + +bool IkConstraint::isActive() { + return _active; +} + +void IkConstraint::setActive(bool inValue) { + _active = inValue; +} + +float IkConstraint::getSoftness() { + return _softness; +} + +void IkConstraint::setSoftness(float inValue) { + _softness = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp new file mode 100644 index 0000000..f13fe5f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -0,0 +1,110 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +IkConstraintData::IkConstraintData(const String &name) : + ConstraintData(name), + _target(NULL), + _bendDirection(1), + _compress(false), + _stretch(false), + _uniform(false), + _mix(1), + _softness(0) { +} + +Vector &IkConstraintData::getBones() { + return _bones; +} + +BoneData *IkConstraintData::getTarget() { + return _target; +} + +void IkConstraintData::setTarget(BoneData *inValue) { + _target = inValue; +} + +int IkConstraintData::getBendDirection() { + return _bendDirection; +} + +void IkConstraintData::setBendDirection(int inValue) { + _bendDirection = inValue; +} + +float IkConstraintData::getMix() { + return _mix; +} + +void IkConstraintData::setMix(float inValue) { + _mix = inValue; +} + +bool IkConstraintData::getStretch() { + return _stretch; +} + +void IkConstraintData::setStretch(bool inValue) { + _stretch = inValue; +} + +bool IkConstraintData::getCompress() { + return _compress; +} + +void IkConstraintData::setCompress(bool inValue) { + _compress = inValue; +} + + +bool IkConstraintData::getUniform() { + return _uniform; +} + +void IkConstraintData::setUniform(bool inValue) { + _uniform = inValue; +} + +float IkConstraintData::getSoftness() { + return _softness; +} + +void IkConstraintData::setSoftness(float inValue) { + _softness = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp new file mode 100644 index 0000000..f0e817a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -0,0 +1,170 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(IkConstraintTimeline, CurveTimeline) + +const int IkConstraintTimeline::ENTRIES = 6; +const int IkConstraintTimeline::PREV_TIME = -6; +const int IkConstraintTimeline::PREV_MIX = -5; +const int IkConstraintTimeline::PREV_SOFTNESS = -4; +const int IkConstraintTimeline::PREV_BEND_DIRECTION = -3; +const int IkConstraintTimeline::PREV_COMPRESS = -2; +const int IkConstraintTimeline::PREV_STRETCH = -1; +const int IkConstraintTimeline::MIX = 1; +const int IkConstraintTimeline::SOFTNESS = 2; +const int IkConstraintTimeline::BEND_DIRECTION = 3; +const int IkConstraintTimeline::COMPRESS = 4; +const int IkConstraintTimeline::STRETCH = 5; + +IkConstraintTimeline::IkConstraintTimeline(int frameCount) : CurveTimeline(frameCount), _ikConstraintIndex(0) { + _frames.setSize(frameCount * ENTRIES, 0); +} + +void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + IkConstraint *constraintP = skeleton._ikConstraints[_ikConstraintIndex]; + IkConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._mix = constraint._data._mix; + constraint._softness = constraint._data._softness; + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + return; + case MixBlend_First: + constraint._mix += (constraint._data._mix - constraint._mix) * alpha; + constraint._softness += (constraint._data._softness - constraint._softness) * alpha; + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + return; + default: + return; + } + } + + if (time >= _frames[_frames.size() - ENTRIES]) { + // Time is after last frame. + if (blend == MixBlend_Setup) { + constraint._mix = + constraint._data._mix + (_frames[_frames.size() + PREV_MIX] - constraint._data._mix) * alpha; + constraint._softness = constraint._data._softness + + (_frames[_frames.size() + PREV_SOFTNESS] - constraint._data._softness) * alpha; + if (direction == MixDirection_Out) { + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + } else { + constraint._bendDirection = (int) _frames[_frames.size() + PREV_BEND_DIRECTION]; + constraint._compress = _frames[_frames.size() + PREV_COMPRESS] != 0; + constraint._stretch = _frames[_frames.size() + PREV_STRETCH] != 0; + } + } else { + constraint._mix += (_frames[_frames.size() + PREV_MIX] - constraint._mix) * alpha; + constraint._softness += (_frames[_frames.size() + PREV_SOFTNESS] - constraint._softness) * alpha; + if (direction == MixDirection_In) { + constraint._bendDirection = (int) _frames[_frames.size() + PREV_BEND_DIRECTION]; + constraint._compress = _frames[_frames.size() + PREV_COMPRESS] != 0; + constraint._stretch = _frames[_frames.size() + PREV_STRETCH] != 0; + } + } + return; + } + + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + float mix = _frames[frame + PREV_MIX]; + float softness = _frames[frame + PREV_SOFTNESS]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + if (blend == MixBlend_Setup) { + constraint._mix = + constraint._data._mix + (mix + (_frames[frame + MIX] - mix) * percent - constraint._data._mix) * alpha; + constraint._softness = constraint._data._softness + + (softness + (_frames[frame + SOFTNESS] - softness) * percent - constraint._data._softness) * alpha; + if (direction == MixDirection_Out) { + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + } else { + constraint._bendDirection = (int) _frames[_frames.size() + PREV_BEND_DIRECTION]; + constraint._compress = _frames[frame + PREV_COMPRESS] != 0; + constraint._stretch = _frames[frame + PREV_STRETCH] != 0; + } + } else { + constraint._mix += (mix + (_frames[frame + MIX] - mix) * percent - constraint._mix) * alpha; + constraint._softness += (softness + (_frames[frame + SOFTNESS] - softness) * percent - constraint._softness) * alpha; + if (direction == MixDirection_In) { + constraint._bendDirection = (int) _frames[frame + PREV_BEND_DIRECTION]; + constraint._compress = _frames[frame + PREV_COMPRESS] != 0; + constraint._stretch = _frames[frame + PREV_STRETCH] != 0; + } + } +} + +int IkConstraintTimeline::getPropertyId() { + return ((int) TimelineType_IkConstraint << 24) + _ikConstraintIndex; +} + +void IkConstraintTimeline::setFrame(int frameIndex, float time, float mix, float softness, int bendDirection, bool compress, bool stretch) { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + MIX] = mix; + _frames[frameIndex + SOFTNESS] = softness; + _frames[frameIndex + BEND_DIRECTION] = (float)bendDirection; + _frames[frameIndex + COMPRESS] = compress ? 1 : 0; + _frames[frameIndex + STRETCH] = stretch ? 1 : 0; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Json.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Json.cpp new file mode 100644 index 0000000..f654e6b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Json.cpp @@ -0,0 +1,555 @@ +/* +Copyright (c) 2009, Dave Gamble +Copyright (c) 2013, Esoteric Software + +Permission is hereby granted, dispose of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +/* Json */ +/* JSON parser in CPP, from json.c in the spine-c runtime */ + +#ifndef _DEFAULT_SOURCE +/* Bring strings.h definitions into string.h, where appropriate */ +#define _DEFAULT_SOURCE +#endif + +#ifndef _BSD_SOURCE +/* Bring strings.h definitions into string.h, where appropriate */ +#define _BSD_SOURCE +#endif + +#include +#include +#include + +#include +#include + +using namespace spine; + +const int Json::JSON_FALSE = 0; +const int Json::JSON_TRUE = 1; +const int Json::JSON_NULL = 2; +const int Json::JSON_NUMBER = 3; +const int Json::JSON_STRING = 4; +const int Json::JSON_ARRAY = 5; +const int Json::JSON_OBJECT = 6; + +const char *Json::_error = NULL; + +Json *Json::getItem(Json *object, const char *string) { + Json *c = object->_child; + while (c && json_strcasecmp(c->_name, string)) { + c = c->_next; + } + return c; +} + +const char *Json::getString(Json *object, const char *name, const char *defaultValue) { + object = getItem(object, name); + if (object) { + return object->_valueString; + } + + return defaultValue; +} + +float Json::getFloat(Json *value, const char *name, float defaultValue) { + value = getItem(value, name); + return value ? value->_valueFloat : defaultValue; +} + +int Json::getInt(Json *value, const char *name, int defaultValue) { + value = getItem(value, name); + return value ? value->_valueInt : defaultValue; +} + +bool Json::getBoolean(spine::Json *value, const char *name, bool defaultValue) { + value = getItem(value, name); + if (value) { + if (value->_valueString) return strcmp(value->_valueString, "true") == 0; + if (value->_type == JSON_NULL) return false; + if (value->_type == JSON_NUMBER) return value->_valueFloat != 0; + return defaultValue; + } else { + return defaultValue; + } +} + +const char *Json::getError() { + return _error; +} + +Json::Json(const char *value) : + _next(NULL), +#if SPINE_JSON_HAVE_PREV + _prev(NULL), +#endif + _child(NULL), + _type(0), + _size(0), + _valueString(NULL), + _valueInt(0), + _valueFloat(0), + _name(NULL) { + if (value) { + value = parseValue(this, skip(value)); + + assert(value); + } +} + +Json::~Json() { + spine::Json* curr = NULL; + spine::Json* next = _child; + do { + curr = next; + if (curr) { + next = curr->_next; + } + delete curr; + } while(next); + + if (_valueString) { + SpineExtension::free(_valueString, __FILE__, __LINE__); + } + + if (_name) { + SpineExtension::free(_name, __FILE__, __LINE__); + } +} + +const char *Json::skip(const char *inValue) { + if (!inValue) { + /* must propagate NULL since it's often called in skip(f(...)) form */ + return NULL; + } + + while (*inValue && (unsigned char) *inValue <= 32) { + inValue++; + } + + return inValue; +} + +const char *Json::parseValue(Json *item, const char *value) { + /* Referenced by constructor, parseArray(), and parseObject(). */ + /* Always called with the result of skip(). */ +#ifdef SPINE_JSON_DEBUG /* Checked at entry to graph, constructor, and after every parse call. */ + if (!value) { + /* Fail on null. */ + return NULL; + } +#endif + + switch (*value) { + case 'n': { + if (!strncmp(value + 1, "ull", 3)) { + item->_type = JSON_NULL; + return value + 4; + } + break; + } + case 'f': { + if (!strncmp(value + 1, "alse", 4)) { + item->_type = JSON_FALSE; + /* calloc prevents us needing item->_type = JSON_FALSE or valueInt = 0 here */ + return value + 5; + } + break; + } + case 't': { + if (!strncmp(value + 1, "rue", 3)) { + item->_type = JSON_TRUE; + item->_valueInt = 1; + return value + 4; + } + break; + } + case '\"': + return parseString(item, value); + case '[': + return parseArray(item, value); + case '{': + return parseObject(item, value); + case '-': /* fallthrough */ + case '0': /* fallthrough */ + case '1': /* fallthrough */ + case '2': /* fallthrough */ + case '3': /* fallthrough */ + case '4': /* fallthrough */ + case '5': /* fallthrough */ + case '6': /* fallthrough */ + case '7': /* fallthrough */ + case '8': /* fallthrough */ + case '9': + return parseNumber(item, value); + default: + break; + } + + _error = value; + return NULL; /* failure. */ +} + +static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC}; + +const char *Json::parseString(Json *item, const char *str) { + const char *ptr = str + 1; + char *ptr2; + char *out; + int len = 0; + unsigned uc, uc2; + if (*str != '\"') { + /* TODO: don't need this check when called from parseValue, but do need from parseObject */ + _error = str; + return 0; + } /* not a string! */ + + while (*ptr != '\"' && *ptr && ++len) { + if (*ptr++ == '\\') { + ptr++; /* Skip escaped quotes. */ + } + } + + out = SpineExtension::alloc(len + 1, __FILE__, __LINE__); /* The length needed for the string, roughly. */ + if (!out) { + return 0; + } + + ptr = str + 1; + ptr2 = out; + while (*ptr != '\"' && *ptr) { + if (*ptr != '\\') { + *ptr2++ = *ptr++; + } else { + ptr++; + switch (*ptr) { + case 'b': + *ptr2++ = '\b'; + break; + case 'f': + *ptr2++ = '\f'; + break; + case 'n': + *ptr2++ = '\n'; + break; + case 'r': + *ptr2++ = '\r'; + break; + case 't': + *ptr2++ = '\t'; + break; + case 'u': { + /* transcode utf16 to utf8. */ + sscanf(ptr + 1, "%4x", &uc); + ptr += 4; /* get the unicode char. */ + + if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) { + break; /* check for invalid. */ + } + + /* TODO provide an option to ignore surrogates, use unicode replacement character? */ + if (uc >= 0xD800 && uc <= 0xDBFF) /* UTF16 surrogate pairs. */ { + if (ptr[1] != '\\' || ptr[2] != 'u') { + break; /* missing second-half of surrogate. */ + } + sscanf(ptr + 3, "%4x", &uc2); + ptr += 6; + if (uc2 < 0xDC00 || uc2 > 0xDFFF) { + break; /* invalid second-half of surrogate. */ + } + uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF)); + } + + len = 4; + if (uc < 0x80) { + len = 1; + } else if (uc < 0x800) { + len = 2; + } else if (uc < 0x10000) { + len = 3; + } + ptr2 += len; + + switch (len) { + case 4: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 3: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 2: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 1: + *--ptr2 = (uc | firstByteMark[len]); + } + ptr2 += len; + break; + } + default: + *ptr2++ = *ptr; + break; + } + ptr++; + } + } + + *ptr2 = 0; + + if (*ptr == '\"') { + ptr++; /* TODO error handling if not \" or \0 ? */ + } + + item->_valueString = out; + item->_type = JSON_STRING; + + return ptr; +} + +const char *Json::parseNumber(Json *item, const char *num) { + double result = 0.0; + int negative = 0; + char *ptr = (char *) num; + + if (*ptr == '-') { + negative = -1; + ++ptr; + } + + while (*ptr >= '0' && *ptr <= '9') { + result = result * 10.0 + (*ptr - '0'); + ++ptr; + } + + if (*ptr == '.') { + double fraction = 0.0; + int n = 0; + ++ptr; + + while (*ptr >= '0' && *ptr <= '9') { + fraction = (fraction * 10.0) + (*ptr - '0'); + ++ptr; + ++n; + } + result += fraction / pow(10.0, n); + } + + if (negative) { + result = -result; + } + + if (*ptr == 'e' || *ptr == 'E') { + double exponent = 0; + int expNegative = 0; + int n = 0; + ++ptr; + + if (*ptr == '-') { + expNegative = -1; + ++ptr; + } else if (*ptr == '+') { + ++ptr; + } + + while (*ptr >= '0' && *ptr <= '9') { + exponent = (exponent * 10.0) + (*ptr - '0'); + ++ptr; + ++n; + } + + if (expNegative) { + result = result / pow(10, exponent); + } else { + result = result * pow(10, exponent); + } + } + + if (ptr != num) { + /* Parse success, number found. */ + item->_valueFloat = (float)result; + item->_valueInt = (int)result; + item->_type = JSON_NUMBER; + return ptr; + } else { + /* Parse failure, _error is set. */ + _error = num; + return NULL; + } +} + +const char *Json::parseArray(Json *item, const char *value) { + Json *child; + +#ifdef SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */ + if (*value != '[') { + ep = value; + return 0; + } /* not an array! */ +#endif + + item->_type = JSON_ARRAY; + value = skip(value + 1); + if (*value == ']') { + return value + 1; /* empty array. */ + } + + item->_child = child = new(__FILE__, __LINE__) Json(NULL); + if (!item->_child) { + return NULL; /* memory fail */ + } + + value = skip(parseValue(child, skip(value))); /* skip any spacing, get the value. */ + + if (!value) { + return NULL; + } + + item->_size = 1; + + while (*value == ',') { + Json *new_item = new(__FILE__, __LINE__) Json(NULL); + if (!new_item) { + return NULL; /* memory fail */ + } + child->_next = new_item; +#if SPINE_JSON_HAVE_PREV + new_item->prev = child; +#endif + child = new_item; + value = skip(parseValue(child, skip(value + 1))); + if (!value) { + return NULL; /* parse fail */ + } + item->_size++; + } + + if (*value == ']') { + return value + 1; /* end of array */ + } + + _error = value; + + return NULL; /* malformed. */ +} + +/* Build an object from the text. */ +const char *Json::parseObject(Json *item, const char *value) { + Json *child; + +#ifdef SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */ + if (*value != '{') { + ep = value; + return 0; + } /* not an object! */ +#endif + + item->_type = JSON_OBJECT; + value = skip(value + 1); + if (*value == '}') { + return value + 1; /* empty array. */ + } + + item->_child = child = new(__FILE__, __LINE__) Json(NULL); + if (!item->_child) { + return NULL; + } + value = skip(parseString(child, skip(value))); + if (!value) { + return NULL; + } + child->_name = child->_valueString; + child->_valueString = 0; + if (*value != ':') { + _error = value; + return NULL; + } /* fail! */ + + value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return NULL; + } + + item->_size = 1; + + while (*value == ',') { + Json *new_item = new(__FILE__, __LINE__) Json(NULL); + if (!new_item) { + return NULL; /* memory fail */ + } + child->_next = new_item; +#if SPINE_JSON_HAVE_PREV + new_item->prev = child; +#endif + child = new_item; + value = skip(parseString(child, skip(value + 1))); + if (!value) { + return NULL; + } + child->_name = child->_valueString; + child->_valueString = 0; + if (*value != ':') { + _error = value; + return NULL; + } /* fail! */ + + value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return NULL; + } + item->_size++; + } + + if (*value == '}') { + return value + 1; /* end of array */ + } + + _error = value; + + return NULL; /* malformed. */ +} + +int Json::json_strcasecmp(const char *s1, const char *s2) { + /* TODO we may be able to elide these NULL checks if we can prove + * the graph and input (only callsite is Json_getItem) should not have NULLs + */ + if (s1 && s2) { +#if defined(_WIN32) + return _stricmp(s1, s2); +#else + return strcasecmp(s1, s2); +#endif + } else { + if (s1 < s2) { + return -1; /* s1 is null, s2 is not */ + } else if (s1 == s2) { + return 0; /* both are null */ + } else { + return 1; /* s2 is nul s1 is not */ + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp new file mode 100644 index 0000000..cfc082a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp @@ -0,0 +1,46 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +LinkedMesh::LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, bool inheritDeform) : + _mesh(mesh), + _skin(skin), + _slotIndex(slotIndex), + _parent(parent), + _inheritDeform(inheritDeform) { +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/MathUtil.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/MathUtil.cpp new file mode 100644 index 0000000..4601f71 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/MathUtil.cpp @@ -0,0 +1,127 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include + +// Required for division by 0 in _isNaN on MSVC +#ifdef _MSC_VER +#pragma warning(disable:4723) +#endif + +using namespace spine; + +const float MathUtil::Pi = 3.1415926535897932385f; +const float MathUtil::Pi_2 = 3.1415926535897932385f * 2; +const float MathUtil::Deg_Rad = (3.1415926535897932385f / 180.0f); +const float MathUtil::Rad_Deg = (180.0f / 3.1415926535897932385f); + +float MathUtil::abs(float v) { + return ((v) < 0 ? -(v) : (v)); +} + +float MathUtil::sign(float v) { + return ((v) < 0 ? -1.0f : (v) > 0 ? 1.0f : 0.0f); +} + +float MathUtil::clamp(float x, float min, float max) { + return ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))); +} + +float MathUtil::fmod(float a, float b) { + return (float)::fmod(a, b); +} + +/// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 +/// degrees), largest error of 0.00488 radians (0.2796 degrees). +float MathUtil::atan2(float y, float x) { + return (float)::atan2(y, x); +} + +/// Returns the cosine in radians from a lookup table. +float MathUtil::cos(float radians) { + return (float)::cos(radians); +} + +/// Returns the sine in radians from a lookup table. +float MathUtil::sin(float radians) { + return (float)::sin(radians); +} + +float MathUtil::sqrt(float v) { + return (float)::sqrt(v); +} + +float MathUtil::acos(float v) { + return (float)::acos(v); +} + +/// Returns the sine in radians from a lookup table. +float MathUtil::sinDeg(float degrees) { + return (float)::sin(degrees * MathUtil::Deg_Rad); +} + +/// Returns the cosine in radians from a lookup table. +float MathUtil::cosDeg(float degrees) { + return (float)::cos(degrees * MathUtil::Deg_Rad); +} + +/* Need to pass 0 as an argument, so VC++ doesn't error with C2124 */ +static bool _isNan(float value, float zero) { + float _nan = (float) 0.0 / zero; + return 0 == memcmp((void *) &value, (void *) &_nan, sizeof(value)); +} + +bool MathUtil::isNan(float v) { + return _isNan(v, 0); +} + +float MathUtil::random() { + return ::rand() / (float)RAND_MAX; +} + +float MathUtil::randomTriangular(float min, float max) { + return randomTriangular(min, max, (min + max) * 0.5f); +} + +float MathUtil::randomTriangular(float min, float max, float mode) { + float u = random(); + float d = max - min; + if (u <= (mode - min) / d) return min + sqrt(u * d * (mode - min)); + return max - sqrt((1 - u) * d * (max - mode)); +} + +float MathUtil::pow(float a, float b) { + return (float)::pow(a, b); +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp new file mode 100644 index 0000000..4bb4338 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp @@ -0,0 +1,349 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include + +using namespace spine; + +RTTI_IMPL(MeshAttachment, VertexAttachment) + +MeshAttachment::MeshAttachment(const String &name) : VertexAttachment(name), HasRendererObject(), + _regionOffsetX(0), + _regionOffsetY(0), + _regionWidth(0), + _regionHeight(0), + _regionOriginalWidth(0), + _regionOriginalHeight(0), + _parentMesh(NULL), + _path(), + _regionU(0), + _regionV(0), + _regionU2(0), + _regionV2(0), + _width(0), + _height(0), + _color(1, 1, 1, 1), + _hullLength(0), + _regionRotate(false), + _regionDegrees(0) +{} + +MeshAttachment::~MeshAttachment() {} + +void MeshAttachment::updateUVs() { + if (_uvs.size() != _regionUVs.size()) { + _uvs.setSize(_regionUVs.size(), 0); + } + + int i = 0, n = _regionUVs.size(); + float u = _regionU, v = _regionV; + float width = 0, height = 0; + + switch (_regionDegrees) { + case 90: { + float textureWidth = _regionHeight / (_regionU2 - _regionU); + float textureHeight = _regionWidth / (_regionV2 - _regionV); + u -= (_regionOriginalHeight - _regionOffsetY - _regionHeight) / textureWidth; + v -= (_regionOriginalWidth - _regionOffsetX - _regionWidth) / textureHeight; + width = _regionOriginalHeight / textureWidth; + height = _regionOriginalWidth / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + _regionUVs[i + 1] * width; + _uvs[i + 1] = v + (1 - _regionUVs[i]) * height; + } + return; + } + case 180: { + float textureWidth = _regionWidth / (_regionU2 - _regionU); + float textureHeight = _regionHeight / (_regionV2 - _regionV); + u -= (_regionOriginalWidth - _regionOffsetX - _regionWidth) / textureWidth; + v -= _regionOffsetY / textureHeight; + width = _regionOriginalWidth / textureWidth; + height = _regionOriginalHeight / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + (1 - _regionUVs[i]) * width; + _uvs[i + 1] = v + (1 - _regionUVs[i + 1]) * height; + } + return; + } + case 270: { + float textureHeight = _regionHeight / (_regionV2 - _regionV); + float textureWidth = _regionWidth / (_regionU2 - _regionU); + u -= _regionOffsetY / textureWidth; + v -= _regionOffsetX / textureHeight; + width = _regionOriginalHeight / textureWidth; + height = _regionOriginalWidth / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + (1 - _regionUVs[i + 1]) * width; + _uvs[i + 1] = v + _regionUVs[i] * height; + } + return; + } + default: { + float textureWidth = _regionWidth / (_regionU2 - _regionU); + float textureHeight = _regionHeight / (_regionV2 - _regionV); + u -= _regionOffsetX / textureWidth; + v -= (_regionOriginalHeight - _regionOffsetY - _regionHeight) / textureHeight; + width = _regionOriginalWidth / textureWidth; + height = _regionOriginalHeight / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + _regionUVs[i] * width; + _uvs[i + 1] = v + _regionUVs[i + 1] * height; + } + } + } +} + +int MeshAttachment::getHullLength() { + return _hullLength; +} + +void MeshAttachment::setHullLength(int inValue) { + _hullLength = inValue; +} + +Vector &MeshAttachment::getRegionUVs() { + return _regionUVs; +} + +Vector &MeshAttachment::getUVs() { + return _uvs; +} + +Vector &MeshAttachment::getTriangles() { + return _triangles; +} + +const String &MeshAttachment::getPath() { + return _path; +} + +void MeshAttachment::setPath(const String &inValue) { + _path = inValue; +} + +float MeshAttachment::getRegionU() { + return _regionU; +} + +void MeshAttachment::setRegionU(float inValue) { + _regionU = inValue; +} + +float MeshAttachment::getRegionV() { + return _regionV; +} + +void MeshAttachment::setRegionV(float inValue) { + _regionV = inValue; +} + +float MeshAttachment::getRegionU2() { + return _regionU2; +} + +void MeshAttachment::setRegionU2(float inValue) { + _regionU2 = inValue; +} + +float MeshAttachment::getRegionV2() { + return _regionV2; +} + +void MeshAttachment::setRegionV2(float inValue) { + _regionV2 = inValue; +} + +bool MeshAttachment::getRegionRotate() { + return _regionRotate; +} + +void MeshAttachment::setRegionRotate(bool inValue) { + _regionRotate = inValue; +} + +int MeshAttachment::getRegionDegrees() { + return _regionDegrees; +} + +void MeshAttachment::setRegionDegrees(int inValue) { + _regionDegrees = inValue; +} + +float MeshAttachment::getRegionOffsetX() { + return _regionOffsetX; +} + +void MeshAttachment::setRegionOffsetX(float inValue) { + _regionOffsetX = inValue; +} + +float MeshAttachment::getRegionOffsetY() { + return _regionOffsetY; +} + +void MeshAttachment::setRegionOffsetY(float inValue) { + _regionOffsetY = inValue; +} + +float MeshAttachment::getRegionWidth() { + return _regionWidth; +} + +void MeshAttachment::setRegionWidth(float inValue) { + _regionWidth = inValue; +} + +float MeshAttachment::getRegionHeight() { + return _regionHeight; +} + +void MeshAttachment::setRegionHeight(float inValue) { + _regionHeight = inValue; +} + +float MeshAttachment::getRegionOriginalWidth() { + return _regionOriginalWidth; +} + +void MeshAttachment::setRegionOriginalWidth(float inValue) { + _regionOriginalWidth = inValue; +} + +float MeshAttachment::getRegionOriginalHeight() { + return _regionOriginalHeight; +} + +void MeshAttachment::setRegionOriginalHeight(float inValue) { + _regionOriginalHeight = inValue; +} + +MeshAttachment *MeshAttachment::getParentMesh() { + return _parentMesh; +} + +void MeshAttachment::setParentMesh(MeshAttachment *inValue) { + _parentMesh = inValue; + if (inValue != NULL) { + _bones.clearAndAddAll(inValue->_bones); + _vertices.clearAndAddAll(inValue->_vertices); + _worldVerticesLength = inValue->_worldVerticesLength; + _regionUVs.clearAndAddAll(inValue->_regionUVs); + _triangles.clearAndAddAll(inValue->_triangles); + _hullLength = inValue->_hullLength; + _edges.clearAndAddAll(inValue->_edges); + _width = inValue->_width; + _height = inValue->_height; + } +} + +Vector &MeshAttachment::getEdges() { + return _edges; +} + +float MeshAttachment::getWidth() { + return _width; +} + +void MeshAttachment::setWidth(float inValue) { + _width = inValue; +} + +float MeshAttachment::getHeight() { + return _height; +} + +void MeshAttachment::setHeight(float inValue) { + _height = inValue; +} + +spine::Color &MeshAttachment::getColor() { + return _color; +} + +Attachment* MeshAttachment::copy() { + if (_parentMesh) return newLinkedMesh(); + + MeshAttachment* copy = new (__FILE__, __LINE__) MeshAttachment(getName()); + copy->setRendererObject(getRendererObject()); + copy->_regionU = _regionU; + copy->_regionV = _regionV; + copy->_regionU2 = _regionU2; + copy->_regionV2 = _regionV2; + copy->_regionRotate = _regionRotate; + copy->_regionDegrees = _regionDegrees; + copy->_regionOffsetX = _regionOffsetX; + copy->_regionOffsetY = _regionOffsetY; + copy->_regionWidth = _regionWidth; + copy->_regionHeight = _regionHeight; + copy->_regionOriginalWidth = _regionOriginalWidth; + copy->_regionOriginalHeight = _regionOriginalHeight; + copy->_path = _path; + copy->_color.set(_color); + + copyTo(copy); + copy->_regionUVs.clearAndAddAll(_regionUVs); + copy->_uvs.clearAndAddAll(_uvs); + copy->_triangles.clearAndAddAll(_triangles); + copy->_hullLength = _hullLength; + + // Nonessential. + copy->_edges.clearAndAddAll(copy->_edges); + copy->_width = _width; + copy->_height = _height; + return copy; +} + +MeshAttachment* MeshAttachment::newLinkedMesh() { + MeshAttachment* copy = new (__FILE__, __LINE__) MeshAttachment(getName()); + copy->setRendererObject(getRendererObject()); + copy->_regionU = _regionU; + copy->_regionV = _regionV; + copy->_regionU2 = _regionU2; + copy->_regionV2 = _regionV2; + copy->_regionRotate = _regionRotate; + copy->_regionDegrees = _regionDegrees; + copy->_regionOffsetX = _regionOffsetX; + copy->_regionOffsetY = _regionOffsetY; + copy->_regionWidth = _regionWidth; + copy->_regionHeight = _regionHeight; + copy->_regionOriginalWidth = _regionOriginalWidth; + copy->_regionOriginalHeight = _regionOriginalHeight; + copy->_path = _path; + copy->_color.set(_color); + copy->_deformAttachment = this->_deformAttachment; + copy->setParentMesh(_parentMesh ? _parentMesh : this); + copy->updateUVs(); + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp new file mode 100644 index 0000000..ff74a4f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +using namespace spine; + +RTTI_IMPL(PathAttachment, VertexAttachment) + +PathAttachment::PathAttachment(const String &name) : VertexAttachment(name), _closed(false), _constantSpeed(false) { +} + +Vector &PathAttachment::getLengths() { + return _lengths; +} + +bool PathAttachment::isClosed() { + return _closed; +} + +void PathAttachment::setClosed(bool inValue) { + _closed = inValue; +} + +bool PathAttachment::isConstantSpeed() { + return _constantSpeed; +} + +void PathAttachment::setConstantSpeed(bool inValue) { + _constantSpeed = inValue; +} + +Attachment* PathAttachment::copy() { + PathAttachment* copy = new (__FILE__, __LINE__) PathAttachment(getName()); + copyTo(copy); + copy->_lengths.clearAndAddAll(_lengths); + copy->_closed = _closed; + copy->_constantSpeed = _constantSpeed; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp new file mode 100644 index 0000000..b28f80f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -0,0 +1,549 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraint, Updatable) + +const float PathConstraint::EPSILON = 0.00001f; +const int PathConstraint::NONE = -1; +const int PathConstraint::BEFORE = -2; +const int PathConstraint::AFTER = -3; + +PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : Updatable(), + _data(data), + _target(skeleton.findSlot( + data.getTarget()->getName())), + _position(data.getPosition()), + _spacing(data.getSpacing()), + _rotateMix(data.getRotateMix()), + _translateMix(data.getTranslateMix()), + _active(false) +{ + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); i++) { + BoneData *boneData = _data.getBones()[i]; + _bones.add(skeleton.findBone(boneData->getName())); + } + + _segments.setSize(10, 0); +} + +void PathConstraint::apply() { + update(); +} + +void PathConstraint::update() { + Attachment *baseAttachment = _target->getAttachment(); + if (baseAttachment == NULL || !baseAttachment->getRTTI().instanceOf(PathAttachment::rtti)) { + return; + } + + PathAttachment *attachment = static_cast(baseAttachment); + + float rotateMix = _rotateMix; + float translateMix = _translateMix; + bool translate = translateMix > 0; + bool rotate = rotateMix > 0; + if (!translate && !rotate) { + return; + } + + PathConstraintData &data = _data; + bool percentSpacing = data._spacingMode == SpacingMode_Percent; + RotateMode rotateMode = data._rotateMode; + bool tangents = rotateMode == RotateMode_Tangent, scale = rotateMode == RotateMode_ChainScale; + size_t boneCount = _bones.size(); + size_t spacesCount = tangents ? boneCount : boneCount + 1; + _spaces.setSize(spacesCount, 0); + float spacing = _spacing; + if (scale || !percentSpacing) { + if (scale) _lengths.setSize(boneCount, 0); + bool lengthSpacing = data._spacingMode == SpacingMode_Length; + + for (size_t i = 0, n = spacesCount - 1; i < n;) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + float setupLength = bone._data.getLength(); + if (setupLength < PathConstraint::EPSILON) { + if (scale) _lengths[i] = 0; + _spaces[++i] = 0; + } else if (percentSpacing) { + if (scale) { + float x = setupLength * bone._a, y = setupLength * bone._c; + float length = MathUtil::sqrt(x * x + y * y); + _lengths[i] = length; + } + _spaces[++i] = spacing; + } else { + float x = setupLength * bone._a; + float y = setupLength * bone._c; + float length = MathUtil::sqrt(x * x + y * y); + if (scale) { + _lengths[i] = length; + } + + _spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; + } + } + } else { + for (size_t i = 1; i < spacesCount; ++i) { + _spaces[i] = spacing; + } + } + + Vector& positions = computeWorldPositions(*attachment, spacesCount, tangents, + data.getPositionMode() == PositionMode_Percent, percentSpacing); + float boneX = positions[0]; + float boneY = positions[1]; + float offsetRotation = data.getOffsetRotation(); + bool tip; + if (offsetRotation == 0) { + tip = rotateMode == RotateMode_Chain; + } else { + tip = false; + Bone &p = _target->getBone(); + offsetRotation *= p.getA() * p.getD() - p.getB() * p.getC() > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; + } + + for (size_t i = 0, p = 3; i < boneCount; i++, p += 3) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + bone._worldX += (boneX - bone._worldX) * translateMix; + bone._worldY += (boneY - bone._worldY) * translateMix; + float x = positions[p]; + float y = positions[p + 1]; + float dx = x - boneX; + float dy = y - boneY; + if (scale) { + float length = _lengths[i]; + if (length >= PathConstraint::EPSILON) { + float s = (MathUtil::sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1; + bone._a *= s; + bone._c *= s; + } + } + + boneX = x; + boneY = y; + + if (rotate) { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d, r, cos, sin; + if (tangents) + r = positions[p - 1]; + else if (_spaces[i + 1] < PathConstraint::EPSILON) + r = positions[p + 2]; + else + r = MathUtil::atan2(dy, dx); + + r -= MathUtil::atan2(c, a); + + if (tip) { + cos = MathUtil::cos(r); + sin = MathUtil::sin(r); + float length = bone._data.getLength(); + boneX += (length * (cos * a - sin * c) - dx) * rotateMix; + boneY += (length * (sin * a + cos * c) - dy) * rotateMix; + } else + r += offsetRotation; + + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r *= rotateMix; + cos = MathUtil::cos(r); + sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + } + + bone._appliedValid = false; + } +} + +int PathConstraint::getOrder() { + return _data.getOrder(); +} + +float PathConstraint::getPosition() { + return _position; +} + +void PathConstraint::setPosition(float inValue) { + _position = inValue; +} + +float PathConstraint::getSpacing() { + return _spacing; +} + +void PathConstraint::setSpacing(float inValue) { + _spacing = inValue; +} + +float PathConstraint::getRotateMix() { + return _rotateMix; +} + +void PathConstraint::setRotateMix(float inValue) { + _rotateMix = inValue; +} + +float PathConstraint::getTranslateMix() { + return _translateMix; +} + +void PathConstraint::setTranslateMix(float inValue) { + _translateMix = inValue; +} + +Vector &PathConstraint::getBones() { + return _bones; +} + +Slot *PathConstraint::getTarget() { + return _target; +} + +void PathConstraint::setTarget(Slot *inValue) { + _target = inValue; +} + +PathConstraintData &PathConstraint::getData() { + return _data; +} + +Vector& +PathConstraint::computeWorldPositions(PathAttachment &path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing) { + Slot &target = *_target; + float position = _position; + _positions.setSize(spacesCount * 3 + 2, 0); + Vector &out = _positions; + Vector &world = _world; + bool closed = path.isClosed(); + int verticesLength = path.getWorldVerticesLength(); + int curveCount = verticesLength / 6; + int prevCurve = NONE; + + float pathLength; + if (!path.isConstantSpeed()) { + Vector &lengths = path.getLengths(); + curveCount -= closed ? 1 : 2; + pathLength = lengths[curveCount]; + if (percentPosition) position *= pathLength; + + if (percentSpacing) { + for (int i = 1; i < spacesCount; ++i) + _spaces[i] *= pathLength; + } + + world.setSize(8, 0); + for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + float space = _spaces[i]; + position += space; + float p = position; + + if (closed) { + p = MathUtil::fmod(p, pathLength); + if (p < 0) p += pathLength; + curve = 0; + } else if (p < 0) { + if (prevCurve != BEFORE) { + prevCurve = BEFORE; + path.computeWorldVertices(target, 2, 4, world, 0); + } + + addBeforePosition(p, world, 0, out, o); + + continue; + } else if (p > pathLength) { + if (prevCurve != AFTER) { + prevCurve = AFTER; + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0); + } + + addAfterPosition(p - pathLength, world, 0, out, o); + + continue; + } + + // Determine curve containing position. + for (;; curve++) { + float length = lengths[curve]; + if (p > length) continue; + + if (curve == 0) + p /= length; + else { + float prev = lengths[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + + if (curve != prevCurve) { + prevCurve = curve; + if (closed && curve == curveCount) { + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0); + path.computeWorldVertices(target, 0, 4, world, 4); + } else + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0); + } + + addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], + out, o, tangents || (i > 0 && space < EPSILON)); + } + return out; + } + + // World vertices. + if (closed) { + verticesLength += 2; + world.setSize(verticesLength, 0); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } else { + curveCount--; + verticesLength -= 4; + world.setSize(verticesLength, 0); + path.computeWorldVertices(target, 2, verticesLength, world, 0); + } + + // Curve lengths. + _curves.setSize(curveCount, 0); + pathLength = 0; + float x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy; + for (int i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875f; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875f; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375f; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375f; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f; + dfy = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + + if (percentPosition) + position *= pathLength; + else + position *= pathLength / path.getLengths()[curveCount - 1]; + + if (percentSpacing) { + for (int i = 1; i < spacesCount; ++i) + _spaces[i] *= pathLength; + } + + float curveLength = 0; + for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + float space = _spaces[i]; + position += space; + float p = position; + + if (closed) { + p = MathUtil::fmod(p, pathLength); + if (p < 0) p += pathLength; + curve = 0; + } else if (p < 0) { + addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength) { + addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + + // Determine curve containing position. + for (;; curve++) { + float length = _curves[curve]; + if (p > length) continue; + if (curve == 0) + p /= length; + else { + float prev = _curves[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + + // Curve segment lengths. + if (curve != prevCurve) { + prevCurve = curve; + int ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03f; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03f; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006f; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006f; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f; + dfy = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f; + curveLength = MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[9] = curveLength; + segment = 0; + } + + // Weight by segment length. + p *= curveLength; + for (;; segment++) { + float length = _segments[segment]; + if (p > length) continue; + if (segment == 0) + p /= length; + else { + float prev = _segments[segment - 1]; + p = segment + (p - prev) / (length - prev); + } + break; + } + addCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, + tangents || (i > 0 && space < EPSILON)); + } + + return out; +} + +void PathConstraint::addBeforePosition(float p, Vector &temp, int i, Vector &output, int o) { + float x1 = temp[i]; + float y1 = temp[i + 1]; + float dx = temp[i + 2] - x1; + float dy = temp[i + 3] - y1; + float r = MathUtil::atan2(dy, dx); + output[o] = x1 + p * MathUtil::cos(r); + output[o + 1] = y1 + p * MathUtil::sin(r); + output[o + 2] = r; +} + +void PathConstraint::addAfterPosition(float p, Vector &temp, int i, Vector &output, int o) { + float x1 = temp[i + 2]; + float y1 = temp[i + 3]; + float dx = x1 - temp[i]; + float dy = y1 - temp[i + 1]; + float r = MathUtil::atan2(dy, dx); + output[o] = x1 + p * MathUtil::cos(r); + output[o + 1] = y1 + p * MathUtil::sin(r); + output[o + 2] = r; +} + +void PathConstraint::addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, + float y2, Vector &output, int o, bool tangents +) { + if (p < EPSILON || MathUtil::isNan(p)) { + output[o] = x1; + output[o + 1] = y1; + output[o + 2] = MathUtil::atan2(cy1 - y1, cx1 - x1); + return; + } + + float tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + float ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + float x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + output[o] = x; + output[o + 1] = y; + if (tangents) { + if (p < 0.001) + output[o + 2] = MathUtil::atan2(cy1 - y1, cx1 - x1); + else + output[o + 2] = MathUtil::atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } +} + +bool PathConstraint::isActive() { + return _active; +} + +void PathConstraint::setActive(bool inValue) { + _active = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp new file mode 100644 index 0000000..55f69db --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -0,0 +1,130 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include + +using namespace spine; + +PathConstraintData::PathConstraintData(const String &name) : + ConstraintData(name), + _target(NULL), + _positionMode(PositionMode_Fixed), + _spacingMode(SpacingMode_Length), + _rotateMode(RotateMode_Tangent), + _offsetRotation(0), + _position(0), + _spacing(0), + _rotateMix(0), + _translateMix(0) { +} + +Vector &PathConstraintData::getBones() { + return _bones; +} + +SlotData *PathConstraintData::getTarget() { + return _target; +} + +void PathConstraintData::setTarget(SlotData *inValue) { + _target = inValue; +} + +PositionMode PathConstraintData::getPositionMode() { + return _positionMode; +} + +void PathConstraintData::setPositionMode(PositionMode inValue) { + _positionMode = inValue; +} + +SpacingMode PathConstraintData::getSpacingMode() { + return _spacingMode; +} + +void PathConstraintData::setSpacingMode(SpacingMode inValue) { + _spacingMode = inValue; +} + +RotateMode PathConstraintData::getRotateMode() { + return _rotateMode; +} + +void PathConstraintData::setRotateMode(RotateMode inValue) { + _rotateMode = inValue; +} + +float PathConstraintData::getOffsetRotation() { + return _offsetRotation; +} + +void PathConstraintData::setOffsetRotation(float inValue) { + _offsetRotation = inValue; +} + +float PathConstraintData::getPosition() { + return _position; +} + +void PathConstraintData::setPosition(float inValue) { + _position = inValue; +} + +float PathConstraintData::getSpacing() { + return _spacing; +} + +void PathConstraintData::setSpacing(float inValue) { + _spacing = inValue; +} + +float PathConstraintData::getRotateMix() { + return _rotateMix; +} + +void PathConstraintData::setRotateMix(float inValue) { + _rotateMix = inValue; +} + +float PathConstraintData::getTranslateMix() { + return _translateMix; +} + +void PathConstraintData::setTranslateMix(float inValue) { + _translateMix = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp new file mode 100644 index 0000000..5d4404e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -0,0 +1,126 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline) + +const int PathConstraintMixTimeline::ENTRIES = 3; +const int PathConstraintMixTimeline::PREV_TIME = -3; +const int PathConstraintMixTimeline::PREV_ROTATE = -2; +const int PathConstraintMixTimeline::PREV_TRANSLATE = -1; +const int PathConstraintMixTimeline::ROTATE = 1; +const int PathConstraintMixTimeline::TRANSLATE = 2; + +PathConstraintMixTimeline::PathConstraintMixTimeline(int frameCount) : CurveTimeline(frameCount), + _pathConstraintIndex(0) +{ + _frames.setSize(frameCount * ENTRIES, 0); +} + +void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction +) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; + PathConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._rotateMix = constraint._data._rotateMix; + constraint._translateMix = constraint._data._translateMix; + return; + case MixBlend_First: + constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha; + constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha; + return; + default: + return; + } + } + + float rotate, translate; + if (time >= _frames[_frames.size() - ENTRIES]) { + // Time is after last frame. + rotate = _frames[_frames.size() + PREV_ROTATE]; + translate = _frames[_frames.size() + PREV_TRANSLATE]; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + rotate = _frames[frame + PREV_ROTATE]; + translate = _frames[frame + PREV_TRANSLATE]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + rotate += (_frames[frame + ROTATE] - rotate) * percent; + translate += (_frames[frame + TRANSLATE] - translate) * percent; + } + + if (blend == MixBlend_Setup) { + constraint._rotateMix = constraint._data._rotateMix + (rotate - constraint._data._rotateMix) * alpha; + constraint._translateMix = + constraint._data._translateMix + (translate - constraint._data._translateMix) * alpha; + } else { + constraint._rotateMix += (rotate - constraint._rotateMix) * alpha; + constraint._translateMix += (translate - constraint._translateMix) * alpha; + } +} + +int PathConstraintMixTimeline::getPropertyId() { + return ((int) TimelineType_PathConstraintMix << 24) + _pathConstraintIndex; +} + +void PathConstraintMixTimeline::setFrame(int frameIndex, float time, float rotateMix, float translateMix) { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + ROTATE] = rotateMix; + _frames[frameIndex + TRANSLATE] = translateMix; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp new file mode 100644 index 0000000..f470e4f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -0,0 +1,116 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline) + +const int PathConstraintPositionTimeline::ENTRIES = 2; +const int PathConstraintPositionTimeline::PREV_TIME = -2; +const int PathConstraintPositionTimeline::PREV_VALUE = -1; +const int PathConstraintPositionTimeline::VALUE = 1; + +PathConstraintPositionTimeline::PathConstraintPositionTimeline(int frameCount) : CurveTimeline(frameCount), + _pathConstraintIndex(0) +{ + _frames.setSize(frameCount * ENTRIES, 0); +} + +PathConstraintPositionTimeline::~PathConstraintPositionTimeline() { +} + +void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction +) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; + PathConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._position = constraint._data._position; + return; + case MixBlend_First: + constraint._position += (constraint._data._position - constraint._position) * alpha; + return; + default: + return; + } + } + + float position; + if (time >= _frames[_frames.size() - ENTRIES]) { + // Time is after last frame. + position = _frames[_frames.size() + PREV_VALUE]; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + position = _frames[frame + PREV_VALUE]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + position += (_frames[frame + VALUE] - position) * percent; + } + if (blend == MixBlend_Setup) + constraint._position = constraint._data._position + (position - constraint._data._position) * alpha; + else + constraint._position += (position - constraint._position) * alpha; +} + +int PathConstraintPositionTimeline::getPropertyId() { + return ((int) TimelineType_PathConstraintPosition << 24) + _pathConstraintIndex; +} + +void PathConstraintPositionTimeline::setFrame(int frameIndex, float time, float value) { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + VALUE] = value; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp new file mode 100644 index 0000000..b84f46b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -0,0 +1,101 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline) + +PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(int frameCount) : PathConstraintPositionTimeline( + frameCount) { +} + +void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction +) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; + PathConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._spacing = constraint._data._spacing; + return; + case MixBlend_First: + constraint._spacing += (constraint._data._spacing - constraint._spacing) * alpha; + return; + default: + return; + } + } + + float spacing; + if (time >= _frames[_frames.size() - ENTRIES]) { + // Time is after last frame. + spacing = _frames[_frames.size() + PREV_VALUE]; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + spacing = _frames[frame + PREV_VALUE]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + spacing += (_frames[frame + VALUE] - spacing) * percent; + } + + if (blend == MixBlend_Setup) + constraint._spacing = constraint._data._spacing + (spacing - constraint._data._spacing) * alpha; + else + constraint._spacing += (spacing - constraint._spacing) * alpha; +} + +int PathConstraintSpacingTimeline::getPropertyId() { + return ((int) TimelineType_PathConstraintSpacing << 24) + _pathConstraintIndex; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp new file mode 100644 index 0000000..8c5ceb9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp @@ -0,0 +1,90 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +#include + +using namespace spine; + +RTTI_IMPL(PointAttachment, Attachment) + +PointAttachment::PointAttachment(const String &name) : Attachment(name), _x(0), _y(0), _rotation(0) { +} + +void PointAttachment::computeWorldPosition(Bone &bone, float &ox, float &oy) { + bone.localToWorld(_x, _y, ox, oy); +} + +float PointAttachment::computeWorldRotation(Bone &bone) { + float cos = MathUtil::cosDeg(_rotation); + float sin = MathUtil::sinDeg(_rotation); + float ix = cos * bone._a + sin * bone._b; + float iy = cos * bone._c + sin * bone._d; + + return MathUtil::atan2(iy, ix) * MathUtil::Rad_Deg; +} + +float PointAttachment::getX() { + return _x; +} + +void PointAttachment::setX(float inValue) { + _x = inValue; +} + +float PointAttachment::getY() { + return _y; +} + +void PointAttachment::setY(float inValue) { + _y = inValue; +} + +float PointAttachment::getRotation() { + return _rotation; +} + +void PointAttachment::setRotation(float inValue) { + _rotation = inValue; +} + +Attachment* PointAttachment::copy() { + PointAttachment* copy = new(__FILE__, __LINE__) PointAttachment(getName()); + copy->_x = _x; + copy->_y = _y; + copy->_rotation = _rotation; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/RTTI.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/RTTI.cpp new file mode 100644 index 0000000..4b91544 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/RTTI.cpp @@ -0,0 +1,60 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include + +using namespace spine; + +RTTI::RTTI(const char *className) : _className(className), _pBaseRTTI(NULL) { +} + +RTTI::RTTI(const char *className, const RTTI &baseRTTI) : _className(className), _pBaseRTTI(&baseRTTI) { +} + +const char *RTTI::getClassName() const { + return _className; +} + +bool RTTI::isExactly(const RTTI &rtti) const { + return !strcmp(this->_className, rtti._className); +} + +bool RTTI::instanceOf(const RTTI &rtti) const { + const RTTI *pCompare = this; + while (pCompare) { + if (!strcmp(pCompare->_className, rtti._className)) return true; + pCompare = pCompare->_pBaseRTTI; + } + return false; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp new file mode 100644 index 0000000..461a5a9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -0,0 +1,307 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +#include + +using namespace spine; + +RTTI_IMPL(RegionAttachment, Attachment) + +const int RegionAttachment::BLX = 0; +const int RegionAttachment::BLY = 1; +const int RegionAttachment::ULX = 2; +const int RegionAttachment::ULY = 3; +const int RegionAttachment::URX = 4; +const int RegionAttachment::URY = 5; +const int RegionAttachment::BRX = 6; +const int RegionAttachment::BRY = 7; + +RegionAttachment::RegionAttachment(const String &name) : Attachment(name), HasRendererObject(), + _x(0), + _y(0), + _rotation(0), + _scaleX(1), + _scaleY(1), + _width(0), + _height(0), + _regionOffsetX(0), + _regionOffsetY(0), + _regionWidth(0), + _regionHeight(0), + _regionOriginalWidth(0), + _regionOriginalHeight(0), + _path(), + _regionU(0), + _regionV(0), + _regionU2(0), + _regionV2(0), + _color(1, 1, 1, 1) +{ + _vertexOffset.setSize(NUM_UVS, 0); + _uvs.setSize(NUM_UVS, 0); +} + +void RegionAttachment::updateOffset() { + float regionScaleX = _width / _regionOriginalWidth * _scaleX; + float regionScaleY = _height / _regionOriginalHeight * _scaleY; + float localX = -_width / 2 * _scaleX + _regionOffsetX * regionScaleX; + float localY = -_height / 2 * _scaleY + _regionOffsetY * regionScaleY; + float localX2 = localX + _regionWidth * regionScaleX; + float localY2 = localY + _regionHeight * regionScaleY; + float cos = MathUtil::cosDeg(_rotation); + float sin = MathUtil::sinDeg(_rotation); + float localXCos = localX * cos + _x; + float localXSin = localX * sin; + float localYCos = localY * cos + _y; + float localYSin = localY * sin; + float localX2Cos = localX2 * cos + _x; + float localX2Sin = localX2 * sin; + float localY2Cos = localY2 * cos + _y; + float localY2Sin = localY2 * sin; + + _vertexOffset[BLX] = localXCos - localYSin; + _vertexOffset[BLY] = localYCos + localXSin; + _vertexOffset[ULX] = localXCos - localY2Sin; + _vertexOffset[ULY] = localY2Cos + localXSin; + _vertexOffset[URX] = localX2Cos - localY2Sin; + _vertexOffset[URY] = localY2Cos + localX2Sin; + _vertexOffset[BRX] = localX2Cos - localYSin; + _vertexOffset[BRY] = localYCos + localX2Sin; +} + +void RegionAttachment::setUVs(float u, float v, float u2, float v2, bool rotate) { + if (rotate) { + _uvs[URX] = u; + _uvs[URY] = v2; + _uvs[BRX] = u; + _uvs[BRY] = v; + _uvs[BLX] = u2; + _uvs[BLY] = v; + _uvs[ULX] = u2; + _uvs[ULY] = v2; + } else { + _uvs[ULX] = u; + _uvs[ULY] = v2; + _uvs[URX] = u; + _uvs[URY] = v; + _uvs[BRX] = u2; + _uvs[BRY] = v; + _uvs[BLX] = u2; + _uvs[BLY] = v2; + } +} + +void RegionAttachment::computeWorldVertices(Bone &bone, Vector &worldVertices, size_t offset, size_t stride) { + assert(worldVertices.size() >= (offset + 8)); + computeWorldVertices(bone, worldVertices.buffer(), offset, stride); +} + +void RegionAttachment::computeWorldVertices(Bone &bone, float* worldVertices, size_t offset, size_t stride) { + float x = bone.getWorldX(), y = bone.getWorldY(); + float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD(); + float offsetX, offsetY; + + offsetX = _vertexOffset[BRX]; + offsetY = _vertexOffset[BRY]; + worldVertices[offset] = offsetX * a + offsetY * b + x; // br + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = _vertexOffset[BLX]; + offsetY = _vertexOffset[BLY]; + worldVertices[offset] = offsetX * a + offsetY * b + x; // bl + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = _vertexOffset[ULX]; + offsetY = _vertexOffset[ULY]; + worldVertices[offset] = offsetX * a + offsetY * b + x; // ul + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = _vertexOffset[URX]; + offsetY = _vertexOffset[URY]; + worldVertices[offset] = offsetX * a + offsetY * b + x; // ur + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; +} + +float RegionAttachment::getX() { + return _x; +} + +void RegionAttachment::setX(float inValue) { + _x = inValue; +} + +float RegionAttachment::getY() { + return _y; +} + +void RegionAttachment::setY(float inValue) { + _y = inValue; +} + +float RegionAttachment::getRotation() { + return _rotation; +} + +void RegionAttachment::setRotation(float inValue) { + _rotation = inValue; +} + +float RegionAttachment::getScaleX() { + return _scaleX; +} + +void RegionAttachment::setScaleX(float inValue) { + _scaleX = inValue; +} + +float RegionAttachment::getScaleY() { + return _scaleY; +} + +void RegionAttachment::setScaleY(float inValue) { + _scaleY = inValue; +} + +float RegionAttachment::getWidth() { + return _width; +} + +void RegionAttachment::setWidth(float inValue) { + _width = inValue; +} + +float RegionAttachment::getHeight() { + return _height; +} + +void RegionAttachment::setHeight(float inValue) { + _height = inValue; +} + +const String &RegionAttachment::getPath() { + return _path; +} + +void RegionAttachment::setPath(const String &inValue) { + _path = inValue; +} + +float RegionAttachment::getRegionOffsetX() { + return _regionOffsetX; +} + +void RegionAttachment::setRegionOffsetX(float inValue) { + _regionOffsetX = inValue; +} + +float RegionAttachment::getRegionOffsetY() { + return _regionOffsetY; +} + +void RegionAttachment::setRegionOffsetY(float inValue) { + _regionOffsetY = inValue; +} + +float RegionAttachment::getRegionWidth() { + return _regionWidth; +} + +void RegionAttachment::setRegionWidth(float inValue) { + _regionWidth = inValue; +} + +float RegionAttachment::getRegionHeight() { + return _regionHeight; +} + +void RegionAttachment::setRegionHeight(float inValue) { + _regionHeight = inValue; +} + +float RegionAttachment::getRegionOriginalWidth() { + return _regionOriginalWidth; +} + +void RegionAttachment::setRegionOriginalWidth(float inValue) { + _regionOriginalWidth = inValue; +} + +float RegionAttachment::getRegionOriginalHeight() { + return _regionOriginalHeight; +} + +void RegionAttachment::setRegionOriginalHeight(float inValue) { + _regionOriginalHeight = inValue; +} + +Vector &RegionAttachment::getOffset() { + return _vertexOffset; +} + +Vector &RegionAttachment::getUVs() { + return _uvs; +} + +spine::Color &RegionAttachment::getColor() { + return _color; +} + +Attachment* RegionAttachment::copy() { + RegionAttachment* copy = new (__FILE__, __LINE__) RegionAttachment(getName()); + copy->_regionWidth = _regionWidth; + copy->_regionHeight = _regionHeight; + copy->_regionOffsetX = _regionOffsetX; + copy->_regionOffsetY = _regionOffsetY; + copy->_regionOriginalWidth = _regionOriginalWidth; + copy->_regionOriginalHeight = _regionOriginalHeight; + copy->setRendererObject(getRendererObject()); + copy->_path = _path; + copy->_x = _x; + copy->_y = _y; + copy->_scaleX = _scaleX; + copy->_scaleY = _scaleY; + copy->_rotation = _rotation; + copy->_width = _width; + copy->_height = _height; + copy->_uvs.clearAndAddAll(_uvs); + copy->_vertexOffset.clearAndAddAll(_vertexOffset); + copy->_color.set(_color); + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp new file mode 100644 index 0000000..0373639 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -0,0 +1,139 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(RotateTimeline, CurveTimeline) + +RotateTimeline::RotateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) { + _frames.setSize(frameCount << 1, 0); +} + +void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction +) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton.getBones()[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: { + bone->_rotation = bone->_data._rotation; + break; + } + case MixBlend_First: { + float r = bone->_data._rotation - bone->_rotation; + bone->_rotation += (r - (16384 - (int) (16384.499999999996 - r / 360)) * 360) * alpha; + break; + } + default: { + // TODO? + break; + } + } + return; + } + + if (time >= _frames[_frames.size() - ENTRIES]) { + float r = _frames[_frames.size() + PREV_ROTATION]; + switch (blend) { + case MixBlend_Setup: + bone->_rotation = bone->_data._rotation + r * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + r += bone->_data._rotation - bone->_rotation; + r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; + // Fall through. + case MixBlend_Add: + bone->_rotation += r * alpha; + } + return; + } + + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + float prevRotation = _frames[frame + PREV_ROTATION]; + float frameTime = _frames[frame]; + float percent = getCurvePercent((frame >> 1) - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + float r = _frames[frame + ROTATION] - prevRotation; + r = prevRotation + (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * percent; + switch (blend) { + case MixBlend_Setup: + bone->_rotation = bone->_data._rotation + (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + r += bone->_data._rotation - bone->_rotation; + // Fall through. + case MixBlend_Add: + bone->_rotation += (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * alpha; + } +} + +int RotateTimeline::getPropertyId() { + return ((int) TimelineType_Rotate << 24) + _boneIndex; +} + +void RotateTimeline::setFrame(int frameIndex, float time, float degrees) { + frameIndex <<= 1; + _frames[frameIndex] = time; + _frames[frameIndex + ROTATION] = degrees; +} + +int RotateTimeline::getBoneIndex() { + return _boneIndex; +} + +void RotateTimeline::setBoneIndex(int inValue) { + _boneIndex = inValue; +} + +Vector &RotateTimeline::getFrames() { + return _frames; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp new file mode 100644 index 0000000..f00e032 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -0,0 +1,153 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(ScaleTimeline, TranslateTimeline) + +ScaleTimeline::ScaleTimeline(int frameCount) : TranslateTimeline(frameCount) { +} + +void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction +) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + Bone *boneP = skeleton._bones[_boneIndex]; + Bone &bone = *boneP; + + if (!bone._active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone._scaleX = bone._data._scaleX; + bone._scaleY = bone._data._scaleY; + return; + case MixBlend_First: + bone._scaleX += (bone._data._scaleX - bone._scaleX) * alpha; + bone._scaleY += (bone._data._scaleY - bone._scaleY) * alpha; + default: {} + } + return; + } + + float x, y; + if (time >= _frames[_frames.size() - ENTRIES]) { + // Time is after last frame. + x = _frames[_frames.size() + PREV_X] * bone._data._scaleX; + y = _frames[_frames.size() + PREV_Y] * bone._data._scaleY; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + x = _frames[frame + PREV_X]; + y = _frames[frame + PREV_Y]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + x = (x + (_frames[frame + X] - x) * percent) * bone._data._scaleX; + y = (y + (_frames[frame + Y] - y) * percent) * bone._data._scaleY; + } + + if (alpha == 1) { + if (blend == MixBlend_Add) { + bone._scaleX += x - bone._data._scaleX; + bone._scaleY += y - bone._data._scaleY; + } else { + bone._scaleX = x; + bone._scaleY = y; + } + } else { + // Mixing out uses sign of setup or current pose, else use sign of key. + float bx, by; + if (direction == MixDirection_Out) { + switch (blend) { + case MixBlend_Setup: + bx = bone._data._scaleX; + by = bone._data._scaleY; + bone._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; + bone._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bx = bone._scaleX; + by = bone._scaleY; + bone._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; + bone._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; + break; + case MixBlend_Add: + bx = bone._scaleX; + by = bone._scaleY; + bone._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bone._data._scaleX) * alpha; + bone._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - bone._data._scaleY) * alpha; + } + } else { + switch (blend) { + case MixBlend_Setup: + bx = MathUtil::abs(bone._data._scaleX) * MathUtil::sign(x); + by = MathUtil::abs(bone._data._scaleY) * MathUtil::sign(y); + bone._scaleX = bx + (x - bx) * alpha; + bone._scaleY = by + (y - by) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bx = MathUtil::abs(bone._scaleX) * MathUtil::sign(x); + by = MathUtil::abs(bone._scaleY) * MathUtil::sign(y); + bone._scaleX = bx + (x - bx) * alpha; + bone._scaleY = by + (y - by) * alpha; + break; + case MixBlend_Add: + bx = MathUtil::sign(x); + by = MathUtil::sign(y); + bone._scaleX = MathUtil::abs(bone._scaleX) * bx + (x - MathUtil::abs(bone._data._scaleX) * bx) * alpha; + bone._scaleY = MathUtil::abs(bone._scaleY) * by + (y - MathUtil::abs(bone._data._scaleY) * by) * alpha; + } + } + } +} + +int ScaleTimeline::getPropertyId() { + return ((int) TimelineType_Scale << 24) + _boneIndex; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp new file mode 100644 index 0000000..046d057 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -0,0 +1,112 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(ShearTimeline, TranslateTimeline) + +ShearTimeline::ShearTimeline(int frameCount) : TranslateTimeline(frameCount) { +} + +void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction +) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *boneP = skeleton._bones[_boneIndex]; + Bone &bone = *boneP; + if (!bone._active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone._shearX = bone._data._shearX; + bone._shearY = bone._data._shearY; + return; + case MixBlend_First: + bone._shearX += (bone._data._shearX - bone._shearX) * alpha; + bone._shearY += (bone._data._shearY - bone._shearY) * alpha; + default: {} + } + return; + } + + float x, y; + if (time >= _frames[_frames.size() - ENTRIES]) { + // Time is after last frame. + x = _frames[_frames.size() + PREV_X]; + y = _frames[_frames.size() + PREV_Y]; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + x = _frames[frame + PREV_X]; + y = _frames[frame + PREV_Y]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + x = x + (_frames[frame + X] - x) * percent; + y = y + (_frames[frame + Y] - y) * percent; + } + + switch (blend) { + case MixBlend_Setup: + bone._shearX = bone._data._shearX + x * alpha; + bone._shearY = bone._data._shearY + y * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone._shearX += (bone._data._shearX + x - bone._shearX) * alpha; + bone._shearY += (bone._data._shearY + y - bone._shearY) * alpha; + break; + case MixBlend_Add: + bone._shearX += x * alpha; + bone._shearY += y * alpha; + } +} + +int ShearTimeline::getPropertyId() { + return ((int) TimelineType_Shear << 24) + _boneIndex; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Skeleton.cpp new file mode 100644 index 0000000..f9927da --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -0,0 +1,679 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace spine; + +Skeleton::Skeleton(SkeletonData *skeletonData) : + _data(skeletonData), + _skin(NULL), + _color(1, 1, 1, 1), + _time(0), + _scaleX(1), + _scaleY(1), + _x(0), + _y(0) { + _bones.ensureCapacity(_data->getBones().size()); + for (size_t i = 0; i < _data->getBones().size(); ++i) { + BoneData *data = _data->getBones()[i]; + + Bone *bone; + if (data->getParent() == NULL) { + bone = new(__FILE__, __LINE__) Bone(*data, *this, NULL); + } else { + Bone *parent = _bones[data->getParent()->getIndex()]; + bone = new(__FILE__, __LINE__) Bone(*data, *this, parent); + parent->getChildren().add(bone); + } + + _bones.add(bone); + } + + _slots.ensureCapacity(_data->getSlots().size()); + _drawOrder.ensureCapacity(_data->getSlots().size()); + for (size_t i = 0; i < _data->getSlots().size(); ++i) { + SlotData *data = _data->getSlots()[i]; + + Bone *bone = _bones[data->getBoneData().getIndex()]; + Slot *slot = new(__FILE__, __LINE__) Slot(*data, *bone); + + _slots.add(slot); + _drawOrder.add(slot); + } + + _ikConstraints.ensureCapacity(_data->getIkConstraints().size()); + for (size_t i = 0; i < _data->getIkConstraints().size(); ++i) { + IkConstraintData *data = _data->getIkConstraints()[i]; + + IkConstraint *constraint = new(__FILE__, __LINE__) IkConstraint(*data, *this); + + _ikConstraints.add(constraint); + } + + _transformConstraints.ensureCapacity(_data->getTransformConstraints().size()); + for (size_t i = 0; i < _data->getTransformConstraints().size(); ++i) { + TransformConstraintData *data = _data->getTransformConstraints()[i]; + + TransformConstraint *constraint = new(__FILE__, __LINE__) TransformConstraint(*data, *this); + + _transformConstraints.add(constraint); + } + + _pathConstraints.ensureCapacity(_data->getPathConstraints().size()); + for (size_t i = 0; i < _data->getPathConstraints().size(); ++i) { + PathConstraintData *data = _data->getPathConstraints()[i]; + + PathConstraint *constraint = new(__FILE__, __LINE__) PathConstraint(*data, *this); + + _pathConstraints.add(constraint); + } + + updateCache(); +} + +Skeleton::~Skeleton() { + ContainerUtil::cleanUpVectorOfPointers(_bones); + ContainerUtil::cleanUpVectorOfPointers(_slots); + ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); + ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); + ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); +} + +void Skeleton::updateCache() { + _updateCache.clear(); + _updateCacheReset.clear(); + + for (size_t i = 0, n = _bones.size(); i < n; ++i) { + Bone* bone = _bones[i]; + bone->_sorted = bone->_data.isSkinRequired(); + bone->_active = !bone->_sorted; + } + + if (_skin) { + Vector& skinBones = _skin->getBones(); + for (size_t i = 0, n = skinBones.size(); i < n; i++) { + Bone* bone = _bones[skinBones[i]->getIndex()]; + do { + bone->_sorted = false; + bone->_active = true; + bone = bone->_parent; + } while (bone); + } + } + + size_t ikCount = _ikConstraints.size(); + size_t transformCount = _transformConstraints.size(); + size_t pathCount = _pathConstraints.size(); + + size_t constraintCount = ikCount + transformCount + pathCount; + + size_t i = 0; + continue_outer: + for (; i < constraintCount; ++i) { + for (size_t ii = 0; ii < ikCount; ++ii) { + IkConstraint *constraint = _ikConstraints[ii]; + if (constraint->getData().getOrder() == i) { + sortIkConstraint(constraint); + i++; + goto continue_outer; + } + } + + for (size_t ii = 0; ii < transformCount; ++ii) { + TransformConstraint *constraint = _transformConstraints[ii]; + if (constraint->getData().getOrder() == i) { + sortTransformConstraint(constraint); + i++; + goto continue_outer; + } + } + + for (size_t ii = 0; ii < pathCount; ++ii) { + PathConstraint *constraint = _pathConstraints[ii]; + if (constraint->getData().getOrder() == i) { + sortPathConstraint(constraint); + i++; + goto continue_outer; + } + } + } + + size_t n = _bones.size(); + for (i = 0; i < n; ++i) { + sortBone(_bones[i]); + } +} + +void Skeleton::printUpdateCache() { + for (size_t i = 0; i < _updateCache.size(); i++) { + Updatable *updatable = _updateCache[i]; + if (updatable->getRTTI().isExactly(Bone::rtti)) { + printf("bone %s\n", ((Bone *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(TransformConstraint::rtti)) { + printf("transform constraint %s\n", ((TransformConstraint *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(IkConstraint::rtti)) { + printf("ik constraint %s\n", ((IkConstraint *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(PathConstraint::rtti)) { + printf("path constraint %s\n", ((PathConstraint *) updatable)->getData().getName().buffer()); + } + } +} + +void Skeleton::updateWorldTransform() { + for (size_t i = 0, n = _updateCacheReset.size(); i < n; ++i) { + Bone *boneP = _updateCacheReset[i]; + Bone &bone = *boneP; + bone._ax = bone._x; + bone._ay = bone._y; + bone._arotation = bone._rotation; + bone._ascaleX = bone._scaleX; + bone._ascaleY = bone._scaleY; + bone._ashearX = bone._shearX; + bone._ashearY = bone._shearY; + bone._appliedValid = true; + } + + for (size_t i = 0, n = _updateCache.size(); i < n; ++i) { + _updateCache[i]->update(); + } +} + +void Skeleton::setToSetupPose() { + setBonesToSetupPose(); + setSlotsToSetupPose(); +} + +void Skeleton::setBonesToSetupPose() { + for (size_t i = 0, n = _bones.size(); i < n; ++i) { + _bones[i]->setToSetupPose(); + } + + for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) { + IkConstraint *constraintP = _ikConstraints[i]; + IkConstraint &constraint = *constraintP; + + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + constraint._mix = constraint._data._mix; + constraint._softness = constraint._data._softness; + } + + for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) { + TransformConstraint *constraintP = _transformConstraints[i]; + TransformConstraint &constraint = *constraintP; + TransformConstraintData &constraintData = constraint._data; + + constraint._rotateMix = constraintData._rotateMix; + constraint._translateMix = constraintData._translateMix; + constraint._scaleMix = constraintData._scaleMix; + constraint._shearMix = constraintData._shearMix; + } + + for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) { + PathConstraint *constraintP = _pathConstraints[i]; + PathConstraint &constraint = *constraintP; + PathConstraintData &constraintData = constraint._data; + + constraint._position = constraintData._position; + constraint._spacing = constraintData._spacing; + constraint._rotateMix = constraintData._rotateMix; + constraint._translateMix = constraintData._translateMix; + } +} + +void Skeleton::setSlotsToSetupPose() { + _drawOrder.clear(); + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + _drawOrder.add(_slots[i]); + } + + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + _slots[i]->setToSetupPose(); + } +} + +Bone *Skeleton::findBone(const String &boneName) { + return ContainerUtil::findWithDataName(_bones, boneName); +} + +int Skeleton::findBoneIndex(const String &boneName) { + return ContainerUtil::findIndexWithDataName(_bones, boneName); +} + +Slot *Skeleton::findSlot(const String &slotName) { + return ContainerUtil::findWithDataName(_slots, slotName); +} + +int Skeleton::findSlotIndex(const String &slotName) { + return ContainerUtil::findIndexWithDataName(_slots, slotName); +} + +void Skeleton::setSkin(const String &skinName) { + Skin *foundSkin = skinName.isEmpty() ? NULL : _data->findSkin(skinName); + setSkin(foundSkin); +} + +void Skeleton::setSkin(Skin *newSkin) { + if (_skin == newSkin) return; + if (newSkin != NULL) { + if (_skin != NULL) { + Skeleton &thisRef = *this; + newSkin->attachAll(thisRef, *_skin); + } else { + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + Slot *slotP = _slots[i]; + Slot &slot = *slotP; + const String &name = slot._data.getAttachmentName(); + if (name.length() > 0) { + Attachment *attachment = newSkin->getAttachment(i, name); + if (attachment != NULL) { + slot.setAttachment(attachment); + } + } + } + } + } + + _skin = newSkin; + updateCache(); +} + +Attachment *Skeleton::getAttachment(const String &slotName, const String &attachmentName) { + return getAttachment(_data->findSlotIndex(slotName), attachmentName); +} + +Attachment *Skeleton::getAttachment(int slotIndex, const String &attachmentName) { + if (attachmentName.isEmpty()) return NULL; + + if (_skin != NULL) { + Attachment *attachment = _skin->getAttachment(slotIndex, attachmentName); + if (attachment != NULL) { + return attachment; + } + } + + return _data->getDefaultSkin() != NULL ? _data->getDefaultSkin()->getAttachment(slotIndex, attachmentName) : NULL; +} + +void Skeleton::setAttachment(const String &slotName, const String &attachmentName) { + assert(slotName.length() > 0); + + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + Slot *slot = _slots[i]; + if (slot->_data.getName() == slotName) { + Attachment *attachment = NULL; + if (attachmentName.length() > 0) { + attachment = getAttachment(i, attachmentName); + + assert(attachment != NULL); + } + + slot->setAttachment(attachment); + + return; + } + } + + printf("Slot not found: %s", slotName.buffer()); + + assert(false); +} + +IkConstraint *Skeleton::findIkConstraint(const String &constraintName) { + assert(constraintName.length() > 0); + + for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) { + IkConstraint *ikConstraint = _ikConstraints[i]; + if (ikConstraint->_data.getName() == constraintName) { + return ikConstraint; + } + } + return NULL; +} + +TransformConstraint *Skeleton::findTransformConstraint(const String &constraintName) { + assert(constraintName.length() > 0); + + for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) { + TransformConstraint *transformConstraint = _transformConstraints[i]; + if (transformConstraint->_data.getName() == constraintName) { + return transformConstraint; + } + } + + return NULL; +} + +PathConstraint *Skeleton::findPathConstraint(const String &constraintName) { + assert(constraintName.length() > 0); + + for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) { + PathConstraint *constraint = _pathConstraints[i]; + if (constraint->_data.getName() == constraintName) { + return constraint; + } + } + + return NULL; +} + +void Skeleton::update(float delta) { + _time += delta; +} + +void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector &outVertexBuffer) { + float minX = FLT_MAX; + float minY = FLT_MAX; + float maxX = FLT_MIN; + float maxY = FLT_MIN; + + for (size_t i = 0; i < _drawOrder.size(); ++i) { + Slot *slot = _drawOrder[i]; + if (!slot->_bone._active) continue; + size_t verticesLength = 0; + Attachment *attachment = slot->getAttachment(); + + if (attachment != NULL && attachment->getRTTI().instanceOf(RegionAttachment::rtti)) { + RegionAttachment *regionAttachment = static_cast(attachment); + + verticesLength = 8; + if (outVertexBuffer.size() < 8) { + outVertexBuffer.setSize(8, 0); + } + regionAttachment->computeWorldVertices(slot->getBone(), outVertexBuffer, 0); + } else if (attachment != NULL && attachment->getRTTI().instanceOf(MeshAttachment::rtti)) { + MeshAttachment *mesh = static_cast(attachment); + + verticesLength = mesh->getWorldVerticesLength(); + if (outVertexBuffer.size() < verticesLength) { + outVertexBuffer.setSize(verticesLength, 0); + } + + mesh->computeWorldVertices(*slot, 0, verticesLength, outVertexBuffer, 0); + } + + for (size_t ii = 0; ii < verticesLength; ii += 2) { + float vx = outVertexBuffer[ii]; + float vy = outVertexBuffer[ii + 1]; + + minX = MathUtil::min(minX, vx); + minY = MathUtil::min(minY, vy); + maxX = MathUtil::max(maxX, vx); + maxY = MathUtil::max(maxY, vy); + } + } + + outX = minX; + outY = minY; + outWidth = maxX - minX; + outHeight = maxY - minY; +} + +Bone *Skeleton::getRootBone() { + return _bones.size() == 0 ? NULL : _bones[0]; +} + +SkeletonData *Skeleton::getData() { + return _data; +} + +Vector &Skeleton::getBones() { + return _bones; +} + +Vector &Skeleton::getUpdateCacheList() { + return _updateCache; +} + +Vector &Skeleton::getSlots() { + return _slots; +} + +Vector &Skeleton::getDrawOrder() { + return _drawOrder; +} + +Vector &Skeleton::getIkConstraints() { + return _ikConstraints; +} + +Vector &Skeleton::getPathConstraints() { + return _pathConstraints; +} + +Vector &Skeleton::getTransformConstraints() { + return _transformConstraints; +} + +Skin *Skeleton::getSkin() { + return _skin; +} + +Color &Skeleton::getColor() { + return _color; +} + +float Skeleton::getTime() { + return _time; +} + +void Skeleton::setTime(float inValue) { + _time = inValue; +} + +void Skeleton::setPosition(float x, float y) { + _x = x; + _y = y; +} + +float Skeleton::getX() { + return _x; +} + +void Skeleton::setX(float inValue) { + _x = inValue; +} + +float Skeleton::getY() { + return _y; +} + +void Skeleton::setY(float inValue) { + _y = inValue; +} + +float Skeleton::getScaleX() { + return _scaleX; +} + +void Skeleton::setScaleX(float inValue) { + _scaleX = inValue; +} + +float Skeleton::getScaleY() { + return _scaleY * (Bone::isYDown() ? -1 : 1); +} + +void Skeleton::setScaleY(float inValue) { + _scaleY = inValue; +} + +void Skeleton::sortIkConstraint(IkConstraint *constraint) { + constraint->_active = constraint->_target->_active && (!constraint->_data.isSkinRequired() || (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) return; + + Bone *target = constraint->getTarget(); + sortBone(target); + + Vector &constrained = constraint->getBones(); + Bone *parent = constrained[0]; + sortBone(parent); + + if (constrained.size() > 1) { + Bone *child = constrained[constrained.size() - 1]; + if (!_updateCache.contains(child)) _updateCacheReset.add(child); + } + + _updateCache.add(constraint); + + sortReset(parent->getChildren()); + constrained[constrained.size() - 1]->_sorted = true; +} + +void Skeleton::sortPathConstraint(PathConstraint *constraint) { + constraint->_active = constraint->_target->_bone._active && (!constraint->_data.isSkinRequired() || (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) return; + + Slot *slot = constraint->getTarget(); + int slotIndex = slot->getData().getIndex(); + Bone &slotBone = slot->getBone(); + if (_skin != NULL) sortPathConstraintAttachment(_skin, slotIndex, slotBone); + if (_data->_defaultSkin != NULL && _data->_defaultSkin != _skin) + sortPathConstraintAttachment(_data->_defaultSkin, slotIndex, slotBone); + for (size_t ii = 0, nn = _data->_skins.size(); ii < nn; ii++) + sortPathConstraintAttachment(_data->_skins[ii], slotIndex, slotBone); + + Attachment *attachment = slot->getAttachment(); + if (attachment != NULL && attachment->getRTTI().instanceOf(PathAttachment::rtti)) + sortPathConstraintAttachment(attachment, slotBone); + + Vector &constrained = constraint->getBones(); + size_t boneCount = constrained.size(); + for (size_t i = 0; i < boneCount; ++i) { + sortBone(constrained[i]); + } + + _updateCache.add(constraint); + + for (size_t i = 0; i < boneCount; i++) + sortReset(constrained[i]->getChildren()); + for (size_t i = 0; i < boneCount; i++) + constrained[i]->_sorted = true; +} + +void Skeleton::sortTransformConstraint(TransformConstraint *constraint) { + constraint->_active = constraint->_target->_active && (!constraint->_data.isSkinRequired() || (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) return; + + sortBone(constraint->getTarget()); + + Vector &constrained = constraint->getBones(); + size_t boneCount = constrained.size(); + if (constraint->_data.isLocal()) { + for (size_t i = 0; i < boneCount; i++) { + Bone *child = constrained[i]; + sortBone(child->getParent()); + if (!_updateCache.contains(child)) _updateCacheReset.add(child); + } + } else { + for (size_t i = 0; i < boneCount; ++i) { + sortBone(constrained[i]); + } + } + + _updateCache.add(constraint); + + for (size_t i = 0; i < boneCount; ++i) + sortReset(constrained[i]->getChildren()); + for (size_t i = 0; i < boneCount; ++i) + constrained[i]->_sorted = true; +} + +void Skeleton::sortPathConstraintAttachment(Skin *skin, size_t slotIndex, Bone &slotBone) { + Skin::AttachmentMap::Entries attachments = skin->getAttachments(); + + while (attachments.hasNext()) { + Skin::AttachmentMap::Entry entry = attachments.next(); + if (entry._slotIndex == slotIndex) { + Attachment *value = entry._attachment; + sortPathConstraintAttachment(value, slotBone); + } + } +} + +void Skeleton::sortPathConstraintAttachment(Attachment *attachment, Bone &slotBone) { + if (attachment == NULL || !attachment->getRTTI().instanceOf(PathAttachment::rtti)) return; + Vector &pathBones = static_cast(attachment)->getBones(); + if (pathBones.size() == 0) + sortBone(&slotBone); + else { + for (size_t i = 0, n = pathBones.size(); i < n;) { + size_t nn = pathBones[i++]; + nn += i; + while (i < nn) { + sortBone(_bones[pathBones[i++]]); + } + } + } +} + +void Skeleton::sortBone(Bone *bone) { + if (bone->_sorted) return; + Bone *parent = bone->_parent; + if (parent != NULL) sortBone(parent); + bone->_sorted = true; + _updateCache.add(bone); +} + +void Skeleton::sortReset(Vector &bones) { + for (size_t i = 0, n = bones.size(); i < n; ++i) { + Bone *bone = bones[i]; + if (!bone->_active) continue; + if (bone->_sorted) sortReset(bone->getChildren()); + bone->_sorted = false; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp new file mode 100644 index 0000000..f33f2d1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -0,0 +1,1084 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +const int SkeletonBinary::BONE_ROTATE = 0; +const int SkeletonBinary::BONE_TRANSLATE = 1; +const int SkeletonBinary::BONE_SCALE = 2; +const int SkeletonBinary::BONE_SHEAR = 3; + +const int SkeletonBinary::SLOT_ATTACHMENT = 0; +const int SkeletonBinary::SLOT_COLOR = 1; +const int SkeletonBinary::SLOT_TWO_COLOR = 2; + +const int SkeletonBinary::PATH_POSITION = 0; +const int SkeletonBinary::PATH_SPACING = 1; +const int SkeletonBinary::PATH_MIX = 2; + +const int SkeletonBinary::CURVE_LINEAR = 0; +const int SkeletonBinary::CURVE_STEPPED = 1; +const int SkeletonBinary::CURVE_BEZIER = 2; + +SkeletonBinary::SkeletonBinary(Atlas *atlasArray) : _attachmentLoader( + new(__FILE__, __LINE__) AtlasAttachmentLoader(atlasArray)), _error(), _scale(1), _ownsLoader(true) { + +} + +SkeletonBinary::SkeletonBinary(AttachmentLoader* attachmentLoader, bool ownsLoader) : _attachmentLoader(attachmentLoader), _error(), +_scale(1), _ownsLoader(ownsLoader) +{ + assert(_attachmentLoader != NULL); +} + +SkeletonBinary::~SkeletonBinary() { + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + if (_ownsLoader) delete _attachmentLoader; +} + +SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, const int length) { + _error = ""; + + bool nonessential; + SkeletonData *skeletonData; + + DataInput *input = new(__FILE__, __LINE__) DataInput(); + input->cursor = binary; + input->end = binary + length; + + _linkedMeshes.clear(); + + skeletonData = new(__FILE__, __LINE__) SkeletonData(); + + char *skeletonData_hash = readString(input); + skeletonData->_hash.own(skeletonData_hash); + + char *skeletonData_version = readString(input); + skeletonData->_version.own(skeletonData_version); + if ("3.8.75" == skeletonData->_version) { + delete input; + delete skeletonData; + setError("Unsupported skeleton data, please export with a newer version of Spine.", ""); + return NULL; + } + + skeletonData->_x = readFloat(input); + skeletonData->_y = readFloat(input); + skeletonData->_width = readFloat(input); + skeletonData->_height = readFloat(input); + + nonessential = readBoolean(input); + + if (nonessential) { + /* Skip images path, audio path & fps */ + skeletonData->_fps = readFloat(input); + skeletonData->_imagesPath.own(readString(input)); + skeletonData->_audioPath.own(readString(input)); + } + + int numStrings = readVarint(input, true); + for (int i = 0; i < numStrings; i++) + skeletonData->_strings.add(readString(input)); + + /* Bones. */ + int numBones = readVarint(input, true); + skeletonData->_bones.setSize(numBones, 0); + for (int i = 0; i < numBones; ++i) { + const char *name = readString(input); + BoneData *parent = i == 0 ? 0 : skeletonData->_bones[readVarint(input, true)]; + BoneData *data = new(__FILE__, __LINE__) BoneData(i, String(name, true), parent); + data->_rotation = readFloat(input); + data->_x = readFloat(input) * _scale; + data->_y = readFloat(input) * _scale; + data->_scaleX = readFloat(input); + data->_scaleY = readFloat(input); + data->_shearX = readFloat(input); + data->_shearY = readFloat(input); + data->_length = readFloat(input) * _scale; + data->_transformMode = static_cast(readVarint(input, true)); + data->_skinRequired = readBoolean(input); + if (nonessential) readInt(input); /* Skip bone color. */ + skeletonData->_bones[i] = data; + } + + /* Slots. */ + int slotsCount = readVarint(input, true); + skeletonData->_slots.setSize(slotsCount, 0); + for (int i = 0; i < slotsCount; ++i) { + const char *slotName = readString(input); + BoneData *boneData = skeletonData->_bones[readVarint(input, true)]; + SlotData *slotData = new(__FILE__, __LINE__) SlotData(i, String(slotName, true), *boneData); + + readColor(input, slotData->getColor()); + unsigned char r = readByte(input); + unsigned char g = readByte(input); + unsigned char b = readByte(input); + unsigned char a = readByte(input); + if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) { + slotData->getDarkColor().set(r / 255.0f, g / 255.0f, b / 255.0f, 1); + slotData->setHasDarkColor(true); + } + slotData->_attachmentName = readStringRef(input, skeletonData); + slotData->_blendMode = static_cast(readVarint(input, true)); + skeletonData->_slots[i] = slotData; + } + + /* IK constraints. */ + int ikConstraintsCount = readVarint(input, true); + skeletonData->_ikConstraints.setSize(ikConstraintsCount, 0); + for (int i = 0; i < ikConstraintsCount; ++i) { + const char *name = readString(input); + IkConstraintData *data = new(__FILE__, __LINE__) IkConstraintData(String(name, true)); + data->setOrder(readVarint(input, true)); + data->setSkinRequired(readBoolean(input)); + int bonesCount = readVarint(input, true); + data->_bones.setSize(bonesCount, 0); + for (int ii = 0; ii < bonesCount; ++ii) + data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; + data->_target = skeletonData->_bones[readVarint(input, true)]; + data->_mix = readFloat(input); + data->_softness = readFloat(input) * _scale; + data->_bendDirection = readSByte(input); + data->_compress = readBoolean(input); + data->_stretch = readBoolean(input); + data->_uniform = readBoolean(input); + skeletonData->_ikConstraints[i] = data; + } + + /* Transform constraints. */ + int transformConstraintsCount = readVarint(input, true); + skeletonData->_transformConstraints.setSize(transformConstraintsCount, 0); + for (int i = 0; i < transformConstraintsCount; ++i) { + const char *name = readString(input); + TransformConstraintData *data = new(__FILE__, __LINE__) TransformConstraintData(String(name, true)); + data->setOrder(readVarint(input, true)); + data->setSkinRequired(readBoolean(input)); + int bonesCount = readVarint(input, true); + data->_bones.setSize(bonesCount, 0); + for (int ii = 0; ii < bonesCount; ++ii) + data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; + data->_target = skeletonData->_bones[readVarint(input, true)]; + data->_local = readBoolean(input); + data->_relative = readBoolean(input); + data->_offsetRotation = readFloat(input); + data->_offsetX = readFloat(input) * _scale; + data->_offsetY = readFloat(input) * _scale; + data->_offsetScaleX = readFloat(input); + data->_offsetScaleY = readFloat(input); + data->_offsetShearY = readFloat(input); + data->_rotateMix = readFloat(input); + data->_translateMix = readFloat(input); + data->_scaleMix = readFloat(input); + data->_shearMix = readFloat(input); + skeletonData->_transformConstraints[i] = data; + } + + /* Path constraints */ + int pathConstraintsCount = readVarint(input, true); + skeletonData->_pathConstraints.setSize(pathConstraintsCount, 0); + for (int i = 0; i < pathConstraintsCount; ++i) { + const char *name = readString(input); + PathConstraintData *data = new(__FILE__, __LINE__) PathConstraintData(String(name, true)); + data->setOrder(readVarint(input, true)); + data->setSkinRequired(readBoolean(input)); + int bonesCount = readVarint(input, true); + data->_bones.setSize(bonesCount, 0); + for (int ii = 0; ii < bonesCount; ++ii) + data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; + data->_target = skeletonData->_slots[readVarint(input, true)]; + data->_positionMode = static_cast(readVarint(input, true)); + data->_spacingMode = static_cast(readVarint(input, true)); + data->_rotateMode = static_cast(readVarint(input, true)); + data->_offsetRotation = readFloat(input); + data->_position = readFloat(input); + if (data->_positionMode == PositionMode_Fixed) data->_position *= _scale; + data->_spacing = readFloat(input); + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) + data->_spacing *= _scale; + data->_rotateMix = readFloat(input); + data->_translateMix = readFloat(input); + skeletonData->_pathConstraints[i] = data; + } + + /* Default skin. */ + Skin* defaultSkin = readSkin(input, true, skeletonData, nonessential); + if (defaultSkin) { + skeletonData->_defaultSkin = defaultSkin; + skeletonData->_skins.add(defaultSkin); + } + + if (!getError().isEmpty()) { + delete input; + delete skeletonData; + return NULL; + } + + /* Skins. */ + for (size_t i = 0, n = (size_t)readVarint(input, true); i < n; ++i) { + Skin* skin = readSkin(input, false, skeletonData, nonessential); + if (skin) + skeletonData->_skins.add(skin); + else { + delete input; + delete skeletonData; + return NULL; + } + } + + /* Linked meshes. */ + for (int i = 0, n = _linkedMeshes.size(); i < n; ++i) { + LinkedMesh *linkedMesh = _linkedMeshes[i]; + Skin *skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin( + linkedMesh->_skin); + if (skin == NULL) { + delete input; + delete skeletonData; + setError("Skin not found: ", linkedMesh->_skin.buffer()); + return NULL; + } + Attachment *parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); + if (parent == NULL) { + delete input; + delete skeletonData; + setError("Parent mesh not found: ", linkedMesh->_parent.buffer()); + return NULL; + } + linkedMesh->_mesh->_deformAttachment = linkedMesh->_inheritDeform ? static_cast(parent) : linkedMesh->_mesh; + linkedMesh->_mesh->setParentMesh(static_cast(parent)); + linkedMesh->_mesh->updateUVs(); + _attachmentLoader->configureAttachment(linkedMesh->_mesh); + } + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + /* Events. */ + int eventsCount = readVarint(input, true); + skeletonData->_events.setSize(eventsCount, 0); + for (int i = 0; i < eventsCount; ++i) { + const char *name = readStringRef(input, skeletonData); + EventData *eventData = new(__FILE__, __LINE__) EventData(String(name)); + eventData->_intValue = readVarint(input, false); + eventData->_floatValue = readFloat(input); + eventData->_stringValue.own(readString(input)); + eventData->_audioPath.own(readString(input)); // skip audio path + if (!eventData->_audioPath.isEmpty()) { + eventData->_volume = readFloat(input); + eventData->_balance = readFloat(input); + } + skeletonData->_events[i] = eventData; + } + + /* Animations. */ + int animationsCount = readVarint(input, true); + skeletonData->_animations.setSize(animationsCount, 0); + for (int i = 0; i < animationsCount; ++i) { + String name(readString(input), true); + Animation *animation = readAnimation(name, input, skeletonData); + if (!animation) { + delete input; + delete skeletonData; + return NULL; + } + skeletonData->_animations[i] = animation; + } + + delete input; + return skeletonData; +} + +SkeletonData *SkeletonBinary::readSkeletonDataFile(const String &path) { + int length; + SkeletonData *skeletonData; + const char *binary = SpineExtension::readFile(path.buffer(), &length); + if (length == 0 || !binary) { + setError("Unable to read skeleton file: ", path.buffer()); + return NULL; + } + skeletonData = readSkeletonData((unsigned char *) binary, length); + SpineExtension::free(binary, __FILE__, __LINE__); + return skeletonData; +} + +void SkeletonBinary::setError(const char *value1, const char *value2) { + char message[256]; + int length; + strcpy(message, value1); + length = (int) strlen(value1); + if (value2) strncat(message + length, value2, 255 - length); + _error = String(message); +} + +char *SkeletonBinary::readString(DataInput *input) { + int length = readVarint(input, true); + char *string; + if (length == 0) return NULL; + string = SpineExtension::alloc(length, __FILE__, __LINE__); + memcpy(string, input->cursor, length - 1); + input->cursor += length - 1; + string[length - 1] = '\0'; + return string; +} + +char* SkeletonBinary::readStringRef(DataInput* input, SkeletonData* skeletonData) { + int index = readVarint(input, true); + return index == 0 ? NULL : skeletonData->_strings[index - 1]; +} + +float SkeletonBinary::readFloat(DataInput *input) { + union { + int intValue; + float floatValue; + } intToFloat; + intToFloat.intValue = readInt(input); + return intToFloat.floatValue; +} + +unsigned char SkeletonBinary::readByte(DataInput *input) { + return *input->cursor++; +} + +signed char SkeletonBinary::readSByte(DataInput *input) { + return (signed char) readByte(input); +} + +bool SkeletonBinary::readBoolean(DataInput *input) { + return readByte(input) != 0; +} + +int SkeletonBinary::readInt(DataInput *input) { + int result = readByte(input); + result <<= 8; + result |= readByte(input); + result <<= 8; + result |= readByte(input); + result <<= 8; + result |= readByte(input); + return result; +} + +void SkeletonBinary::readColor(DataInput *input, Color &color) { + color.r = readByte(input) / 255.0f; + color.g = readByte(input) / 255.0f; + color.b = readByte(input) / 255.0f; + color.a = readByte(input) / 255.0f; +} + +int SkeletonBinary::readVarint(DataInput *input, bool optimizePositive) { + unsigned char b = readByte(input); + int value = b & 0x7F; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 7; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 14; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 21; + if (b & 0x80) value |= (readByte(input) & 0x7F) << 28; + } + } + } + if (!optimizePositive) value = (((unsigned int) value >> 1) ^ -(value & 1)); + return value; +} + +Skin *SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential) { + Skin *skin; + int slotCount = 0; + if (defaultSkin) { + slotCount = readVarint(input, true); + if (slotCount == 0) return NULL; + skin = new(__FILE__, __LINE__) Skin("default"); + } else { + skin = new(__FILE__, __LINE__) Skin(readStringRef(input, skeletonData)); + for (int i = 0, n = readVarint(input, true); i < n; i++) + skin->getBones().add(skeletonData->_bones[readVarint(input, true)]); + + for (int i = 0, n = readVarint(input, true); i < n; i++) + skin->getConstraints().add(skeletonData->_ikConstraints[readVarint(input, true)]); + + for (int i = 0, n = readVarint(input, true); i < n; i++) + skin->getConstraints().add(skeletonData->_transformConstraints[readVarint(input, true)]); + + for (int i = 0, n = readVarint(input, true); i < n; i++) + skin->getConstraints().add(skeletonData->_pathConstraints[readVarint(input, true)]); + slotCount = readVarint(input, true); + } + + for (int i = 0; i < slotCount; ++i) { + int slotIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + String name(readStringRef(input, skeletonData)); + Attachment *attachment = readAttachment(input, skin, slotIndex, name, skeletonData, nonessential); + if (attachment) + skin->setAttachment(slotIndex, String(name), attachment); + else { + delete skin; + return nullptr; + } + } + } + return skin; +} + +Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName, + SkeletonData *skeletonData, bool nonessential +) { + String name(readStringRef(input, skeletonData)); + if (name.isEmpty()) name = attachmentName; + + AttachmentType type = static_cast(readByte(input)); + switch (type) { + case AttachmentType_Region: { + String path(readStringRef(input, skeletonData)); + if (path.isEmpty()) path = name; + RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path)); + if (!region) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + region->_path = path; + region->_rotation = readFloat(input); + region->_x = readFloat(input) * _scale; + region->_y = readFloat(input) * _scale; + region->_scaleX = readFloat(input); + region->_scaleY = readFloat(input); + region->_width = readFloat(input) * _scale; + region->_height = readFloat(input) * _scale; + readColor(input, region->getColor()); + region->updateOffset(); + _attachmentLoader->configureAttachment(region); + return region; + } + case AttachmentType_Boundingbox: { + int vertexCount = readVarint(input, true); + BoundingBoxAttachment *box = _attachmentLoader->newBoundingBoxAttachment(*skin, String(name)); + if (!box) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + readVertices(input, static_cast(box), vertexCount); + if (nonessential) { + /* Skip color. */ + readInt(input); + } + _attachmentLoader->configureAttachment(box); + return box; + } + case AttachmentType_Mesh: { + int vertexCount; + MeshAttachment *mesh; + String path(readStringRef(input, skeletonData)); + if (path.isEmpty()) path = name; + + mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path)); + if (!mesh) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + mesh->_path = path; + readColor(input, mesh->getColor()); + vertexCount = readVarint(input, true); + readFloatArray(input, vertexCount << 1, 1, mesh->getRegionUVs()); + readShortArray(input, mesh->getTriangles()); + readVertices(input, static_cast(mesh), vertexCount); + mesh->updateUVs(); + mesh->_hullLength = readVarint(input, true) << 1; + if (nonessential) { + readShortArray(input, mesh->getEdges()); + mesh->_width = readFloat(input) * _scale; + mesh->_height = readFloat(input) * _scale; + } else { + mesh->_width = 0; + mesh->_height = 0; + } + _attachmentLoader->configureAttachment(mesh); + return mesh; + } + case AttachmentType_Linkedmesh: { + String path(readStringRef(input, skeletonData)); + if (path.isEmpty()) path = name; + + MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path)); + if (!mesh) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + mesh->_path = path; + readColor(input, mesh->getColor()); + String skinName(readStringRef(input, skeletonData)); + String parent(readStringRef(input, skeletonData)); + bool inheritDeform = readBoolean(input); + if (nonessential) { + mesh->_width = readFloat(input) * _scale; + mesh->_height = readFloat(input) * _scale; + } + + LinkedMesh *linkedMesh = new(__FILE__, __LINE__) LinkedMesh(mesh, String(skinName), slotIndex, + String(parent), inheritDeform); + _linkedMeshes.add(linkedMesh); + return mesh; + } + case AttachmentType_Path: { + PathAttachment* path = _attachmentLoader->newPathAttachment(*skin, String(name)); + if (!path) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + path->_closed = readBoolean(input); + path->_constantSpeed = readBoolean(input); + int vertexCount = readVarint(input, true); + readVertices(input, static_cast(path), vertexCount); + int lengthsLength = vertexCount / 3; + path->_lengths.setSize(lengthsLength, 0); + for (int i = 0; i < lengthsLength; ++i) { + path->_lengths[i] = readFloat(input) * _scale; + } + if (nonessential) { + /* Skip color. */ + readInt(input); + } + _attachmentLoader->configureAttachment(path); + return path; + } + case AttachmentType_Point: { + PointAttachment* point = _attachmentLoader->newPointAttachment(*skin, String(name)); + if (!point) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + point->_rotation = readFloat(input); + point->_x = readFloat(input) * _scale; + point->_y = readFloat(input) * _scale; + + if (nonessential) { + /* Skip color. */ + readInt(input); + } + _attachmentLoader->configureAttachment(point); + return point; + } + case AttachmentType_Clipping: { + int endSlotIndex = readVarint(input, true); + int vertexCount = readVarint(input, true); + ClippingAttachment* clip = _attachmentLoader->newClippingAttachment(*skin, name); + if (!clip) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + readVertices(input, static_cast(clip), vertexCount); + clip->_endSlot = skeletonData->_slots[endSlotIndex]; + if (nonessential) { + /* Skip color. */ + readInt(input); + } + _attachmentLoader->configureAttachment(clip); + return clip; + } + } + return nullptr; +} + +void SkeletonBinary::readVertices(DataInput *input, VertexAttachment *attachment, int vertexCount) { + float scale = _scale; + int verticesLength = vertexCount << 1; + attachment->setWorldVerticesLength(vertexCount << 1); + + if (!readBoolean(input)) { + readFloatArray(input, verticesLength, scale, attachment->getVertices()); + return; + } + + Vector &vertices = attachment->getVertices(); + Vector &bones = attachment->getBones(); + vertices.ensureCapacity(verticesLength * 3 * 3); + bones.ensureCapacity(verticesLength * 3); + + for (int i = 0; i < vertexCount; ++i) { + int boneCount = readVarint(input, true); + bones.add(boneCount); + for (int ii = 0; ii < boneCount; ++ii) { + bones.add(readVarint(input, true)); + vertices.add(readFloat(input) * scale); + vertices.add(readFloat(input) * scale); + vertices.add(readFloat(input)); + } + } +} + +void SkeletonBinary::readFloatArray(DataInput *input, int n, float scale, Vector &array) { + array.setSize(n, 0); + + int i; + if (scale == 1) { + for (i = 0; i < n; ++i) { + array[i] = readFloat(input); + } + } else { + for (i = 0; i < n; ++i) { + array[i] = readFloat(input) * scale; + } + } +} + +void SkeletonBinary::readShortArray(DataInput *input, Vector &array) { + int n = readVarint(input, true); + array.setSize(n, 0); + + int i; + for (i = 0; i < n; ++i) { + array[i] = readByte(input) << 8; + array[i] |= readByte(input); + } +} + +Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, SkeletonData *skeletonData) { + Vector timelines; + float scale = _scale; + float duration = 0; + + // Slot timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int slotIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + unsigned char timelineType = readByte(input); + int frameCount = readVarint(input, true); + switch (timelineType) { + case SLOT_ATTACHMENT: { + AttachmentTimeline *timeline = new(__FILE__, __LINE__) AttachmentTimeline(frameCount); + timeline->_slotIndex = slotIndex; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + String attachmentName(readStringRef(input, skeletonData)); + timeline->setFrame(frameIndex, time, attachmentName); + } + timelines.add(timeline); + duration = MathUtil::max(duration, timeline->_frames[frameCount - 1]); + break; + } + case SLOT_COLOR: { + ColorTimeline *timeline = new(__FILE__, __LINE__) ColorTimeline(frameCount); + timeline->_slotIndex = slotIndex; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + int color = readInt(input); + float r = ((color & 0xff000000) >> 24) / 255.0f; + float g = ((color & 0x00ff0000) >> 16) / 255.0f; + float b = ((color & 0x0000ff00) >> 8) / 255.0f; + float a = ((color & 0x000000ff)) / 255.0f; + timeline->setFrame(frameIndex, time, r, g, b, a); + if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline); + } + timelines.add(timeline); + duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * ColorTimeline::ENTRIES]); + break; + } + case SLOT_TWO_COLOR: { + TwoColorTimeline *timeline = new(__FILE__, __LINE__) TwoColorTimeline(frameCount); + timeline->_slotIndex = slotIndex; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + int color = readInt(input); + float r = ((color & 0xff000000) >> 24) / 255.0f; + float g = ((color & 0x00ff0000) >> 16) / 255.0f; + float b = ((color & 0x0000ff00) >> 8) / 255.0f; + float a = ((color & 0x000000ff)) / 255.0f; + int color2 = readInt(input); // 0x00rrggbb + float r2 = ((color2 & 0x00ff0000) >> 16) / 255.0f; + float g2 = ((color2 & 0x0000ff00) >> 8) / 255.0f; + float b2 = ((color2 & 0x000000ff)) / 255.0f; + + timeline->setFrame(frameIndex, time, r, g, b, a, r2, g2, b2); + if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline); + } + timelines.add(timeline); + duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * TwoColorTimeline::ENTRIES]); + break; + } + default: { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Invalid timeline type for a slot: ", skeletonData->_slots[slotIndex]->_name.buffer()); + return NULL; + } + } + } + } + + // Bone timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int boneIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + unsigned char timelineType = readByte(input); + int frameCount = readVarint(input, true); + switch (timelineType) { + case BONE_ROTATE: { + RotateTimeline *timeline = new(__FILE__, __LINE__) RotateTimeline(frameCount); + timeline->_boneIndex = boneIndex; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float degrees = readFloat(input); + timeline->setFrame(frameIndex, time, degrees); + if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline); + } + timelines.add(timeline); + duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * RotateTimeline::ENTRIES]); + break; + } + case BONE_TRANSLATE: + case BONE_SCALE: + case BONE_SHEAR: { + TranslateTimeline *timeline; + float timelineScale = 1; + if (timelineType == BONE_SCALE) { + timeline = new(__FILE__, __LINE__) ScaleTimeline(frameCount); + } else if (timelineType == BONE_SHEAR) { + timeline = new(__FILE__, __LINE__) ShearTimeline(frameCount); + } else { + timeline = new(__FILE__, __LINE__) TranslateTimeline(frameCount); + timelineScale = scale; + } + timeline->_boneIndex = boneIndex; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float x = readFloat(input) * timelineScale; + float y = readFloat(input) * timelineScale; + timeline->setFrame(frameIndex, time, x, y); + if (frameIndex < frameCount - 1) { + readCurve(input, frameIndex, timeline); + } + } + timelines.add(timeline); + duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * TranslateTimeline::ENTRIES]); + break; + } + default: { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Invalid timeline type for a bone: ", skeletonData->_bones[boneIndex]->_name.buffer()); + return NULL; + } + } + } + } + + // IK timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int index = readVarint(input, true); + int frameCount = readVarint(input, true); + IkConstraintTimeline *timeline = new(__FILE__, __LINE__) IkConstraintTimeline(frameCount); + timeline->_ikConstraintIndex = index; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float mix = readFloat(input); + float softness = readFloat(input) * _scale; + signed char bendDirection = readSByte(input); + bool compress = readBoolean(input); + bool stretch = readBoolean(input); + timeline->setFrame(frameIndex, time, mix, softness, bendDirection, compress, stretch); + if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline); + } + timelines.add(timeline); + duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * IkConstraintTimeline::ENTRIES]); + } + + // Transform constraint timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int index = readVarint(input, true); + int frameCount = readVarint(input, true); + TransformConstraintTimeline *timeline = new(__FILE__, __LINE__) TransformConstraintTimeline(frameCount); + timeline->_transformConstraintIndex = index; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float rotateMix = readFloat(input); + float translateMix = readFloat(input); + float scaleMix = readFloat(input); + float shearMix = readFloat(input); + timeline->setFrame(frameIndex, time, rotateMix, translateMix, scaleMix, shearMix); + if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline); + } + timelines.add(timeline); + duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * TransformConstraintTimeline::ENTRIES]); + } + + // Path constraint timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int index = readVarint(input, true); + PathConstraintData *data = skeletonData->_pathConstraints[index]; + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + int timelineType = readSByte(input); + int frameCount = readVarint(input, true); + switch (timelineType) { + case PATH_POSITION: + case PATH_SPACING: { + PathConstraintPositionTimeline *timeline; + float timelineScale = 1; + if (timelineType == PATH_SPACING) { + timeline = new(__FILE__, __LINE__) PathConstraintSpacingTimeline(frameCount); + + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) timelineScale = scale; + } else { + timeline = new(__FILE__, __LINE__) PathConstraintPositionTimeline(frameCount); + + if (data->_positionMode == PositionMode_Fixed) timelineScale = scale; + } + timeline->_pathConstraintIndex = index; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float value = readFloat(input) * timelineScale; + timeline->setFrame(frameIndex, time, value); + if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline); + } + timelines.add(timeline); + duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * PathConstraintPositionTimeline::ENTRIES]); + break; + } + case PATH_MIX: { + PathConstraintMixTimeline *timeline = new(__FILE__, __LINE__) PathConstraintMixTimeline(frameCount); + + timeline->_pathConstraintIndex = index; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float rotateMix = readFloat(input); + float translateMix = readFloat(input); + timeline->setFrame(frameIndex, time, rotateMix, translateMix); + if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline); + } + timelines.add(timeline); + duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * PathConstraintMixTimeline::ENTRIES]); + break; + } + } + } + } + + // Deform timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + Skin *skin = skeletonData->_skins[readVarint(input, true)]; + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + int slotIndex = readVarint(input, true); + for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) { + const char *attachmentName = readStringRef(input, skeletonData); + Attachment *baseAttachment = skin->getAttachment(slotIndex, String(attachmentName)); + + if (!baseAttachment) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Attachment not found: ", attachmentName); + return NULL; + } + + VertexAttachment *attachment = static_cast(baseAttachment); + + bool weighted = attachment->_bones.size() > 0; + Vector &vertices = attachment->_vertices; + size_t deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size(); + + size_t frameCount = (size_t)readVarint(input, true); + + DeformTimeline *timeline = new(__FILE__, __LINE__) DeformTimeline(frameCount); + timeline->_slotIndex = slotIndex; + timeline->_attachment = attachment; + + for (size_t frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + Vector deform; + size_t end = (size_t)readVarint(input, true); + if (end == 0) { + if (weighted) { + deform.setSize(deformLength, 0); + for (size_t iiii = 0; iiii < deformLength; ++iiii) + deform[iiii] = 0; + } else { + deform.clearAndAddAll(vertices); + } + } else { + deform.setSize(deformLength, 0); + size_t start = (size_t)readVarint(input, true); + end += start; + if (scale == 1) { + for (size_t v = start; v < end; ++v) + deform[v] = readFloat(input); + } else { + for (size_t v = start; v < end; ++v) + deform[v] = readFloat(input) * scale; + } + + if (!weighted) { + for (size_t v = 0, vn = deform.size(); v < vn; ++v) + deform[v] += vertices[v]; + } + } + + timeline->setFrame(frameIndex, time, deform); + if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline); + } + + timelines.add(timeline); + duration = MathUtil::max(duration, timeline->_frames[frameCount - 1]); + } + } + } + + // Draw order timeline. + size_t drawOrderCount = (size_t)readVarint(input, true); + if (drawOrderCount > 0) { + DrawOrderTimeline *timeline = new(__FILE__, __LINE__) DrawOrderTimeline(drawOrderCount); + + size_t slotCount = skeletonData->_slots.size(); + for (size_t i = 0; i < drawOrderCount; ++i) { + float time = readFloat(input); + size_t offsetCount = (size_t)readVarint(input, true); + + Vector drawOrder; + drawOrder.setSize(slotCount, 0); + for (int ii = (int)slotCount - 1; ii >= 0; --ii) + drawOrder[ii] = -1; + + Vector unchanged; + unchanged.setSize(slotCount - offsetCount, 0); + size_t originalIndex = 0, unchangedIndex = 0; + for (size_t ii = 0; ii < offsetCount; ++ii) { + size_t slotIndex = (size_t)readVarint(input, true); + // Collect unchanged items. + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + // Set changed items. + size_t index = originalIndex; + drawOrder[index + (size_t)readVarint(input, true)] = originalIndex++; + } + + // Collect remaining unchanged items. + while (originalIndex < slotCount) { + unchanged[unchangedIndex++] = originalIndex++; + } + + // Fill in unchanged items. + for (int ii = (int)slotCount - 1; ii >= 0; --ii) + if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; + timeline->setFrame(i, time, drawOrder); + } + timelines.add(timeline); + duration = MathUtil::max(duration, timeline->_frames[drawOrderCount - 1]); + } + + // Event timeline. + int eventCount = readVarint(input, true); + if (eventCount > 0) { + EventTimeline *timeline = new(__FILE__, __LINE__) EventTimeline(eventCount); + + for (int i = 0; i < eventCount; ++i) { + float time = readFloat(input); + EventData *eventData = skeletonData->_events[readVarint(input, true)]; + Event *event = new(__FILE__, __LINE__) Event(time, *eventData); + + event->_intValue = readVarint(input, false); + event->_floatValue = readFloat(input); + bool freeString = readBoolean(input); + const char *event_stringValue = freeString ? readString(input) : eventData->_stringValue.buffer(); + event->_stringValue = String(event_stringValue); + if (freeString) SpineExtension::free(event_stringValue, __FILE__, __LINE__); + + if (!eventData->_audioPath.isEmpty()) { + event->_volume = readFloat(input); + event->_balance = readFloat(input); + } + timeline->setFrame(i, event); + } + + timelines.add(timeline); + duration = MathUtil::max(duration, timeline->_frames[eventCount - 1]); + } + + return new(__FILE__, __LINE__) Animation(String(name), timelines, duration); +} + +void SkeletonBinary::readCurve(DataInput *input, int frameIndex, CurveTimeline *timeline) { + switch (readByte(input)) { + case CURVE_STEPPED: { + timeline->setStepped(frameIndex); + break; + } + case CURVE_BEZIER: { + float cx1 = readFloat(input); + float cy1 = readFloat(input); + float cx2 = readFloat(input); + float cy2 = readFloat(input); + timeline->setCurve(frameIndex, cx1, cy1, cx2, cy2); + break; + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp new file mode 100644 index 0000000..520c323 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp @@ -0,0 +1,222 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include + +#include + +#include + +using namespace spine; + +SkeletonBounds::SkeletonBounds() : _minX(0), _minY(0), _maxX(0), _maxY(0) { +} + +SkeletonBounds::~SkeletonBounds() { + for (size_t i = 0, n = _polygons.size(); i < n; i++) + _polygonPool.free(_polygons[i]); + _polygons.clear(); +} + +void SkeletonBounds::update(Skeleton &skeleton, bool updateAabb) { + Vector &slots = skeleton.getSlots(); + size_t slotCount = slots.size(); + + _boundingBoxes.clear(); + for (size_t i = 0, n = _polygons.size(); i < n; ++i) { + _polygonPool.free(_polygons[i]); + } + + _polygons.clear(); + + for (size_t i = 0; i < slotCount; i++) { + Slot *slot = slots[i]; + if (!slot->getBone().isActive()) continue; + + Attachment *attachment = slot->getAttachment(); + if (attachment == NULL || !attachment->getRTTI().instanceOf(BoundingBoxAttachment::rtti)) continue; + BoundingBoxAttachment *boundingBox = static_cast(attachment); + _boundingBoxes.add(boundingBox); + + spine::Polygon *polygonP = _polygonPool.obtain(); + _polygons.add(polygonP); + + Polygon &polygon = *polygonP; + + size_t count = boundingBox->getWorldVerticesLength(); + polygon._count = count; + if (polygon._vertices.size() < count) { + polygon._vertices.setSize(count, 0); + } + boundingBox->computeWorldVertices(*slot, polygon._vertices); + } + + if (updateAabb) + aabbCompute(); + else { + _minX = FLT_MIN; + _minY = FLT_MIN; + _maxX = FLT_MAX; + _maxY = FLT_MAX; + } +} + +bool SkeletonBounds::aabbcontainsPoint(float x, float y) { + return x >= _minX && x <= _maxX && y >= _minY && y <= _maxY; +} + +bool SkeletonBounds::aabbintersectsSegment(float x1, float y1, float x2, float y2) { + float minX = _minX; + float minY = _minY; + float maxX = _maxX; + float maxY = _maxY; + + if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || + (y1 >= maxY && y2 >= maxY)) { + return false; + } + + float m = (y2 - y1) / (x2 - x1); + float y = m * (minX - x1) + y1; + if (y > minY && y < maxY) return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) return true; + float x = (minY - y1) / m + x1; + if (x > minX && x < maxX) return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) return true; + return false; +} + +bool SkeletonBounds::aabbIntersectsSkeleton(SkeletonBounds bounds) { + return _minX < bounds._maxX && _maxX > bounds._minX && _minY < bounds._maxY && _maxY > bounds._minY; +} + +bool SkeletonBounds::containsPoint(spine::Polygon *polygon, float x, float y) { + Vector &vertices = polygon->_vertices; + int nn = polygon->_count; + + int prevIndex = nn - 2; + bool inside = false; + for (int ii = 0; ii < nn; ii += 2) { + float vertexY = vertices[ii + 1]; + float prevY = vertices[prevIndex + 1]; + if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { + float vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) { + inside = !inside; + } + } + prevIndex = ii; + } + return inside; +} + +BoundingBoxAttachment *SkeletonBounds::containsPoint(float x, float y) { + for (size_t i = 0, n = _polygons.size(); i < n; ++i) + if (containsPoint(_polygons[i], x, y)) return _boundingBoxes[i]; + return NULL; +} + +BoundingBoxAttachment *SkeletonBounds::intersectsSegment(float x1, float y1, float x2, float y2) { + for (size_t i = 0, n = _polygons.size(); i < n; ++i) + if (intersectsSegment(_polygons[i], x1, y1, x2, y2)) return _boundingBoxes[i]; + return NULL; +} + +bool SkeletonBounds::intersectsSegment(spine::Polygon *polygon, float x1, float y1, float x2, float y2) { + Vector &vertices = polygon->_vertices; + size_t nn = polygon->_count; + + float width12 = x1 - x2, height12 = y1 - y2; + float det1 = x1 * y2 - y1 * x2; + float x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (size_t ii = 0; ii < nn; ii += 2) { + float x4 = vertices[ii], y4 = vertices[ii + 1]; + float det2 = x3 * y4 - y3 * x4; + float width34 = x3 - x4, height34 = y3 - y4; + float det3 = width12 * height34 - height12 * width34; + float x = (det1 * width34 - width12 * det2) / det3; + if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { + float y = (det1 * height34 - height12 * det2) / det3; + if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) { + return true; + } + } + x3 = x4; + y3 = y4; + } + + return false; +} + +spine::Polygon *SkeletonBounds::getPolygon(BoundingBoxAttachment *attachment) { + int index = _boundingBoxes.indexOf(attachment); + return index == -1 ? NULL : _polygons[index]; +} + +float SkeletonBounds::getWidth() { + return _maxX - _minX; +} + +float SkeletonBounds::getHeight() { + return _maxY - _minY; +} + +void SkeletonBounds::aabbCompute() { + float minX = FLT_MIN; + float minY = FLT_MIN; + float maxX = FLT_MAX; + float maxY = FLT_MAX; + + for (size_t i = 0, n = _polygons.size(); i < n; ++i) { + spine::Polygon *polygon = _polygons[i]; + Vector &vertices = polygon->_vertices; + for (int ii = 0, nn = polygon->_count; ii < nn; ii += 2) { + float x = vertices[ii]; + float y = vertices[ii + 1]; + minX = MathUtil::min(minX, x); + minY = MathUtil::min(minY, y); + maxX = MathUtil::max(maxX, x); + maxY = MathUtil::max(maxY, y); + } + } + _minX = minX; + _minY = minY; + _maxX = maxX; + _maxY = maxY; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp new file mode 100644 index 0000000..fa5bb48 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp @@ -0,0 +1,328 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +using namespace spine; + +SkeletonClipping::SkeletonClipping() : _clipAttachment(NULL) { + _clipOutput.ensureCapacity(128); + _clippedVertices.ensureCapacity(128); + _clippedTriangles.ensureCapacity(128); + _clippedUVs.ensureCapacity(128); +} + +size_t SkeletonClipping::clipStart(Slot &slot, ClippingAttachment *clip) { + if (_clipAttachment != NULL) { + return 0; + } + + _clipAttachment = clip; + + int n = clip->getWorldVerticesLength(); + _clippingPolygon.setSize(n, 0); + clip->computeWorldVertices(slot, 0, n, _clippingPolygon, 0, 2); + makeClockwise(_clippingPolygon); + _clippingPolygons = &_triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon)); + + for (size_t i = 0; i < _clippingPolygons->size(); ++i) { + Vector *polygonP = (*_clippingPolygons)[i]; + Vector &polygon = *polygonP; + makeClockwise(polygon); + polygon.add(polygon[0]); + polygon.add(polygon[1]); + } + + return (*_clippingPolygons).size(); +} + +void SkeletonClipping::clipEnd(Slot &slot) { + if (_clipAttachment != NULL && _clipAttachment->_endSlot == &slot._data) { + clipEnd(); + } +} + +void SkeletonClipping::clipEnd() { + if (_clipAttachment == NULL) return; + + _clipAttachment = NULL; + _clippingPolygons = NULL; + _clippedVertices.clear(); + _clippedUVs.clear(); + _clippedTriangles.clear(); + _clippingPolygon.clear(); +} + +void SkeletonClipping::clipTriangles(Vector &vertices, Vector &triangles, Vector &uvs, size_t stride) { + clipTriangles(vertices.buffer(), triangles.buffer(), triangles.size(), uvs.buffer(), stride); +} + +void SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, + size_t trianglesLength, float *uvs, size_t stride +) { + Vector &clipOutput = _clipOutput; + Vector &clippedVertices = _clippedVertices; + Vector &clippedTriangles = _clippedTriangles; + Vector *> &polygons = *_clippingPolygons; + size_t polygonsCount = (*_clippingPolygons).size(); + + size_t index = 0; + clippedVertices.clear(); + _clippedUVs.clear(); + clippedTriangles.clear(); + + size_t i = 0; + continue_outer: + for (; i < trianglesLength; i += 3) { + int vertexOffset = triangles[i] * stride; + float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + + vertexOffset = triangles[i + 1] * stride; + float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + float u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + + vertexOffset = triangles[i + 2] * stride; + float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + float u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + + for (size_t p = 0; p < polygonsCount; p++) { + size_t s = clippedVertices.size(); + if (clip(x1, y1, x2, y2, x3, y3, &(*polygons[p]), &clipOutput)) { + size_t clipOutputLength = clipOutput.size(); + if (clipOutputLength == 0) continue; + float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + float d = 1 / (d0 * d2 + d1 * (y1 - y3)); + + size_t clipOutputCount = clipOutputLength >> 1; + clippedVertices.setSize(s + clipOutputCount * 2, 0); + _clippedUVs.setSize(s + clipOutputCount * 2, 0); + for (size_t ii = 0; ii < clipOutputLength; ii += 2) { + float x = clipOutput[ii], y = clipOutput[ii + 1]; + clippedVertices[s] = x; + clippedVertices[s + 1] = y; + float c0 = x - x3, c1 = y - y3; + float a = (d0 * c0 + d1 * c1) * d; + float b = (d4 * c0 + d2 * c1) * d; + float c = 1 - a - b; + _clippedUVs[s] = u1 * a + u2 * b + u3 * c; + _clippedUVs[s + 1] = v1 * a + v2 * b + v3 * c; + s += 2; + } + + s = clippedTriangles.size(); + clippedTriangles.setSize(s + 3 * (clipOutputCount - 2), 0); + clipOutputCount--; + for (size_t ii = 1; ii < clipOutputCount; ii++) { + clippedTriangles[s] = (unsigned short)(index); + clippedTriangles[s + 1] = (unsigned short)(index + ii); + clippedTriangles[s + 2] = (unsigned short)(index + ii + 1); + s += 3; + } + index += clipOutputCount + 1; + } else { + clippedVertices.setSize(s + 3 * 2, 0); + _clippedUVs.setSize(s + 3 * 2, 0); + clippedVertices[s] = x1; + clippedVertices[s + 1] = y1; + clippedVertices[s + 2] = x2; + clippedVertices[s + 3] = y2; + clippedVertices[s + 4] = x3; + clippedVertices[s + 5] = y3; + + _clippedUVs[s] = u1; + _clippedUVs[s + 1] = v1; + _clippedUVs[s + 2] = u2; + _clippedUVs[s + 3] = v2; + _clippedUVs[s + 4] = u3; + _clippedUVs[s + 5] = v3; + + s = clippedTriangles.size(); + clippedTriangles.setSize(s + 3, 0); + clippedTriangles[s] = (unsigned short)index; + clippedTriangles[s + 1] = (unsigned short)(index + 1); + clippedTriangles[s + 2] = (unsigned short)(index + 2); + index += 3; + i += 3; + goto continue_outer; + } + } + } +} + +bool SkeletonClipping::isClipping() { + return _clipAttachment != NULL; +} + +Vector &SkeletonClipping::getClippedVertices() { + return _clippedVertices; +} + +Vector &SkeletonClipping::getClippedTriangles() { + return _clippedTriangles; +} + +Vector &SkeletonClipping::getClippedUVs() { + return _clippedUVs; +} + +bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector *clippingArea, + Vector *output +) { + Vector *originalOutput = output; + bool clipped = false; + + // Avoid copy at the end. + Vector *input; + if (clippingArea->size() % 4 >= 2) { + input = output; + output = &_scratch; + } else + input = &_scratch; + + input->clear(); + input->add(x1); + input->add(y1); + input->add(x2); + input->add(y2); + input->add(x3); + input->add(y3); + input->add(x1); + input->add(y1); + output->clear(); + + Vector &clippingVertices = *clippingArea; + size_t clippingVerticesLast = clippingArea->size() - 4; + for (size_t i = 0;; i += 2) { + float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; + float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; + + Vector &inputVertices = *input; + size_t inputVerticesLength = input->size() - 2, outputStart = output->size(); + for (size_t ii = 0; ii < inputVerticesLength; ii += 2) { + float inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; + bool side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; + if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { + if (side2) { + // v1 inside, v2 inside + output->add(inputX2); + output->add(inputY2); + continue; + } + // v1 inside, v2 outside + float c0 = inputY2 - inputY, c2 = inputX2 - inputX; + float s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (MathUtil::abs(s) > 0.000001f) { + float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output->add(edgeX + (edgeX2 - edgeX) * ua); + output->add(edgeY + (edgeY2 - edgeY) * ua); + } else { + output->add(edgeX); + output->add(edgeY); + } + } else if (side2) { + // v1 outside, v2 inside + float c0 = inputY2 - inputY, c2 = inputX2 - inputX; + float s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (MathUtil::abs(s) > 0.000001f) { + float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output->add(edgeX + (edgeX2 - edgeX) * ua); + output->add(edgeY + (edgeY2 - edgeY) * ua); + } else { + output->add(edgeX); + output->add(edgeY); + } + output->add(inputX2); + output->add(inputY2); + } + clipped = true; + } + + if (outputStart == output->size()) { + // All edges outside. + originalOutput->clear(); + return true; + } + + output->add((*output)[0]); + output->add((*output)[1]); + + if (i == clippingVerticesLast) { + break; + } + Vector *temp = output; + output = input; + output->clear(); + input = temp; + } + + if (originalOutput != output) { + originalOutput->clear(); + for (size_t i = 0, n = output->size() - 2; i < n; ++i) + originalOutput->add((*output)[i]); + } else + originalOutput->setSize(originalOutput->size() - 2, 0); + + return clipped; +} + +void SkeletonClipping::makeClockwise(Vector &polygon) { + size_t verticeslength = polygon.size(); + + float area = polygon[verticeslength - 2] * polygon[1] - polygon[0] * polygon[verticeslength - 1]; + float p1x, p1y, p2x, p2y; + + for (size_t i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = polygon[i]; + p1y = polygon[i + 1]; + p2x = polygon[i + 2]; + p2y = polygon[i + 3]; + area += p1x * p2y - p2x * p1y; + } + + if (area < 0) return; + + for (size_t i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + float x = polygon[i], y = polygon[i + 1]; + int other = lastX - i; + polygon[i] = polygon[other]; + polygon[i + 1] = polygon[other + 1]; + polygon[other] = x; + polygon[other + 1] = y; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp new file mode 100644 index 0000000..a23ab04 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -0,0 +1,242 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +SkeletonData::SkeletonData() : + _name(), + _defaultSkin(NULL), + _x(0), + _y(0), + _width(0), + _height(0), + _version(), + _hash(), + _fps(0), + _imagesPath() { +} + +SkeletonData::~SkeletonData() { + ContainerUtil::cleanUpVectorOfPointers(_bones); + ContainerUtil::cleanUpVectorOfPointers(_slots); + ContainerUtil::cleanUpVectorOfPointers(_skins); + + _defaultSkin = NULL; + + ContainerUtil::cleanUpVectorOfPointers(_events); + ContainerUtil::cleanUpVectorOfPointers(_animations); + ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); + ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); + ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); + for (size_t i = 0; i < _strings.size(); i++) { + SpineExtension::free(_strings[i], __FILE__, __LINE__); + } +} + +BoneData *SkeletonData::findBone(const String &boneName) { + return ContainerUtil::findWithName(_bones, boneName); +} + +int SkeletonData::findBoneIndex(const String &boneName) { + return ContainerUtil::findIndexWithName(_bones, boneName); +} + +SlotData *SkeletonData::findSlot(const String &slotName) { + return ContainerUtil::findWithName(_slots, slotName); +} + +int SkeletonData::findSlotIndex(const String &slotName) { + return ContainerUtil::findIndexWithName(_slots, slotName); +} + +Skin *SkeletonData::findSkin(const String &skinName) { + return ContainerUtil::findWithName(_skins, skinName); +} + +spine::EventData *SkeletonData::findEvent(const String &eventDataName) { + return ContainerUtil::findWithName(_events, eventDataName); +} + +Animation *SkeletonData::findAnimation(const String &animationName) { + return ContainerUtil::findWithName(_animations, animationName); +} + +IkConstraintData *SkeletonData::findIkConstraint(const String &constraintName) { + return ContainerUtil::findWithName(_ikConstraints, constraintName); +} + +TransformConstraintData *SkeletonData::findTransformConstraint(const String &constraintName) { + return ContainerUtil::findWithName(_transformConstraints, constraintName); +} + +PathConstraintData *SkeletonData::findPathConstraint(const String &constraintName) { + return ContainerUtil::findWithName(_pathConstraints, constraintName); +} + +int SkeletonData::findPathConstraintIndex(const String &pathConstraintName) { + return ContainerUtil::findIndexWithName(_pathConstraints, pathConstraintName); +} + +const String &SkeletonData::getName() { + return _name; +} + +void SkeletonData::setName(const String &inValue) { + _name = inValue; +} + +Vector &SkeletonData::getBones() { + return _bones; +} + +Vector &SkeletonData::getSlots() { + return _slots; +} + +Vector &SkeletonData::getSkins() { + return _skins; +} + +Skin *SkeletonData::getDefaultSkin() { + return _defaultSkin; +} + +void SkeletonData::setDefaultSkin(Skin *inValue) { + _defaultSkin = inValue; +} + +Vector &SkeletonData::getEvents() { + return _events; +} + +Vector &SkeletonData::getAnimations() { + return _animations; +} + +Vector &SkeletonData::getIkConstraints() { + return _ikConstraints; +} + +Vector &SkeletonData::getTransformConstraints() { + return _transformConstraints; +} + +Vector &SkeletonData::getPathConstraints() { + return _pathConstraints; +} + +float SkeletonData::getX() { + return _x; +} + +void SkeletonData::setX(float inValue) { + _x = inValue; +} + +float SkeletonData::getY() { + return _y; +} + +void SkeletonData::setY(float inValue) { + _y = inValue; +} + +float SkeletonData::getWidth() { + return _width; +} + +void SkeletonData::setWidth(float inValue) { + _width = inValue; +} + +float SkeletonData::getHeight() { + return _height; +} + +void SkeletonData::setHeight(float inValue) { + _height = inValue; +} + +const String &SkeletonData::getVersion() { + return _version; +} + +void SkeletonData::setVersion(const String &inValue) { + _version = inValue; +} + +const String &SkeletonData::getHash() { + return _hash; +} + +void SkeletonData::setHash(const String &inValue) { + _hash = inValue; +} + +const String &SkeletonData::getImagesPath() { + return _imagesPath; +} + +void SkeletonData::setImagesPath(const String &inValue) { + _imagesPath = inValue; +} + + +const String &SkeletonData::getAudioPath() { + return _audioPath; +} + +void SkeletonData::setAudioPath(const String &inValue) { + _audioPath = inValue; +} + +float SkeletonData::getFps() { + return _fps; +} + +void SkeletonData::setFps(float inValue) { + _fps = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp new file mode 100644 index 0000000..54f94c6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -0,0 +1,1228 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) +#define strdup _strdup +#endif + +using namespace spine; + +SkeletonJson::SkeletonJson(Atlas *atlas) : _attachmentLoader(new(__FILE__, __LINE__) AtlasAttachmentLoader(atlas)), + _scale(1), _ownsLoader(true) +{} + +SkeletonJson::SkeletonJson(AttachmentLoader *attachmentLoader, bool ownsLoader) : _attachmentLoader(attachmentLoader), _scale(1), + _ownsLoader(ownsLoader) +{ + assert(_attachmentLoader != NULL); +} + +SkeletonJson::~SkeletonJson() { + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + + if (_ownsLoader) delete _attachmentLoader; +} + +SkeletonData *SkeletonJson::readSkeletonDataFile(const String &path) { + int length; + SkeletonData *skeletonData; + const char *json = SpineExtension::readFile(path, &length); + if (length == 0 || !json) { + setError(NULL, "Unable to read skeleton file: ", path); + return NULL; + } + + skeletonData = readSkeletonData(json); + + SpineExtension::free(json, __FILE__, __LINE__); + + return skeletonData; +} + +SkeletonData *SkeletonJson::readSkeletonData(const char *json) { + int i, ii; + SkeletonData *skeletonData; + Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *slots, *skins, *animations, *events; + + _error = ""; + _linkedMeshes.clear(); + + root = new(__FILE__, __LINE__) Json(json); + + if (!root) { + setError(NULL, "Invalid skeleton JSON: ", Json::getError()); + return NULL; + } + + skeletonData = new(__FILE__, __LINE__) SkeletonData(); + + skeleton = Json::getItem(root, "skeleton"); + if (skeleton) { + skeletonData->_hash = Json::getString(skeleton, "hash", 0); + skeletonData->_version = Json::getString(skeleton, "spine", 0); + if ("3.8.75" == skeletonData->_version) { + delete skeletonData; + setError(root, "Unsupported skeleton data, please export with a newer version of Spine.", ""); + return NULL; + } + skeletonData->_x = Json::getFloat(skeleton, "x", 0); + skeletonData->_y = Json::getFloat(skeleton, "y", 0); + skeletonData->_width = Json::getFloat(skeleton, "width", 0); + skeletonData->_height = Json::getFloat(skeleton, "height", 0); + skeletonData->_fps = Json::getFloat(skeleton, "fps", 30); + skeletonData->_audioPath = Json::getString(skeleton, "audio", 0); + skeletonData->_imagesPath = Json::getString(skeleton, "images", 0); + } + + /* Bones. */ + bones = Json::getItem(root, "bones"); + skeletonData->_bones.setSize(bones->_size, 0); + int bonesCount = 0; + for (boneMap = bones->_child, i = 0; boneMap; boneMap = boneMap->_next, ++i) { + BoneData *data; + const char *transformMode; + + BoneData *parent = 0; + const char *parentName = Json::getString(boneMap, "parent", 0); + if (parentName) { + parent = skeletonData->findBone(parentName); + if (!parent) { + delete skeletonData; + setError(root, "Parent bone not found: ", parentName); + return NULL; + } + } + + data = new(__FILE__, __LINE__) BoneData(bonesCount, Json::getString(boneMap, "name", 0), parent); + + data->_length = Json::getFloat(boneMap, "length", 0) * _scale; + data->_x = Json::getFloat(boneMap, "x", 0) * _scale; + data->_y = Json::getFloat(boneMap, "y", 0) * _scale; + data->_rotation = Json::getFloat(boneMap, "rotation", 0); + data->_scaleX = Json::getFloat(boneMap, "scaleX", 1); + data->_scaleY = Json::getFloat(boneMap, "scaleY", 1); + data->_shearX = Json::getFloat(boneMap, "shearX", 0); + data->_shearY = Json::getFloat(boneMap, "shearY", 0); + transformMode = Json::getString(boneMap, "transform", "normal"); + data->_transformMode = TransformMode_Normal; + if (strcmp(transformMode, "normal") == 0) data->_transformMode = TransformMode_Normal; + else if (strcmp(transformMode, "onlyTranslation") == 0) data->_transformMode = TransformMode_OnlyTranslation; + else if (strcmp(transformMode, "noRotationOrReflection") == 0) data->_transformMode = TransformMode_NoRotationOrReflection; + else if (strcmp(transformMode, "noScale") == 0) data->_transformMode = TransformMode_NoScale; + else if (strcmp(transformMode, "noScaleOrReflection") == 0) data->_transformMode = TransformMode_NoScaleOrReflection; + data->_skinRequired = Json::getBoolean(boneMap, "skin", false); + + skeletonData->_bones[i] = data; + bonesCount++; + } + + /* Slots. */ + slots = Json::getItem(root, "slots"); + if (slots) { + Json *slotMap; + skeletonData->_slots.ensureCapacity(slots->_size); + skeletonData->_slots.setSize(slots->_size, 0); + for (slotMap = slots->_child, i = 0; slotMap; slotMap = slotMap->_next, ++i) { + SlotData *data; + const char *color; + const char *dark; + Json *item; + + const char *boneName = Json::getString(slotMap, "bone", 0); + BoneData *boneData = skeletonData->findBone(boneName); + if (!boneData) { + delete skeletonData; + setError(root, "Slot bone not found: ", boneName); + return NULL; + } + + data = new(__FILE__, __LINE__) SlotData(i, Json::getString(slotMap, "name", 0), *boneData); + + color = Json::getString(slotMap, "color", 0); + if (color) { + Color &c = data->getColor(); + c.r = toColor(color, 0); + c.g = toColor(color, 1); + c.b = toColor(color, 2); + c.a = toColor(color, 3); + } + + dark = Json::getString(slotMap, "dark", 0); + if (dark) { + Color &darkColor = data->getDarkColor(); + darkColor.r = toColor(dark, 0); + darkColor.g = toColor(dark, 1); + darkColor.b = toColor(dark, 2); + darkColor.a = 1; + data->setHasDarkColor(true); + } + + item = Json::getItem(slotMap, "attachment"); + if (item) data->setAttachmentName(item->_valueString); + + item = Json::getItem(slotMap, "blend"); + if (item) { + if (strcmp(item->_valueString, "additive") == 0) data->_blendMode = BlendMode_Additive; + else if (strcmp(item->_valueString, "multiply") == 0) data->_blendMode = BlendMode_Multiply; + else if (strcmp(item->_valueString, "screen") == 0) data->_blendMode = BlendMode_Screen; + } + + skeletonData->_slots[i] = data; + } + } + + /* IK constraints. */ + ik = Json::getItem(root, "ik"); + if (ik) { + Json *constraintMap; + skeletonData->_ikConstraints.ensureCapacity(ik->_size); + skeletonData->_ikConstraints.setSize(ik->_size, 0); + for (constraintMap = ik->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *targetName; + + IkConstraintData *data = new(__FILE__, __LINE__) IkConstraintData(Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.ensureCapacity(boneMap->_size); + data->_bones.setSize(boneMap->_size, 0); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) { + delete skeletonData; + setError(root, "IK bone not found: ", boneMap->_valueString); + return NULL; + } + } + + targetName = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findBone(targetName); + if (!data->_target) { + delete skeletonData; + setError(root, "Target bone not found: ", targetName); + return NULL; + } + + data->_mix = Json::getFloat(constraintMap, "mix", 1); + data->_softness = Json::getFloat(constraintMap, "softness", 0) * _scale; + data->_bendDirection = Json::getInt(constraintMap, "bendPositive", 1) ? 1 : -1; + data->_compress = Json::getInt(constraintMap, "compress", 0) ? true: false; + data->_stretch = Json::getInt(constraintMap, "stretch", 0) ? true: false; + data->_uniform = Json::getInt(constraintMap, "uniform", 0) ? true: false; + + skeletonData->_ikConstraints[i] = data; + } + } + + /* Transform constraints. */ + transform = Json::getItem(root, "transform"); + if (transform) { + Json *constraintMap; + skeletonData->_transformConstraints.ensureCapacity(transform->_size); + skeletonData->_transformConstraints.setSize(transform->_size, 0); + for (constraintMap = transform->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *name; + + TransformConstraintData *data = new(__FILE__, __LINE__) TransformConstraintData(Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.ensureCapacity(boneMap->_size); + data->_bones.setSize(boneMap->_size, 0); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) { + delete skeletonData; + setError(root, "Transform bone not found: ", boneMap->_valueString); + return NULL; + } + } + + name = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findBone(name); + if (!data->_target) { + delete skeletonData; + setError(root, "Target bone not found: ", name); + return NULL; + } + + data->_local = Json::getInt(constraintMap, "local", 0) ? true : false; + data->_relative = Json::getInt(constraintMap, "relative", 0) ? true : false; + data->_offsetRotation = Json::getFloat(constraintMap, "rotation", 0); + data->_offsetX = Json::getFloat(constraintMap, "x", 0) * _scale; + data->_offsetY = Json::getFloat(constraintMap, "y", 0) * _scale; + data->_offsetScaleX = Json::getFloat(constraintMap, "scaleX", 0); + data->_offsetScaleY = Json::getFloat(constraintMap, "scaleY", 0); + data->_offsetShearY = Json::getFloat(constraintMap, "shearY", 0); + + data->_rotateMix = Json::getFloat(constraintMap, "rotateMix", 1); + data->_translateMix = Json::getFloat(constraintMap, "translateMix", 1); + data->_scaleMix = Json::getFloat(constraintMap, "scaleMix", 1); + data->_shearMix = Json::getFloat(constraintMap, "shearMix", 1); + + skeletonData->_transformConstraints[i] = data; + } + } + + /* Path constraints */ + path = Json::getItem(root, "path"); + if (path) { + Json *constraintMap; + skeletonData->_pathConstraints.ensureCapacity(path->_size); + skeletonData->_pathConstraints.setSize(path->_size, 0); + for (constraintMap = path->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *name; + const char *item; + + PathConstraintData *data = new(__FILE__, __LINE__) PathConstraintData(Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.ensureCapacity(boneMap->_size); + data->_bones.setSize(boneMap->_size, 0); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) { + delete skeletonData; + setError(root, "Path bone not found: ", boneMap->_valueString); + return NULL; + } + } + + name = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findSlot(name); + if (!data->_target) { + delete skeletonData; + setError(root, "Target slot not found: ", name); + return NULL; + } + + item = Json::getString(constraintMap, "positionMode", "percent"); + if (strcmp(item, "fixed") == 0) { + data->_positionMode = PositionMode_Fixed; + } else if (strcmp(item, "percent") == 0) { + data->_positionMode = PositionMode_Percent; + } + + item = Json::getString(constraintMap, "spacingMode", "length"); + if (strcmp(item, "length") == 0) data->_spacingMode = SpacingMode_Length; + else if (strcmp(item, "fixed") == 0) data->_spacingMode = SpacingMode_Fixed; + else if (strcmp(item, "percent") == 0) data->_spacingMode = SpacingMode_Percent; + + item = Json::getString(constraintMap, "rotateMode", "tangent"); + if (strcmp(item, "tangent") == 0) data->_rotateMode = RotateMode_Tangent; + else if (strcmp(item, "chain") == 0) data->_rotateMode = RotateMode_Chain; + else if (strcmp(item, "chainScale") == 0) data->_rotateMode = RotateMode_ChainScale; + + data->_offsetRotation = Json::getFloat(constraintMap, "rotation", 0); + data->_position = Json::getFloat(constraintMap, "position", 0); + if (data->_positionMode == PositionMode_Fixed) data->_position *= _scale; + data->_spacing = Json::getFloat(constraintMap, "spacing", 0); + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) data->_spacing *= _scale; + data->_rotateMix = Json::getFloat(constraintMap, "rotateMix", 1); + data->_translateMix = Json::getFloat(constraintMap, "translateMix", 1); + + skeletonData->_pathConstraints[i] = data; + } + } + + /* Skins. */ + skins = Json::getItem(root, "skins"); + if (skins) { + Json *skinMap; + skeletonData->_skins.ensureCapacity(skins->_size); + skeletonData->_skins.setSize(skins->_size, 0); + int skinsIndex = 0; + for (skinMap = skins->_child, i = 0; skinMap; skinMap = skinMap->_next, ++i) { + Json *attachmentsMap; + Json *curves; + + Skin *skin = new(__FILE__, __LINE__) Skin(Json::getString(skinMap, "name", "")); + + Json *item = Json::getItem(skinMap, "bones"); + if (item) { + for (item = item->_child; item; item = item->_next) { + BoneData* data = skeletonData->findBone(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin bone not found: "), item->_valueString); + return NULL; + } + skin->getBones().add(data); + } + } + + item = Json::getItem(skinMap, "ik"); + if (item) { + for (item = item->_child; item; item = item->_next) { + IkConstraintData* data = skeletonData->findIkConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin IK constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + item = Json::getItem(skinMap, "transform"); + if (item) { + for (item = item->_child; item; item = item->_next) { + TransformConstraintData* data = skeletonData->findTransformConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin transform constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + item = Json::getItem(skinMap, "path"); + if (item) { + for (item = item->_child; item; item = item->_next) { + PathConstraintData* data = skeletonData->findPathConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin path constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + skeletonData->_skins[skinsIndex++] = skin; + if (strcmp(Json::getString(skinMap, "name", ""), "default") == 0) { + skeletonData->_defaultSkin = skin; + } + + for (attachmentsMap = Json::getItem(skinMap, "attachments")->_child; attachmentsMap; attachmentsMap = attachmentsMap->_next) { + SlotData* slot = skeletonData->findSlot(attachmentsMap->_name); + Json *attachmentMap; + + for (attachmentMap = attachmentsMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) { + Attachment *attachment = NULL; + const char *skinAttachmentName = attachmentMap->_name; + const char *attachmentName = Json::getString(attachmentMap, "name", skinAttachmentName); + const char *attachmentPath = Json::getString(attachmentMap, "path", attachmentName); + const char *color; + Json *entry; + + const char *typeString = Json::getString(attachmentMap, "type", "region"); + AttachmentType type; + if (strcmp(typeString, "region") == 0) type = AttachmentType_Region; + else if (strcmp(typeString, "mesh") == 0) type = AttachmentType_Mesh; + else if (strcmp(typeString, "linkedmesh") == 0) type = AttachmentType_Linkedmesh; + else if (strcmp(typeString, "boundingbox") == 0) type = AttachmentType_Boundingbox; + else if (strcmp(typeString, "path") == 0) type = AttachmentType_Path; + else if (strcmp(typeString, "clipping") == 0) type = AttachmentType_Clipping; + else if (strcmp(typeString, "point") == 0) type = AttachmentType_Point; + else { + delete skeletonData; + setError(root, "Unknown attachment type: ", typeString); + return NULL; + } + + switch (type) { + case AttachmentType_Region: { + attachment = _attachmentLoader->newRegionAttachment(*skin, attachmentName, attachmentPath); + if (!attachment) { + delete skeletonData; + setError(root, "Error reading attachment: ", skinAttachmentName); + return NULL; + } + + RegionAttachment *region = static_cast(attachment); + region->_path = attachmentPath; + + region->_x = Json::getFloat(attachmentMap, "x", 0) * _scale; + region->_y = Json::getFloat(attachmentMap, "y", 0) * _scale; + region->_scaleX = Json::getFloat(attachmentMap, "scaleX", 1); + region->_scaleY = Json::getFloat(attachmentMap, "scaleY", 1); + region->_rotation = Json::getFloat(attachmentMap, "rotation", 0); + region->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; + region->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; + + color = Json::getString(attachmentMap, "color", 0); + if (color) { + region->getColor().r = toColor(color, 0); + region->getColor().g = toColor(color, 1); + region->getColor().b = toColor(color, 2); + region->getColor().a = toColor(color, 3); + } + + region->updateOffset(); + _attachmentLoader->configureAttachment(region); + break; + } + case AttachmentType_Mesh: + case AttachmentType_Linkedmesh: { + attachment = _attachmentLoader->newMeshAttachment(*skin, attachmentName, attachmentPath); + + if (!attachment) { + delete skeletonData; + setError(root, "Error reading attachment: ", skinAttachmentName); + return NULL; + } + + MeshAttachment *mesh = static_cast(attachment); + mesh->_path = attachmentPath; + + color = Json::getString(attachmentMap, "color", 0); + if (color) { + mesh->getColor().r = toColor(color, 0); + mesh->getColor().g = toColor(color, 1); + mesh->getColor().b = toColor(color, 2); + mesh->getColor().a = toColor(color, 3); + } + + mesh->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; + mesh->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; + + entry = Json::getItem(attachmentMap, "parent"); + if (!entry) { + int verticesLength; + entry = Json::getItem(attachmentMap, "triangles"); + mesh->_triangles.ensureCapacity(entry->_size); + mesh->_triangles.setSize(entry->_size, 0); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + mesh->_triangles[ii] = (unsigned short) entry->_valueInt; + + entry = Json::getItem(attachmentMap, "uvs"); + verticesLength = entry->_size; + mesh->_regionUVs.ensureCapacity(verticesLength); + mesh->_regionUVs.setSize(verticesLength, 0); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + mesh->_regionUVs[ii] = entry->_valueFloat; + + readVertices(attachmentMap, mesh, verticesLength); + + mesh->updateUVs(); + + mesh->_hullLength = Json::getInt(attachmentMap, "hull", 0); + + entry = Json::getItem(attachmentMap, "edges"); + if (entry) { + mesh->_edges.ensureCapacity(entry->_size); + mesh->_edges.setSize(entry->_size, 0); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + mesh->_edges[ii] = entry->_valueInt; + } + _attachmentLoader->configureAttachment(mesh); + } else { + bool inheritDeform = Json::getInt(attachmentMap, "deform", 1) ? true : false; + LinkedMesh *linkedMesh = new(__FILE__, __LINE__) LinkedMesh(mesh, + String(Json::getString(attachmentMap, "skin", 0)), slot->getIndex(), String(entry->_valueString), + inheritDeform); + _linkedMeshes.add(linkedMesh); + } + break; + } + case AttachmentType_Boundingbox: { + attachment = _attachmentLoader->newBoundingBoxAttachment(*skin, attachmentName); + + BoundingBoxAttachment *box = static_cast(attachment); + + int vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; + readVertices(attachmentMap, box, vertexCount); + _attachmentLoader->configureAttachment(attachment); + break; + } + case AttachmentType_Path: { + attachment = _attachmentLoader->newPathAttachment(*skin, attachmentName); + + PathAttachment *pathAttatchment = static_cast(attachment); + + int vertexCount = 0; + pathAttatchment->_closed = Json::getInt(attachmentMap, "closed", 0) ? true : false; + pathAttatchment->_constantSpeed = Json::getInt(attachmentMap, "constantSpeed", 1) ? true : false; + vertexCount = Json::getInt(attachmentMap, "vertexCount", 0); + readVertices(attachmentMap, pathAttatchment, vertexCount << 1); + + pathAttatchment->_lengths.ensureCapacity(vertexCount / 3); + pathAttatchment->_lengths.setSize(vertexCount / 3, 0); + + curves = Json::getItem(attachmentMap, "lengths"); + for (curves = curves->_child, ii = 0; curves; curves = curves->_next, ++ii) + pathAttatchment->_lengths[ii] = curves->_valueFloat * _scale; + _attachmentLoader->configureAttachment(attachment); + break; + } + case AttachmentType_Point: { + attachment = _attachmentLoader->newPointAttachment(*skin, attachmentName); + + PointAttachment *point = static_cast(attachment); + + point->_x = Json::getFloat(attachmentMap, "x", 0) * _scale; + point->_y = Json::getFloat(attachmentMap, "y", 0) * _scale; + point->_rotation = Json::getFloat(attachmentMap, "rotation", 0); + _attachmentLoader->configureAttachment(attachment); + break; + } + case AttachmentType_Clipping: { + attachment = _attachmentLoader->newClippingAttachment(*skin, attachmentName); + + ClippingAttachment *clip = static_cast(attachment); + + int vertexCount = 0; + const char *end = Json::getString(attachmentMap, "end", 0); + if (end) clip->_endSlot = skeletonData->findSlot(end); + vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; + readVertices(attachmentMap, clip, vertexCount); + _attachmentLoader->configureAttachment(attachment); + break; + } + } + + skin->setAttachment(slot->getIndex(), skinAttachmentName, attachment); + } + } + } + } + + /* Linked meshes. */ + int n = _linkedMeshes.size(); + for (i = 0; i < n; ++i) { + LinkedMesh *linkedMesh = _linkedMeshes[i]; + Skin *skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin(linkedMesh->_skin); + if (skin == NULL) { + delete skeletonData; + setError(root, "Skin not found: ", linkedMesh->_skin.buffer()); + return NULL; + } + Attachment *parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); + if (parent == NULL) { + delete skeletonData; + setError(root, "Parent mesh not found: ", linkedMesh->_parent.buffer()); + return NULL; + } + linkedMesh->_mesh->_deformAttachment = linkedMesh->_inheritDeform ? static_cast(parent) : linkedMesh->_mesh; + linkedMesh->_mesh->setParentMesh(static_cast(parent)); + linkedMesh->_mesh->updateUVs(); + _attachmentLoader->configureAttachment(linkedMesh->_mesh); + } + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + /* Events. */ + events = Json::getItem(root, "events"); + if (events) { + Json *eventMap; + skeletonData->_events.ensureCapacity(events->_size); + skeletonData->_events.setSize(events->_size, 0); + for (eventMap = events->_child, i = 0; eventMap; eventMap = eventMap->_next, ++i) { + EventData *eventData = new(__FILE__, __LINE__) EventData(String(eventMap->_name)); + + eventData->_intValue = Json::getInt(eventMap, "int", 0); + eventData->_floatValue = Json::getFloat(eventMap, "float", 0); + const char *stringValue = Json::getString(eventMap, "string", 0); + eventData->_stringValue = stringValue; + const char *audioPath = Json::getString(eventMap, "audio", 0); + eventData->_audioPath = audioPath; + if (audioPath) { + eventData->_volume = Json::getFloat(eventMap, "volume", 1); + eventData->_balance = Json::getFloat(eventMap, "balance", 0); + } + skeletonData->_events[i] = eventData; + } + } + + /* Animations. */ + animations = Json::getItem(root, "animations"); + if (animations) { + Json *animationMap; + skeletonData->_animations.ensureCapacity(animations->_size); + skeletonData->_animations.setSize(animations->_size, 0); + int animationsIndex = 0; + for (animationMap = animations->_child; animationMap; animationMap = animationMap->_next) { + Animation *animation = readAnimation(animationMap, skeletonData); + if (!animation) { + delete skeletonData; + delete root; + return NULL; + } + skeletonData->_animations[animationsIndex++] = animation; + } + } + + delete root; + + return skeletonData; +} + +float SkeletonJson::toColor(const char *value, size_t index) { + char digits[3]; + char *error; + int color; + + if (index >= strlen(value) / 2) return -1; + + value += index * 2; + + digits[0] = *value; + digits[1] = *(value + 1); + digits[2] = '\0'; + color = (int) strtoul(digits, &error, 16); + if (*error != 0) return -1; + + return color / (float) 255; +} + +void SkeletonJson::readCurve(Json *frame, CurveTimeline *timeline, size_t frameIndex) { + Json *curve = Json::getItem(frame, "curve"); + if (!curve) return; + if (curve->_type == Json::JSON_STRING && strcmp(curve->_valueString, "stepped") == 0) + timeline->setStepped(frameIndex); + else { + float c1 = Json::getFloat(frame, "curve", 0); + float c2 = Json::getFloat(frame, "c2", 0); + float c3 = Json::getFloat(frame, "c3", 1); + float c4 = Json::getFloat(frame, "c4", 1); + timeline->setCurve(frameIndex, c1, c2, c3, c4); + } +} + +Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) { + Vector timelines; + float duration = 0; + + size_t frameIndex; + Json *valueMap; + int timelinesCount = 0; + + Json *bones = Json::getItem(root, "bones"); + Json *slots = Json::getItem(root, "slots"); + Json *ik = Json::getItem(root, "ik"); + Json *transform = Json::getItem(root, "transform"); + Json *paths = Json::getItem(root, "path"); + Json *deform = Json::getItem(root, "deform"); + Json *drawOrder = Json::getItem(root, "drawOrder"); + Json *events = Json::getItem(root, "events"); + Json *boneMap, *slotMap, *constraintMap; + if (!drawOrder) drawOrder = Json::getItem(root, "draworder"); + + for (boneMap = bones ? bones->_child : NULL; boneMap; boneMap = boneMap->_next) + timelinesCount += boneMap->_size; + + for (slotMap = slots ? slots->_child : NULL; slotMap; slotMap = slotMap->_next) + timelinesCount += slotMap->_size; + + timelinesCount += ik ? ik->_size : 0; + timelinesCount += transform ? transform->_size : 0; + + for (constraintMap = paths ? paths->_child : NULL; constraintMap; constraintMap = constraintMap->_next) + timelinesCount += constraintMap->_size; + + for (constraintMap = deform ? deform->_child : NULL; constraintMap; constraintMap = constraintMap->_next) + for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) + timelinesCount += slotMap->_size; + + if (drawOrder) ++timelinesCount; + + if (events) ++timelinesCount; + + /** Slot timelines. */ + for (slotMap = slots ? slots->_child : 0; slotMap; slotMap = slotMap->_next) { + Json *timelineMap; + + int slotIndex = skeletonData->findSlotIndex(slotMap->_name); + if (slotIndex == -1) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Slot not found: ", slotMap->_name); + return NULL; + } + + for (timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) { + if (strcmp(timelineMap->_name, "attachment") == 0) { + AttachmentTimeline *timeline = new(__FILE__, __LINE__) AttachmentTimeline(timelineMap->_size); + + timeline->_slotIndex = slotIndex; + + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { + Json *name = Json::getItem(valueMap, "name"); + String attachmentName = name->_type == Json::JSON_NULL ? "" : name->_valueString; + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), attachmentName); + } + timelines.add(timeline); + timelinesCount++; + duration = MathUtil::max(duration, timeline->_frames[timelineMap->_size - 1]); + + } else if (strcmp(timelineMap->_name, "color") == 0) { + ColorTimeline *timeline = new(__FILE__, __LINE__) ColorTimeline(timelineMap->_size); + + timeline->_slotIndex = slotIndex; + + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { + const char *s = Json::getString(valueMap, "color", 0); + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), + toColor(s, 2), toColor(s, 3)); + readCurve(valueMap, timeline, frameIndex); + } + timelines.add(timeline); + timelinesCount++; + duration = MathUtil::max(duration, timeline->_frames[(timelineMap->_size - 1) * ColorTimeline::ENTRIES]); + + } else if (strcmp(timelineMap->_name, "twoColor") == 0) { + TwoColorTimeline *timeline = new(__FILE__, __LINE__) TwoColorTimeline(timelineMap->_size); + + timeline->_slotIndex = slotIndex; + + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { + const char *s = Json::getString(valueMap, "light", 0); + const char *ds = Json::getString(valueMap, "dark", 0); + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), + toColor(s, 2), toColor(s, 3), toColor(ds, 0), toColor(ds, 1), toColor(ds, 2)); + readCurve(valueMap, timeline, frameIndex); + } + timelines.add(timeline); + timelinesCount++; + duration = MathUtil::max(duration, + timeline->_frames[(timelineMap->_size - 1) * TwoColorTimeline::ENTRIES]); + } else { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Invalid timeline type for a slot: ", timelineMap->_name); + return NULL; + } + } + } + + /** Bone timelines. */ + for (boneMap = bones ? bones->_child : 0; boneMap; boneMap = boneMap->_next) { + Json *timelineMap; + + int boneIndex = skeletonData->findBoneIndex(boneMap->_name); + if (boneIndex == -1) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Bone not found: ", boneMap->_name); + return NULL; + } + + for (timelineMap = boneMap->_child; timelineMap; timelineMap = timelineMap->_next) { + if (strcmp(timelineMap->_name, "rotate") == 0) { + RotateTimeline *timeline = new(__FILE__, __LINE__) RotateTimeline(timelineMap->_size); + + timeline->_boneIndex = boneIndex; + + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "angle", 0)); + readCurve(valueMap, timeline, frameIndex); + } + timelines.add(timeline); + timelinesCount++; + duration = MathUtil::max(duration, timeline->_frames[(timelineMap->_size - 1) * RotateTimeline::ENTRIES]); + } else { + int isScale = strcmp(timelineMap->_name, "scale") == 0; + int isTranslate = strcmp(timelineMap->_name, "translate") == 0; + int isShear = strcmp(timelineMap->_name, "shear") == 0; + if (isScale || isTranslate || isShear) { + float timelineScale = isTranslate ? _scale : 1; + float defaultValue = 0; + TranslateTimeline *timeline = 0; + if (isScale) { + timeline = new(__FILE__, __LINE__) ScaleTimeline(timelineMap->_size); + defaultValue = 1; + } else if (isTranslate) { + timeline = new(__FILE__, __LINE__) TranslateTimeline(timelineMap->_size); + } else if (isShear) { + timeline = new(__FILE__, __LINE__) ShearTimeline(timelineMap->_size); + } + timeline->_boneIndex = boneIndex; + + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), + Json::getFloat(valueMap, "x", defaultValue) * timelineScale, + Json::getFloat(valueMap, "y", defaultValue) * timelineScale); + readCurve(valueMap, timeline, frameIndex); + } + + timelines.add(timeline); + timelinesCount++; + duration = MathUtil::max(duration, timeline->_frames[(timelineMap->_size - 1) * TranslateTimeline::ENTRIES]); + } else { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Invalid timeline type for a bone: ", timelineMap->_name); + return NULL; + } + } + } + } + + /** IK constraint timelines. */ + for (constraintMap = ik ? ik->_child : 0; constraintMap; constraintMap = constraintMap->_next) { + IkConstraintData *constraint = skeletonData->findIkConstraint(constraintMap->_name); + IkConstraintTimeline *timeline = new(__FILE__, __LINE__) IkConstraintTimeline(constraintMap->_size); + + for (frameIndex = 0; frameIndex < skeletonData->_ikConstraints.size(); ++frameIndex) { + if (constraint == skeletonData->_ikConstraints[frameIndex]) { + timeline->_ikConstraintIndex = frameIndex; + break; + } + } + for (valueMap = constraintMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "mix", 1), + Json::getFloat(valueMap, "softness", 0) * _scale, Json::getInt(valueMap, "bendPositive", 1) ? 1 : -1, + Json::getInt(valueMap, "compress", 0) ? true : false, Json::getInt(valueMap, "stretch", 0) ? true : false); + readCurve(valueMap, timeline, frameIndex); + } + timelines.add(timeline); + timelinesCount++; + duration = MathUtil::max(duration, timeline->_frames[(constraintMap->_size - 1) * IkConstraintTimeline::ENTRIES]); + } + + /** Transform constraint timelines. */ + for (constraintMap = transform ? transform->_child : 0; constraintMap; constraintMap = constraintMap->_next) { + TransformConstraintData *constraint = skeletonData->findTransformConstraint(constraintMap->_name); + TransformConstraintTimeline *timeline = new(__FILE__, __LINE__) TransformConstraintTimeline(constraintMap->_size); + + for (frameIndex = 0; frameIndex < skeletonData->_transformConstraints.size(); ++frameIndex) { + if (constraint == skeletonData->_transformConstraints[frameIndex]) { + timeline->_transformConstraintIndex = frameIndex; + break; + } + } + for (valueMap = constraintMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), + Json::getFloat(valueMap, "rotateMix", 1), Json::getFloat(valueMap, "translateMix", 1), + Json::getFloat(valueMap, "scaleMix", 1), Json::getFloat(valueMap, "shearMix", 1)); + readCurve(valueMap, timeline, frameIndex); + } + timelines.add(timeline); + timelinesCount++; + duration = MathUtil::max(duration, timeline->_frames[(constraintMap->_size - 1) * TransformConstraintTimeline::ENTRIES]); + } + + /** Path constraint timelines. */ + for (constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) { + size_t constraintIndex = 0, i; + Json *timelineMap; + + PathConstraintData *data = skeletonData->findPathConstraint(constraintMap->_name); + if (!data) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Path constraint not found: ", constraintMap->_name); + return NULL; + } + + for (i = 0; i < skeletonData->_pathConstraints.size(); i++) { + if (skeletonData->_pathConstraints[i] == data) { + constraintIndex = i; + break; + } + } + + for (timelineMap = constraintMap->_child; timelineMap; timelineMap = timelineMap->_next) { + const char *timelineName = timelineMap->_name; + if (strcmp(timelineName, "position") == 0 || strcmp(timelineName, "spacing") == 0) { + PathConstraintPositionTimeline *timeline; + float timelineScale = 1; + if (strcmp(timelineName, "spacing") == 0) { + timeline = new(__FILE__, __LINE__) PathConstraintSpacingTimeline(timelineMap->_size); + + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) { + timelineScale = _scale; + } + } else { + timeline = new(__FILE__, __LINE__) PathConstraintPositionTimeline(timelineMap->_size); + + if (data->_positionMode == PositionMode_Fixed) { + timelineScale = _scale; + } + } + + timeline->_pathConstraintIndex = constraintIndex; + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), + Json::getFloat(valueMap, timelineName, 0) * timelineScale); + readCurve(valueMap, timeline, frameIndex); + } + timelines.add(timeline); + timelinesCount++; + duration = MathUtil::max(duration, timeline->_frames[(timelineMap->_size - 1) * + PathConstraintPositionTimeline::ENTRIES]); + } else if (strcmp(timelineName, "mix") == 0) { + PathConstraintMixTimeline *timeline = new(__FILE__, __LINE__) PathConstraintMixTimeline(timelineMap->_size); + timeline->_pathConstraintIndex = constraintIndex; + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), + Json::getFloat(valueMap, "rotateMix", 1), + Json::getFloat(valueMap, "translateMix", 1)); + readCurve(valueMap, timeline, frameIndex); + } + timelines.add(timeline); + timelinesCount++; + duration = MathUtil::max(duration, timeline->_frames[(timelineMap->_size - 1) * PathConstraintMixTimeline::ENTRIES]); + } + } + } + + /** Deform timelines. */ + for (constraintMap = deform ? deform->_child : NULL; constraintMap; constraintMap = constraintMap->_next) { + Skin *skin = skeletonData->findSkin(constraintMap->_name); + for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) { + int slotIndex = skeletonData->findSlotIndex(slotMap->_name); + Json *timelineMap; + for (timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) { + DeformTimeline *timeline; + int weighted, deformLength; + + Attachment *baseAttachment = skin->getAttachment(slotIndex, timelineMap->_name); + + if (!baseAttachment) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Attachment not found: ", timelineMap->_name); + return NULL; + } + + VertexAttachment *attachment = static_cast(baseAttachment); + + weighted = attachment->_bones.size() != 0; + Vector &verts = attachment->_vertices; + deformLength = weighted ? verts.size() / 3 * 2 : verts.size(); + + timeline = new(__FILE__, __LINE__) DeformTimeline(timelineMap->_size); + + timeline->_slotIndex = slotIndex; + timeline->_attachment = attachment; + + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { + Json *vertices = Json::getItem(valueMap, "vertices"); + Vector deformed; + if (!vertices) { + if (weighted) { + deformed.setSize(deformLength, 0); + } else { + deformed.clearAndAddAll(attachment->_vertices); + } + } else { + int v, start = Json::getInt(valueMap, "offset", 0); + Json *vertex; + deformed.setSize(deformLength, 0); + if (_scale == 1) { + for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { + deformed[v] = vertex->_valueFloat; + } + } else { + for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { + deformed[v] = vertex->_valueFloat * _scale; + } + } + if (!weighted) { + Vector &verticesAttachment = attachment->_vertices; + for (v = 0; v < deformLength; ++v) { + deformed[v] += verticesAttachment[v]; + } + } + } + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), deformed); + readCurve(valueMap, timeline, frameIndex); + } + + timelines.add(timeline); + timelinesCount++; + duration = MathUtil::max(duration, timeline->_frames[timelineMap->_size - 1]); + } + } + } + + /** Draw order timeline. */ + if (drawOrder) { + DrawOrderTimeline *timeline = new(__FILE__, __LINE__) DrawOrderTimeline(drawOrder->_size); + + for (valueMap = drawOrder->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { + int ii; + Vector drawOrder2; + Json *offsets = Json::getItem(valueMap, "offsets"); + if (offsets) { + Json *offsetMap; + Vector unchanged; + unchanged.ensureCapacity(skeletonData->_slots.size() - offsets->_size); + unchanged.setSize(skeletonData->_slots.size() - offsets->_size, 0); + size_t originalIndex = 0, unchangedIndex = 0; + + drawOrder2.ensureCapacity(skeletonData->_slots.size()); + drawOrder2.setSize(skeletonData->_slots.size(), 0); + for (ii = (int)skeletonData->_slots.size() - 1; ii >= 0; --ii) + drawOrder2[ii] = -1; + + for (offsetMap = offsets->_child; offsetMap; offsetMap = offsetMap->_next) { + int slotIndex = skeletonData->findSlotIndex(Json::getString(offsetMap, "slot", 0)); + if (slotIndex == -1) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Slot not found: ", Json::getString(offsetMap, "slot", 0)); + return NULL; + } + /* Collect unchanged items. */ + while (originalIndex != (size_t)slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + /* Set changed items. */ + drawOrder2[originalIndex + Json::getInt(offsetMap, "offset", 0)] = originalIndex; + originalIndex++; + } + /* Collect remaining unchanged items. */ + while (originalIndex < skeletonData->_slots.size()) + unchanged[unchangedIndex++] = originalIndex++; + /* Fill in unchanged items. */ + for (ii = (int)skeletonData->_slots.size() - 1; ii >= 0; ii--) + if (drawOrder2[ii] == -1) drawOrder2[ii] = unchanged[--unchangedIndex]; + } + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), drawOrder2); + } + timelines.add(timeline); + timelinesCount++; + duration = MathUtil::max(duration, timeline->_frames[drawOrder->_size - 1]); + } + + /** Event timeline. */ + if (events) { + EventTimeline *timeline = new(__FILE__, __LINE__) EventTimeline(events->_size); + + for (valueMap = events->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { + Event *event; + EventData *eventData = skeletonData->findEvent(Json::getString(valueMap, "name", 0)); + if (!eventData) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Event not found: ", Json::getString(valueMap, "name", 0)); + return NULL; + } + + event = new(__FILE__, __LINE__) Event(Json::getFloat(valueMap, "time", 0), *eventData); + event->_intValue = Json::getInt(valueMap, "int", eventData->_intValue); + event->_floatValue = Json::getFloat(valueMap, "float", eventData->_floatValue); + event->_stringValue = Json::getString(valueMap, "string", eventData->_stringValue.buffer()); + if (!eventData->_audioPath.isEmpty()) { + event->_volume = Json::getFloat(valueMap, "volume", 1); + event->_balance = Json::getFloat(valueMap, "balance", 0); + } + timeline->setFrame(frameIndex, event); + } + timelines.add(timeline); + timelinesCount++; + duration = MathUtil::max(duration, timeline->_frames[events->_size - 1]); + } + + return new(__FILE__, __LINE__) Animation(String(root->_name), timelines, duration); +} + +void SkeletonJson::readVertices(Json *attachmentMap, VertexAttachment *attachment, size_t verticesLength) { + Json *entry; + size_t i, n, nn, entrySize; + Vector vertices; + + attachment->setWorldVerticesLength(verticesLength); + + entry = Json::getItem(attachmentMap, "vertices"); + entrySize = entry->_size; + vertices.ensureCapacity(entrySize); + vertices.setSize(entrySize, 0); + for (entry = entry->_child, i = 0; entry; entry = entry->_next, ++i) + vertices[i] = entry->_valueFloat; + + if (verticesLength == entrySize) { + if (_scale != 1) { + for (i = 0; i < entrySize; ++i) + vertices[i] *= _scale; + } + + attachment->getVertices().clearAndAddAll(vertices); + return; + } + + Vertices bonesAndWeights; + bonesAndWeights._bones.ensureCapacity(verticesLength * 3); + bonesAndWeights._vertices.ensureCapacity(verticesLength * 3 * 3); + + for (i = 0, n = entrySize; i < n;) { + int boneCount = (int) vertices[i++]; + bonesAndWeights._bones.add(boneCount); + for (nn = i + boneCount * 4; i < nn; i += 4) { + bonesAndWeights._bones.add((int) vertices[i]); + bonesAndWeights._vertices.add(vertices[i + 1] * _scale); + bonesAndWeights._vertices.add(vertices[i + 2] * _scale); + bonesAndWeights._vertices.add(vertices[i + 3]); + } + } + + attachment->getVertices().clearAndAddAll(bonesAndWeights._vertices); + attachment->getBones().clearAndAddAll(bonesAndWeights._bones); +} + +void SkeletonJson::setError(Json *root, const String &value1, const String &value2) { + _error = String(value1).append(value2); + delete root; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Skin.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Skin.cpp new file mode 100644 index 0000000..caf0225 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -0,0 +1,198 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include + +#include +#include + +#include + +using namespace spine; + +Skin::AttachmentMap::AttachmentMap() { +} + +static void disposeAttachment(Attachment* attachment) { + if (!attachment) return; + attachment->dereference(); + if (attachment->getRefCount() == 0) delete attachment; +} + +void Skin::AttachmentMap::put(size_t slotIndex, const String &attachmentName, Attachment *attachment) { + if (slotIndex >= _buckets.size()) + _buckets.setSize(slotIndex + 1, Vector()); + Vector &bucket = _buckets[slotIndex]; + int existing = findInBucket(bucket, attachmentName); + attachment->reference(); + if (existing >= 0) { + disposeAttachment(bucket[existing]._attachment); + bucket[existing]._attachment = attachment; + } else { + bucket.add(Entry(slotIndex, attachmentName, attachment)); + } +} + +Attachment *Skin::AttachmentMap::get(size_t slotIndex, const String &attachmentName) { + if (slotIndex >= _buckets.size()) return NULL; + int existing = findInBucket(_buckets[slotIndex], attachmentName); + return existing >= 0 ? _buckets[slotIndex][existing]._attachment : NULL; +} + +void Skin::AttachmentMap::remove(size_t slotIndex, const String &attachmentName) { + if (slotIndex >= _buckets.size()) return; + int existing = findInBucket(_buckets[slotIndex], attachmentName); + if (existing >= 0) { + disposeAttachment(_buckets[slotIndex][existing]._attachment); + _buckets[slotIndex].removeAt(existing); + } +} + +int Skin::AttachmentMap::findInBucket(Vector &bucket, const String &attachmentName) { + for (size_t i = 0; i < bucket.size(); i++) + if (bucket[i]._name == attachmentName) return i; + return -1; +} + +Skin::AttachmentMap::Entries Skin::AttachmentMap::getEntries() { + return Skin::AttachmentMap::Entries(_buckets); +} + +Skin::Skin(const String &name) : _name(name), _attachments() { + assert(_name.length() > 0); +} + +Skin::~Skin() { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry entry = entries.next(); + disposeAttachment(entry._attachment); + } +} + +void Skin::setAttachment(size_t slotIndex, const String &name, Attachment *attachment) { + assert(attachment); + _attachments.put(slotIndex, name, attachment); +} + +Attachment *Skin::getAttachment(size_t slotIndex, const String &name) { + return _attachments.get(slotIndex, name); +} + +void Skin::removeAttachment(size_t slotIndex, const String& name) { + _attachments.remove(slotIndex, name); +} + +void Skin::findNamesForSlot(size_t slotIndex, Vector &names) { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == slotIndex) { + names.add(entry._name); + } + } +} + +void Skin::findAttachmentsForSlot(size_t slotIndex, Vector &attachments) { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == slotIndex) attachments.add(entry._attachment); + } +} + +const String &Skin::getName() { + return _name; +} + +Skin::AttachmentMap::Entries Skin::getAttachments() { + return _attachments.getEntries(); +} + +void Skin::attachAll(Skeleton &skeleton, Skin &oldSkin) { + Vector &slots = skeleton.getSlots(); + Skin::AttachmentMap::Entries entries = oldSkin.getAttachments(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + int slotIndex = entry._slotIndex; + Slot *slot = slots[slotIndex]; + + if (slot->getAttachment() == entry._attachment) { + Attachment *attachment = getAttachment(slotIndex, entry._name); + if (attachment) slot->setAttachment(attachment); + } + } +} + +void Skin::addSkin(Skin* other) { + for (size_t i = 0; i < other->getBones().size(); i++) + if (!_bones.contains(other->getBones()[i])) _bones.add(other->getBones()[i]); + + for (size_t i = 0; i < other->getConstraints().size(); i++) + if (!_constraints.contains(other->getConstraints()[i])) _constraints.add(other->getConstraints()[i]); + + AttachmentMap::Entries entries = other->getAttachments(); + while(entries.hasNext()) { + AttachmentMap::Entry& entry = entries.next(); + setAttachment(entry._slotIndex, entry._name, entry._attachment); + } +} + +void Skin::copySkin(Skin* other) { + for (size_t i = 0; i < other->getBones().size(); i++) + if (!_bones.contains(other->getBones()[i])) _bones.add(other->getBones()[i]); + + for (size_t i = 0; i < other->getConstraints().size(); i++) + if (!_constraints.contains(other->getConstraints()[i])) _constraints.add(other->getConstraints()[i]); + + AttachmentMap::Entries entries = other->getAttachments(); + while(entries.hasNext()) { + AttachmentMap::Entry& entry = entries.next(); + if (entry._attachment->getRTTI().isExactly(MeshAttachment::rtti)) + setAttachment(entry._slotIndex, entry._name, static_cast(entry._attachment)->newLinkedMesh()); + else + setAttachment(entry._slotIndex, entry._name, entry._attachment->copy()); + } +} + +Vector& Skin::getConstraints() { + return _constraints; +} + +Vector& Skin::getBones() { + return _bones; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Slot.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Slot.cpp new file mode 100644 index 0000000..4edf8b7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -0,0 +1,125 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include + +using namespace spine; + +Slot::Slot(SlotData &data, Bone &bone) : + _data(data), + _bone(bone), + _skeleton(bone.getSkeleton()), + _color(1, 1, 1, 1), + _darkColor(0, 0, 0, 0), + _hasDarkColor(data.hasDarkColor()), + _attachment(NULL), + _attachmentState(0), + _attachmentTime(0) { + setToSetupPose(); +} + +void Slot::setToSetupPose() { + _color.set(_data.getColor()); + if (_hasDarkColor) _darkColor.set(_data.getDarkColor()); + + const String &attachmentName = _data.getAttachmentName(); + if (attachmentName.length() > 0) { + _attachment = NULL; + setAttachment(_skeleton.getAttachment(_data.getIndex(), attachmentName)); + } else { + setAttachment(NULL); + } +} + +SlotData &Slot::getData() { + return _data; +} + +Bone &Slot::getBone() { + return _bone; +} + +Skeleton &Slot::getSkeleton() { + return _skeleton; +} + +Color &Slot::getColor() { + return _color; +} + +Color &Slot::getDarkColor() { + return _darkColor; +} + +bool Slot::hasDarkColor() { + return _hasDarkColor; +} + +Attachment *Slot::getAttachment() { + return _attachment; +} + +void Slot::setAttachment(Attachment *inValue) { + if (_attachment == inValue) { + return; + } + + _attachment = inValue; + _attachmentTime = _skeleton.getTime(); + _deform.clear(); +} + +int Slot::getAttachmentState() { + return _attachmentState; +} + +void Slot::setAttachmentState(int state) { + _attachmentState = state; +} + +float Slot::getAttachmentTime() { + return _skeleton.getTime() - _attachmentTime; +} + +void Slot::setAttachmentTime(float inValue) { + _attachmentTime = _skeleton.getTime() - inValue; +} + +Vector &Slot::getDeform() { + return _deform; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SlotData.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SlotData.cpp new file mode 100644 index 0000000..4f61894 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SlotData.cpp @@ -0,0 +1,95 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +SlotData::SlotData(int index, const String &name, BoneData &boneData) : + _index(index), + _name(name), + _boneData(boneData), + _color(1, 1, 1, 1), + _darkColor(0, 0, 0, 0), + _hasDarkColor(false), + _attachmentName(), + _blendMode(BlendMode_Normal) { + assert(_index >= 0); + assert(_name.length() > 0); +} + +int SlotData::getIndex() { + return _index; +} + +const String &SlotData::getName() { + return _name; +} + +BoneData &SlotData::getBoneData() { + return _boneData; +} + +Color &SlotData::getColor() { + return _color; +} + +Color &SlotData::getDarkColor() { + return _darkColor; +} + +bool SlotData::hasDarkColor() { + return _hasDarkColor; +} + +void SlotData::setHasDarkColor(bool inValue) { + _hasDarkColor = inValue; +} + +const String &SlotData::getAttachmentName() { + return _attachmentName; +} + +void SlotData::setAttachmentName(const String &inValue) { + _attachmentName = inValue; +} + +BlendMode SlotData::getBlendMode() { + return _blendMode; +} + +void SlotData::setBlendMode(BlendMode inValue) { + _blendMode = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SpineObject.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SpineObject.cpp new file mode 100644 index 0000000..f432f1a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/SpineObject.cpp @@ -0,0 +1,67 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include + +using namespace spine; + +void *SpineObject::operator new(size_t sz) { + return SpineExtension::getInstance()->_calloc(sz, __FILE__, __LINE__); +} + +void *SpineObject::operator new(size_t sz, const char *file, int line) { + return SpineExtension::getInstance()->_calloc(sz, file, line); +} + +void *SpineObject::operator new(size_t sz, void *ptr) { + SP_UNUSED(sz); + return ptr; +} + +void SpineObject::operator delete(void *p, const char *file, int line) { + SpineExtension::free(p, file, line); +} + +void SpineObject::operator delete(void *p, void *mem) { + SP_UNUSED(mem); + SpineExtension::free(p, __FILE__, __LINE__); +} + +void SpineObject::operator delete(void *p) { + SpineExtension::free(p, __FILE__, __LINE__); +} + +SpineObject::~SpineObject() { + SpineExtension::beforeFree(this); +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp new file mode 100644 index 0000000..4cffb32 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp @@ -0,0 +1,42 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +namespace spine { +TextureLoader::TextureLoader() { +} + +TextureLoader::~TextureLoader() { +} +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Timeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Timeline.cpp new file mode 100644 index 0000000..23bf723 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Timeline.cpp @@ -0,0 +1,48 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +namespace spine { +RTTI_IMPL_NOPARENT(Timeline) + +Timeline::Timeline() { +} + +Timeline::~Timeline() { +} + +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp new file mode 100644 index 0000000..c2ac1b5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -0,0 +1,355 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(TransformConstraint, Updatable) + +TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : Updatable(), + _data(data), + _target(skeleton.findBone( + data.getTarget()->getName())), + _rotateMix( + data.getRotateMix()), + _translateMix( + data.getTranslateMix()), + _scaleMix( + data.getScaleMix()), + _shearMix( + data.getShearMix()), + _active(false) +{ + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); ++i) { + BoneData *boneData = _data.getBones()[i]; + _bones.add(skeleton.findBone(boneData->getName())); + } +} + +void TransformConstraint::apply() { + update(); +} + +void TransformConstraint::update() { + if (_data.isLocal()) { + if (_data.isRelative()) + applyRelativeLocal(); + else + applyAbsoluteLocal(); + } else { + if (_data.isRelative()) + applyRelativeWorld(); + else + applyAbsoluteWorld(); + } +} + +int TransformConstraint::getOrder() { + return _data.getOrder(); +} + +TransformConstraintData &TransformConstraint::getData() { + return _data; +} + +Vector &TransformConstraint::getBones() { + return _bones; +} + +Bone *TransformConstraint::getTarget() { + return _target; +} + +void TransformConstraint::setTarget(Bone *inValue) { + _target = inValue; +} + +float TransformConstraint::getRotateMix() { + return _rotateMix; +} + +void TransformConstraint::setRotateMix(float inValue) { + _rotateMix = inValue; +} + +float TransformConstraint::getTranslateMix() { + return _translateMix; +} + +void TransformConstraint::setTranslateMix(float inValue) { + _translateMix = inValue; +} + +float TransformConstraint::getScaleMix() { + return _scaleMix; +} + +void TransformConstraint::setScaleMix(float inValue) { + _scaleMix = inValue; +} + +float TransformConstraint::getShearMix() { + return _shearMix; +} + +void TransformConstraint::setShearMix(float inValue) { + _shearMix = inValue; +} + +void TransformConstraint::applyAbsoluteWorld() { + float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; + Bone &target = *_target; + float ta = target._a, tb = target._b, tc = target._c, td = target._d; + float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; + float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; + + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + bool modified = false; + + if (rotateMix != 0) { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + float r = MathUtil::atan2(tc, ta) - MathUtil::atan2(c, a) + offsetRotation; + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r *= rotateMix; + float cos = MathUtil::cos(r), sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + modified = true; + } + + if (translateMix != 0) { + float tx, ty; + target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); + bone._worldX += (tx - bone._worldX) * translateMix; + bone._worldY += (ty - bone._worldY) * translateMix; + modified = true; + } + + if (scaleMix > 0) { + float s = MathUtil::sqrt(bone._a * bone._a + bone._c * bone._c); + + if (s > 0.00001f) s = (s + (MathUtil::sqrt(ta * ta + tc * tc) - s + _data._offsetScaleX) * scaleMix) / s; + bone._a *= s; + bone._c *= s; + s = MathUtil::sqrt(bone._b * bone._b + bone._d * bone._d); + + if (s > 0.00001f) s = (s + (MathUtil::sqrt(tb * tb + td * td) - s + _data._offsetScaleY) * scaleMix) / s; + bone._b *= s; + bone._d *= s; + modified = true; + } + + if (shearMix > 0) { + float b = bone._b, d = bone._d; + float by = MathUtil::atan2(d, b); + float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta) - (by - MathUtil::atan2(bone._c, bone._a)); + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r = by + (r + offsetShearY) * shearMix; + float s = MathUtil::sqrt(b * b + d * d); + bone._b = MathUtil::cos(r) * s; + bone._d = MathUtil::sin(r) * s; + modified = true; + } + + if (modified) bone._appliedValid = false; + } +} + +void TransformConstraint::applyRelativeWorld() { + float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; + Bone &target = *_target; + float ta = target._a, tb = target._b, tc = target._c, td = target._d; + float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; + float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + bool modified = false; + + if (rotateMix != 0) { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + float r = MathUtil::atan2(tc, ta) + offsetRotation; + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r *= rotateMix; + float cos = MathUtil::cos(r), sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + modified = true; + } + + if (translateMix != 0) { + float tx, ty; + target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); + bone._worldX += tx * translateMix; + bone._worldY += ty * translateMix; + modified = true; + } + + if (scaleMix > 0) { + float s = (MathUtil::sqrt(ta * ta + tc * tc) - 1 + _data._offsetScaleX) * scaleMix + 1; + bone._a *= s; + bone._c *= s; + s = (MathUtil::sqrt(tb * tb + td * td) - 1 + _data._offsetScaleY) * scaleMix + 1; + bone._b *= s; + bone._d *= s; + modified = true; + } + + if (shearMix > 0) { + float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta); + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + float b = bone._b, d = bone._d; + r = MathUtil::atan2(d, b) + (r - MathUtil::Pi / 2 + offsetShearY) * shearMix; + float s = MathUtil::sqrt(b * b + d * d); + bone._b = MathUtil::cos(r) * s; + bone._d = MathUtil::sin(r) * s; + modified = true; + } + + if (modified) bone._appliedValid = false; + } +} + +void TransformConstraint::applyAbsoluteLocal() { + float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; + Bone &target = *_target; + if (!target._appliedValid) target.updateAppliedTransform(); + + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + if (!bone._appliedValid) bone.updateAppliedTransform(); + + float rotation = bone._arotation; + if (rotateMix != 0) { + float r = target._arotation - rotation + _data._offsetRotation; + r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360; + rotation += r * rotateMix; + } + + float x = bone._ax, y = bone._ay; + if (translateMix != 0) { + x += (target._ax - x + _data._offsetX) * translateMix; + y += (target._ay - y + _data._offsetY) * translateMix; + } + + float scaleX = bone._ascaleX, scaleY = bone._ascaleY; + if (scaleMix != 0) { + if (scaleX > 0.00001f) scaleX = (scaleX + (target._ascaleX - scaleX + _data._offsetScaleX) * scaleMix) / scaleX; + if (scaleY > 0.00001f) scaleY = (scaleY + (target._ascaleY - scaleY + _data._offsetScaleY) * scaleMix) / scaleY; + } + + float shearY = bone._ashearY; + if (shearMix != 0) { + float r = target._ashearY - shearY + _data._offsetShearY; + r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360; + bone._shearY += r * shearMix; + } + + bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); + } +} + +void TransformConstraint::applyRelativeLocal() { + float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; + Bone &target = *_target; + if (!target._appliedValid) target.updateAppliedTransform(); + + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + if (!bone._appliedValid) bone.updateAppliedTransform(); + + float rotation = bone._arotation; + if (rotateMix != 0) rotation += (target._arotation + _data._offsetRotation) * rotateMix; + + float x = bone._ax, y = bone._ay; + if (translateMix != 0) { + x += (target._ax + _data._offsetX) * translateMix; + y += (target._ay + _data._offsetY) * translateMix; + } + + float scaleX = bone._ascaleX, scaleY = bone._ascaleY; + if (scaleMix != 0) { + if (scaleX > 0.00001f) scaleX *= ((target._ascaleX - 1 + _data._offsetScaleX) * scaleMix) + 1; + if (scaleY > 0.00001f) scaleY *= ((target._ascaleY - 1 + _data._offsetScaleY) * scaleMix) + 1; + } + + float shearY = bone._ashearY; + if (shearMix != 0) shearY += (target._ashearY + _data._offsetShearY) * shearMix; + + bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); + } +} + +bool TransformConstraint::isActive() { + return _active; +} + +void TransformConstraint::setActive(bool inValue) { + _active = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp new file mode 100644 index 0000000..52cf454 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -0,0 +1,112 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +#include + +using namespace spine; +TransformConstraintData::TransformConstraintData(const String &name) : + ConstraintData(name), + _target(NULL), + _rotateMix(0), + _translateMix(0), + _scaleMix(0), + _shearMix(0), + _offsetRotation(0), + _offsetX(0), + _offsetY(0), + _offsetScaleX(0), + _offsetScaleY(0), + _offsetShearY(0), + _relative(false), + _local(false) { +} + +Vector &TransformConstraintData::getBones() { + return _bones; +} + +BoneData *TransformConstraintData::getTarget() { + return _target; +} + +float TransformConstraintData::getRotateMix() { + return _rotateMix; +} + +float TransformConstraintData::getTranslateMix() { + return _translateMix; +} + +float TransformConstraintData::getScaleMix() { + return _scaleMix; +} + +float TransformConstraintData::getShearMix() { + return _shearMix; +} + +float TransformConstraintData::getOffsetRotation() { + return _offsetRotation; +} + +float TransformConstraintData::getOffsetX() { + return _offsetX; +} + +float TransformConstraintData::getOffsetY() { + return _offsetY; +} + +float TransformConstraintData::getOffsetScaleX() { + return _offsetScaleX; +} + +float TransformConstraintData::getOffsetScaleY() { + return _offsetScaleY; +} + +float TransformConstraintData::getOffsetShearY() { + return _offsetShearY; +} + +bool TransformConstraintData::isRelative() { + return _relative; +} + +bool TransformConstraintData::isLocal() { + return _local; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp new file mode 100644 index 0000000..2da77e8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -0,0 +1,148 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(TransformConstraintTimeline, CurveTimeline) + +const int TransformConstraintTimeline::ENTRIES = 5; +const int TransformConstraintTimeline::PREV_TIME = -5; +const int TransformConstraintTimeline::PREV_ROTATE = -4; +const int TransformConstraintTimeline::PREV_TRANSLATE = -3; +const int TransformConstraintTimeline::PREV_SCALE = -2; +const int TransformConstraintTimeline::PREV_SHEAR = -1; +const int TransformConstraintTimeline::ROTATE = 1; +const int TransformConstraintTimeline::TRANSLATE = 2; +const int TransformConstraintTimeline::SCALE = 3; +const int TransformConstraintTimeline::SHEAR = 4; + +TransformConstraintTimeline::TransformConstraintTimeline(int frameCount) : CurveTimeline(frameCount), + _transformConstraintIndex(0) +{ + _frames.setSize(frameCount * ENTRIES, 0); +} + +void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + TransformConstraint *constraintP = skeleton._transformConstraints[_transformConstraintIndex]; + TransformConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._rotateMix = constraint._data._rotateMix; + constraint._translateMix = constraint._data._translateMix; + constraint._scaleMix = constraint._data._scaleMix; + constraint._shearMix = constraint._data._shearMix; + return; + case MixBlend_First: + constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha; + constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha; + constraint._scaleMix += (constraint._data._scaleMix - constraint._scaleMix) * alpha; + constraint._shearMix += (constraint._data._shearMix - constraint._shearMix) * alpha; + return; + default: + return; + } + } + + float rotate, translate, scale, shear; + if (time >= _frames[_frames.size() - ENTRIES]) { + // Time is after last frame. + size_t i = _frames.size(); + rotate = _frames[i + PREV_ROTATE]; + translate = _frames[i + PREV_TRANSLATE]; + scale = _frames[i + PREV_SCALE]; + shear = _frames[i + PREV_SHEAR]; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + rotate = _frames[frame + PREV_ROTATE]; + translate = _frames[frame + PREV_TRANSLATE]; + scale = _frames[frame + PREV_SCALE]; + shear = _frames[frame + PREV_SHEAR]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + rotate += (_frames[frame + ROTATE] - rotate) * percent; + translate += (_frames[frame + TRANSLATE] - translate) * percent; + scale += (_frames[frame + SCALE] - scale) * percent; + shear += (_frames[frame + SHEAR] - shear) * percent; + } + + if (blend == MixBlend_Setup) { + TransformConstraintData &data = constraint._data; + constraint._rotateMix = data._rotateMix + (rotate - data._rotateMix) * alpha; + constraint._translateMix = data._translateMix + (translate - data._translateMix) * alpha; + constraint._scaleMix = data._scaleMix + (scale - data._scaleMix) * alpha; + constraint._shearMix = data._shearMix + (shear - data._shearMix) * alpha; + } else { + constraint._rotateMix += (rotate - constraint._rotateMix) * alpha; + constraint._translateMix += (translate - constraint._translateMix) * alpha; + constraint._scaleMix += (scale - constraint._scaleMix) * alpha; + constraint._shearMix += (shear - constraint._shearMix) * alpha; + } +} + +int TransformConstraintTimeline::getPropertyId() { + return ((int) TimelineType_TransformConstraint << 24) + _transformConstraintIndex; +} + +void TransformConstraintTimeline::setFrame(size_t frameIndex, float time, float rotateMix, float translateMix, float scaleMix, + float shearMix +) { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + ROTATE] = rotateMix; + _frames[frameIndex + TRANSLATE] = translateMix; + _frames[frameIndex + SCALE] = scaleMix; + _frames[frameIndex + SHEAR] = shearMix; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp new file mode 100644 index 0000000..09f9b06 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -0,0 +1,131 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(TranslateTimeline, CurveTimeline) + +const int TranslateTimeline::ENTRIES = 3; +const int TranslateTimeline::PREV_TIME = -3; +const int TranslateTimeline::PREV_X = -2; +const int TranslateTimeline::PREV_Y = -1; +const int TranslateTimeline::X = 1; +const int TranslateTimeline::Y = 2; + +TranslateTimeline::TranslateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) { + _frames.ensureCapacity(frameCount * ENTRIES); + _frames.setSize(frameCount * ENTRIES, 0); +} + +TranslateTimeline::~TranslateTimeline() { +} + +void TranslateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction +) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *boneP = skeleton._bones[_boneIndex]; + Bone &bone = *boneP; + if (!bone._active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone._x = bone._data._x; + bone._y = bone._data._y; + return; + case MixBlend_First: + bone._x += (bone._data._x - bone._x) * alpha; + bone._y += (bone._data._y - bone._y) * alpha; + default: {} + } + return; + } + + float x, y; + if (time >= _frames[_frames.size() - ENTRIES]) { + // Time is after last frame. + x = _frames[_frames.size() + PREV_X]; + y = _frames[_frames.size() + PREV_Y]; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + x = _frames[frame + PREV_X]; + y = _frames[frame + PREV_Y]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + x += (_frames[frame + X] - x) * percent; + y += (_frames[frame + Y] - y) * percent; + } + + switch (blend) { + case MixBlend_Setup: + bone._x = bone._data._x + x * alpha; + bone._y = bone._data._y + y * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone._x += (bone._data._x + x - bone._x) * alpha; + bone._y += (bone._data._y + y - bone._y) * alpha; + break; + case MixBlend_Add: + bone._x += x * alpha; + bone._y += y * alpha; + } +} + +int TranslateTimeline::getPropertyId() { + return ((int) TimelineType_Translate << 24) + _boneIndex; +} + +void TranslateTimeline::setFrame(int frameIndex, float time, float x, float y) { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + X] = x; + _frames[frameIndex + Y] = y; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Triangulator.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Triangulator.cpp new file mode 100644 index 0000000..04963b4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Triangulator.cpp @@ -0,0 +1,289 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +Triangulator::~Triangulator() { + ContainerUtil::cleanUpVectorOfPointers(_convexPolygons); + ContainerUtil::cleanUpVectorOfPointers(_convexPolygonsIndices); +} + +Vector &Triangulator::triangulate(Vector &vertices) { + size_t vertexCount = vertices.size() >> 1; + + Vector &indices = _indices; + indices.clear(); + indices.ensureCapacity(vertexCount); + indices.setSize(vertexCount, 0); + for (size_t i = 0; i < vertexCount; ++i) { + indices[i] = i; + } + + Vector &isConcaveArray = _isConcaveArray; + isConcaveArray.ensureCapacity(vertexCount); + isConcaveArray.setSize(vertexCount, 0); + for (size_t i = 0, n = vertexCount; i < n; ++i) { + isConcaveArray[i] = isConcave(i, vertexCount, vertices, indices); + } + + Vector &triangles = _triangles; + triangles.clear(); + triangles.ensureCapacity(MathUtil::max((int)0, (int)vertexCount - 2) << 2); + + while (vertexCount > 3) { + // Find ear tip. + size_t previous = vertexCount - 1, i = 0, next = 1; + + // outer: + while (true) { + if (!isConcaveArray[i]) { + int p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + float p1x = vertices[p1], p1y = vertices[p1 + 1]; + float p2x = vertices[p2], p2y = vertices[p2 + 1]; + float p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (size_t ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcaveArray[ii]) continue; + + int v = indices[ii] << 1; + float vx = vertices[v], vy = vertices[v + 1]; + if (positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (positiveArea(p2x, p2y, p3x, p3y, vx, vy)) { + goto break_outer; // break outer; + } + } + } + } + break; + } + break_outer: + + if (next == 0) { + do { + if (!isConcaveArray[i]) break; + i--; + } while (i > 0); + break; + } + + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + + // Cut ear tip. + triangles.add(indices[(vertexCount + i - 1) % vertexCount]); + triangles.add(indices[i]); + triangles.add(indices[(i + 1) % vertexCount]); + indices.removeAt(i); + isConcaveArray.removeAt(i); + vertexCount--; + + int previousIndex = (vertexCount + i - 1) % vertexCount; + int nextIndex = i == vertexCount ? 0 : i; + isConcaveArray[previousIndex] = isConcave(previousIndex, vertexCount, vertices, indices); + isConcaveArray[nextIndex] = isConcave(nextIndex, vertexCount, vertices, indices); + } + + if (vertexCount == 3) { + triangles.add(indices[2]); + triangles.add(indices[0]); + triangles.add(indices[1]); + } + + return triangles; +} + +Vector *> &Triangulator::decompose(Vector &vertices, Vector &triangles) { + Vector *> &convexPolygons = _convexPolygons; + for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) + _polygonPool.free(convexPolygons[i]); + convexPolygons.clear(); + + Vector *> &convexPolygonsIndices = _convexPolygonsIndices; + for (size_t i = 0, n = convexPolygonsIndices.size(); i < n; ++i) + _polygonIndicesPool.free(convexPolygonsIndices[i]); + convexPolygonsIndices.clear(); + + Vector *polygonIndices = _polygonIndicesPool.obtain(); + polygonIndices->clear(); + + Vector *polygon = _polygonPool.obtain(); + polygon->clear(); + + // Merge subsequent triangles if they form a triangle fan. + int fanBaseIndex = -1, lastwinding = 0; + for (size_t i = 0, n = triangles.size(); i < n; i += 3) { + int t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + float x1 = vertices[t1], y1 = vertices[t1 + 1]; + float x2 = vertices[t2], y2 = vertices[t2 + 1]; + float x3 = vertices[t3], y3 = vertices[t3 + 1]; + + // If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan). + bool merged = false; + if (fanBaseIndex == t1) { + size_t o = polygon->size() - 4; + Vector &p = *polygon; + int winding1 = winding(p[o], p[o + 1], p[o + 2], p[o + 3], x3, y3); + int winding2 = winding(x3, y3, p[0], p[1], p[2], p[3]); + if (winding1 == lastwinding && winding2 == lastwinding) { + polygon->add(x3); + polygon->add(y3); + polygonIndices->add(t3); + merged = true; + } + } + + // Otherwise make this triangle the new base. + if (!merged) { + if (polygon->size() > 0) { + convexPolygons.add(polygon); + convexPolygonsIndices.add(polygonIndices); + } else { + _polygonPool.free(polygon); + _polygonIndicesPool.free(polygonIndices); + } + + polygon = _polygonPool.obtain(); + polygon->clear(); + polygon->add(x1); + polygon->add(y1); + polygon->add(x2); + polygon->add(y2); + polygon->add(x3); + polygon->add(y3); + polygonIndices = _polygonIndicesPool.obtain(); + polygonIndices->clear(); + polygonIndices->add(t1); + polygonIndices->add(t2); + polygonIndices->add(t3); + lastwinding = winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + + if (polygon->size() > 0) { + convexPolygons.add(polygon); + convexPolygonsIndices.add(polygonIndices); + } + + // Go through the list of polygons and try to merge the remaining triangles with the found triangle fans. + for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) { + polygonIndices = convexPolygonsIndices[i]; + + if (polygonIndices->size() == 0) continue; + int firstIndex = (*polygonIndices)[0]; + int lastIndex = (*polygonIndices)[polygonIndices->size() - 1]; + + polygon = convexPolygons[i]; + size_t o = polygon->size() - 4; + Vector &p = *polygon; + float prevPrevX = p[o], prevPrevY = p[o + 1]; + float prevX = p[o + 2], prevY = p[o + 3]; + float firstX = p[0], firstY = p[1]; + float secondX = p[2], secondY = p[3]; + int winding0 = winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + + for (size_t ii = 0; ii < n; ++ii) { + if (ii == i) continue; + + Vector *otherIndicesP = convexPolygonsIndices[ii]; + Vector &otherIndices = *otherIndicesP; + + if (otherIndices.size() != 3) continue; + + int otherFirstIndex = otherIndices[0]; + int otherSecondIndex = otherIndices[1]; + int otherLastIndex = otherIndices[2]; + + Vector *otherPolyP = convexPolygons[ii]; + Vector &otherPoly = *otherPolyP; + + float x3 = otherPoly[otherPoly.size() - 2], y3 = otherPoly[otherPoly.size() - 1]; + + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue; + + int winding1 = winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + int winding2 = winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding0 && winding2 == winding0) { + otherPoly.clear(); + otherIndices.clear(); + polygon->add(x3); + polygon->add(y3); + polygonIndices->add(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + + // Remove empty polygons that resulted from the merge step above. + for (int i = (int)convexPolygons.size() - 1; i >= 0; --i) { + polygon = convexPolygons[i]; + if (polygon->size() == 0) { + convexPolygons.removeAt(i); + _polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.removeAt(i); + _polygonIndicesPool.free(polygonIndices); + } + } + + return convexPolygons; +} + +bool Triangulator::isConcave(int index, int vertexCount, Vector &vertices, Vector &indices) { + int previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + int current = indices[index] << 1; + int next = indices[(index + 1) % vertexCount] << 1; + + return !positiveArea(vertices[previous], vertices[previous + 1], + vertices[current], vertices[current + 1], + vertices[next], vertices[next + 1]); +} + +bool Triangulator::positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; +} + +int Triangulator::winding(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) { + float px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp new file mode 100644 index 0000000..89d34d8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -0,0 +1,182 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(TwoColorTimeline, CurveTimeline) + +const int TwoColorTimeline::ENTRIES = 8; +const int TwoColorTimeline::PREV_TIME = -8; +const int TwoColorTimeline::PREV_R = -7; +const int TwoColorTimeline::PREV_G = -6; +const int TwoColorTimeline::PREV_B = -5; +const int TwoColorTimeline::PREV_A = -4; +const int TwoColorTimeline::PREV_R2 = -3; +const int TwoColorTimeline::PREV_G2 = -2; +const int TwoColorTimeline::PREV_B2 = -1; +const int TwoColorTimeline::R = 1; +const int TwoColorTimeline::G = 2; +const int TwoColorTimeline::B = 3; +const int TwoColorTimeline::A = 4; +const int TwoColorTimeline::R2 = 5; +const int TwoColorTimeline::G2 = 6; +const int TwoColorTimeline::B2 = 7; + +TwoColorTimeline::TwoColorTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0) { + _frames.ensureCapacity(frameCount * ENTRIES); + _frames.setSize(frameCount * ENTRIES, 0); +} + +void TwoColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction +) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slotP = skeleton._slots[_slotIndex]; + Slot &slot = *slotP; + if (!slot._bone.isActive()) return; + + if (time < _frames[0]) { + // Time is before first frame. + switch (blend) { + case MixBlend_Setup: + slot.getColor().set(slot.getData().getColor()); + slot.getDarkColor().set(slot.getData().getDarkColor()); + return; + case MixBlend_First: { + Color &color = slot.getColor(); + color.r += (color.r - slot._data.getColor().r) * alpha; + color.g += (color.g - slot._data.getColor().g) * alpha; + color.b += (color.b - slot._data.getColor().b) * alpha; + color.a += (color.a - slot._data.getColor().a) * alpha; + + Color &darkColor = slot.getDarkColor(); + darkColor.r += (darkColor.r - slot._data.getDarkColor().r) * alpha; + darkColor.g += (darkColor.g - slot._data.getDarkColor().g) * alpha; + darkColor.b += (darkColor.b - slot._data.getDarkColor().b) * alpha; + return; + } + default: + return; + } + } + + float r, g, b, a, r2, g2, b2; + if (time >= _frames[_frames.size() - ENTRIES]) { + // Time is after last frame. + size_t i = _frames.size(); + r = _frames[i + PREV_R]; + g = _frames[i + PREV_G]; + b = _frames[i + PREV_B]; + a = _frames[i + PREV_A]; + r2 = _frames[i + PREV_R2]; + g2 = _frames[i + PREV_G2]; + b2 = _frames[i + PREV_B2]; + } else { + // Interpolate between the previous frame and the current frame. + size_t frame = (size_t)Animation::binarySearch(_frames, time, ENTRIES); + r = _frames[frame + PREV_R]; + g = _frames[frame + PREV_G]; + b = _frames[frame + PREV_B]; + a = _frames[frame + PREV_A]; + r2 = _frames[frame + PREV_R2]; + g2 = _frames[frame + PREV_G2]; + b2 = _frames[frame + PREV_B2]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + r += (_frames[frame + R] - r) * percent; + g += (_frames[frame + G] - g) * percent; + b += (_frames[frame + B] - b) * percent; + a += (_frames[frame + A] - a) * percent; + r2 += (_frames[frame + R2] - r2) * percent; + g2 += (_frames[frame + G2] - g2) * percent; + b2 += (_frames[frame + B2] - b2) * percent; + } + + if (alpha == 1) { + Color &color = slot.getColor(); + color.set(r, g, b, a); + + Color &darkColor = slot.getDarkColor(); + darkColor.set(r2, g2, b2, 1); + } else { + Color &light = slot._color; + Color &dark = slot._darkColor; + if (blend == MixBlend_Setup) { + light.set(slot._data._color); + dark.set(slot._data._darkColor); + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.add((r2 - dark.r) * alpha, (g2 - dark.g) * alpha, (b2 - dark.b) * alpha, 0); + } +} + +int TwoColorTimeline::getPropertyId() { + return ((int) TimelineType_TwoColor << 24) + _slotIndex; +} + +void TwoColorTimeline::setFrame(int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + R] = r; + _frames[frameIndex + G] = g; + _frames[frameIndex + B] = b; + _frames[frameIndex + A] = a; + _frames[frameIndex + R2] = r2; + _frames[frameIndex + G2] = g2; + _frames[frameIndex + B2] = b2; +} + +int TwoColorTimeline::getSlotIndex() { + return _slotIndex; +} + +void TwoColorTimeline::setSlotIndex(int inValue) { + assert(inValue >= 0); + _slotIndex = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Updatable.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Updatable.cpp new file mode 100644 index 0000000..4193473 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/Updatable.cpp @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(Updatable) + +Updatable::Updatable() { +} + +Updatable::~Updatable() { +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp new file mode 100644 index 0000000..9ff2cda --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -0,0 +1,169 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL(VertexAttachment, Attachment) + +VertexAttachment::VertexAttachment(const String &name) : Attachment(name), _worldVerticesLength(0), _deformAttachment(this), _id(getNextID()) { +} + +VertexAttachment::~VertexAttachment() { +} + +void VertexAttachment::computeWorldVertices(Slot &slot, Vector &worldVertices) { + computeWorldVertices(slot, 0, _worldVerticesLength, worldVertices, 0); +} + +void VertexAttachment::computeWorldVertices(Slot &slot, float *worldVertices) { + computeWorldVertices(slot, 0, _worldVerticesLength, worldVertices, 0); +} + +void VertexAttachment::computeWorldVertices(Slot &slot, size_t start, size_t count, Vector &worldVertices, size_t offset, size_t stride) { + computeWorldVertices(slot, start, count, worldVertices.buffer(), offset, stride); +} + +void VertexAttachment::computeWorldVertices(Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, size_t stride) { + count = offset + (count >> 1) * stride; + Skeleton &skeleton = slot._bone._skeleton; + Vector *deformArray = &slot.getDeform(); + Vector *vertices = &_vertices; + Vector &bones = _bones; + if (bones.size() == 0) { + if (deformArray->size() > 0) vertices = deformArray; + + Bone &bone = slot._bone; + float x = bone._worldX; + float y = bone._worldY; + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + for (size_t vv = start, w = offset; w < count; vv += 2, w += stride) { + float vx = (*vertices)[vv]; + float vy = (*vertices)[vv + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + + int v = 0, skip = 0; + for (size_t i = 0; i < start; i += 2) { + int n = bones[v]; + v += n + 1; + skip += n; + } + + Vector &skeletonBones = skeleton.getBones(); + if (deformArray->size() == 0) { + for (size_t w = offset, b = skip * 3; w < count; w += stride) { + float wx = 0, wy = 0; + int n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + Bone *boneP = skeletonBones[bones[v]]; + Bone &bone = *boneP; + float vx = (*vertices)[b]; + float vy = (*vertices)[b + 1]; + float weight = (*vertices)[b + 2]; + wx += (vx * bone._a + vy * bone._b + bone._worldX) * weight; + wy += (vx * bone._c + vy * bone._d + bone._worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } else { + for (size_t w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + float wx = 0, wy = 0; + int n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + Bone *boneP = skeletonBones[bones[v]]; + Bone &bone = *boneP; + float vx = (*vertices)[b] + (*deformArray)[f]; + float vy = (*vertices)[b + 1] + (*deformArray)[f + 1]; + float weight = (*vertices)[b + 2]; + wx += (vx * bone._a + vy * bone._b + bone._worldX) * weight; + wy += (vx * bone._c + vy * bone._d + bone._worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } +} + +int VertexAttachment::getId() { + return _id; +} + +Vector &VertexAttachment::getBones() { + return _bones; +} + +Vector &VertexAttachment::getVertices() { + return _vertices; +} + +size_t VertexAttachment::getWorldVerticesLength() { + return _worldVerticesLength; +} + +void VertexAttachment::setWorldVerticesLength(size_t inValue) { + _worldVerticesLength = inValue; +} + +VertexAttachment* VertexAttachment::getDeformAttachment() { + return _deformAttachment; +} + +void VertexAttachment::setDeformAttachment(VertexAttachment* attachment) { + _deformAttachment = attachment; +} + +int VertexAttachment::getNextID() { + static int nextID = 0; + + return (nextID++ & 65535) << 11; +} + +void VertexAttachment::copyTo(VertexAttachment* other) { + other->_bones.clearAndAddAll(this->_bones); + other->_vertices.clearAndAddAll(this->_vertices); + other->_worldVerticesLength = this->_worldVerticesLength; + other->_deformAttachment = this->_deformAttachment; +} diff --git a/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/VertexEffect.cpp b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/VertexEffect.cpp new file mode 100644 index 0000000..68e22e6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/3.8/spine-cpp/spine-cpp/src/spine/VertexEffect.cpp @@ -0,0 +1,159 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include + +using namespace spine; + +JitterVertexEffect::JitterVertexEffect(float jitterX, float jitterY): _jitterX(jitterX), _jitterY(jitterY) { +} + +void JitterVertexEffect::begin(Skeleton &skeleton) { + SP_UNUSED(skeleton); +} + +void JitterVertexEffect::transform(float &x, float &y, float &u, float &v, Color &light, Color &dark) { + SP_UNUSED(u); + SP_UNUSED(v); + SP_UNUSED(light); + SP_UNUSED(dark); + float jitterX = _jitterX; + float jitterY = _jitterY; + x += MathUtil::randomTriangular(-jitterX, jitterX); + y += MathUtil::randomTriangular(-jitterX, jitterY); +} + +void JitterVertexEffect::end() { +} + +void JitterVertexEffect::setJitterX(float jitterX) { + _jitterX = jitterX; +} + +float JitterVertexEffect::getJitterX() { + return _jitterX; +} + +void JitterVertexEffect::setJitterY(float jitterY) { + _jitterY = jitterY; +} + +float JitterVertexEffect::getJitterY() { + return _jitterY; +} + +SwirlVertexEffect::SwirlVertexEffect(float radius, Interpolation &interpolation): + _centerX(0), + _centerY(0), + _radius(radius), + _angle(0), + _worldX(0), + _worldY(0), + _interpolation(interpolation) { +} + +void SwirlVertexEffect::begin(Skeleton &skeleton) { + _worldX = skeleton.getX() + _centerX; + _worldY = skeleton.getY() + _centerY; +} + +void SwirlVertexEffect::transform(float &positionX, float &positionY, float &u, float &v, Color &light, Color &dark) { + SP_UNUSED(u); + SP_UNUSED(v); + SP_UNUSED(light); + SP_UNUSED(dark); + + float x = positionX - _worldX; + float y = positionY - _worldY; + float dist = (float)MathUtil::sqrt(x * x + y * y); + if (dist < _radius) { + float theta = _interpolation.interpolate(0, _angle, (_radius - dist) / _radius); + float cos = MathUtil::cos(theta), sin = MathUtil::sin(theta); + positionX = cos * x - sin * y + _worldX; + positionY = sin * x + cos * y + _worldY; + } +} + +void SwirlVertexEffect::end() { + +} + +void SwirlVertexEffect::setCenterX(float centerX) { + _centerX = centerX; +} + +float SwirlVertexEffect::getCenterX() { + return _centerX; +} + +void SwirlVertexEffect::setCenterY(float centerY) { + _centerY = centerY; +} + +float SwirlVertexEffect::getCenterY() { + return _centerY; +} + +void SwirlVertexEffect::setRadius(float radius) { + _radius = radius; +} + +float SwirlVertexEffect::getRadius() { + return _radius; +} + +void SwirlVertexEffect::setAngle(float angle) { + _angle = angle * MathUtil::Deg_Rad; +} + +float SwirlVertexEffect::getAngle() { + return _angle; +} + +void SwirlVertexEffect::setWorldX(float worldX) { + _worldX = worldX; +} + +float SwirlVertexEffect::getWorldX() { + return _worldX; +} + +void SwirlVertexEffect::setWorldY(float worldY) { + _worldY = worldY; +} + +float SwirlVertexEffect::getWorldY() { + return _worldY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0 b/DateToSpine/third_party/spine-runtimes/4.0 deleted file mode 160000 index 425ce41..0000000 --- a/DateToSpine/third_party/spine-runtimes/4.0 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 425ce416bb218b28caeec47b317aa57cd7140375 diff --git a/DateToSpine/third_party/spine-runtimes/4.0/CHANGELOG.md b/DateToSpine/third_party/spine-runtimes/4.0/CHANGELOG.md new file mode 100644 index 0000000..d34fdd9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/CHANGELOG.md @@ -0,0 +1,1174 @@ +# 4.0 + +## AS3 +**NOTE: Spine 4.0 will be the last release supporting spine-as3. Starting from Spine 4.1, spine-as3 will no longer be supported or maintained.** +* Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. +* Expose non-essential colors on bones, bounding box, clipping, and path attachments. +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +* Added support for reverse animation playback via `TrackEntry.reverse`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. + +### Starling +**NOTE: Spine 4.0 will be the last release supporting spine-starling. Starting from Spine 4.1, spine-starling will no longer be supported or maintained.** +* Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. +* Updated to Starling 2.6 and Air SDK 33. + +## C +* **Breaking change:** Removed `SPINE_SHORT_NAMES` define and C++ constructors. +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `spAnimationState_clearNext()` which removes the given `spTrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `spAtlasRegion.keyValues`. +* Added support for reverse animation playback via `spTrackEntry.reverse`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. + +### Cocos2d-Objc +**NOTE: Spine 4.0 will be the last release supporting spine-cocos2d-objc. Starting from Spine 4.1, spine-cocos2d-objc will no longer be supported or maintained.** + +### SFML +* Added `ikDemo()` in `main.cpp`. to illustrate how to drive a bone and IK chain through mouse movement. + +## C++ +* Removed dependency on STL throughout the code base, cutting down on the LOC that need parsing by 66%. +* Exposed `x` and `y` on `SkeletonData` through getters and setters. +* Expose non-essential colors on bones, bounding box, clipping, and path attachments. +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +* Added support for reverse animation playback via `TrackEntry.reverse`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. +* spine-cpp now requires C++11. + +### Cocos2d-x +* Added `IKExample` scene to illustrate how to drive a bone and IK chain through mouse movement. +* Added `SkeletonAnimation::setPreUpdateWorldTransformsListener()` and `SkeletonAnimation::setPostUpdateWorldTransformsListener()`. This allows users to modify bone transforms and other skeleton properties before and after the world transforms of all bones are calculated. See the `IKExample` for a usage example. + +### SFML +* Added `ikDemo()` in `main.cpp`. to illustrate how to drive a bone and IK chain through mouse movement. + +### UE4 +* `SpineWidget` now supports the full widget transform, including rendering scale/shear. +* Materials on `SkeletonRendererComponent` are now blueprint read and writeable. This allows setting dynamic material instances at runtime. +* Added `InitialSkin` property to `USpineWidget`. This allows previewing different skins in the UMG Designer. Initial skins can still be overridden via blueprint events such as `On Initialized`. +* **Breaking change:** `SpineWidget` no longer has the `Scale` property. Instead the size x/y properties can be used. +* Added `SetSlotColor` on `USpineSkeletonComponent` to easily set the color of a slot via blueprints. +* Changed mixes set on an `SkeletonDataAsset` will now be applied to instances of `USpineSkeletonComponent`. +* Generated normals are now correctly flipped for back faces. +* Modifying parent materials updates material instances accordingly. +* Only `.json` files that are actually encoding Spine skeletons will be loaded. Other `.json` files will be left to other importers. +* Updated example project to UE 4.27. + + +## C# ## +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +* Added support for reverse animation playback via `TrackEntry.Reverse`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. +* **Breaking change:** Removed `SkeletonData` and `Skeleton` methods: `FindBoneIndex`, `FindSlotIndex`. Bones and slots have an `Index` field that should be used instead. Be sure to check for e.g. `bone == null` accordingly before accessing `bone.Index`. + +### Unity + +* **Officially supported Unity versions are 2017.1-2022.1**. +* **Breaking changes** + * Removed all `Spine.Unity.AttachmentTools.SkinUtilities` Skin extension methods. These have become obsoleted and error-prone since the introduction of the new Skin API in 3.8. To fix any compile errors, replace any usage of `Skin` extension methods with their counterparts, e.g. replace occurrances of `skin.AddAttachments()` with `skin.AddSkin()`. Please see the example scene `Mix and Match Skins` on how to use the new Skin API to combine skins, or the updated old example scenes `Mix and Match` and `Mix and Match Equip` on how you can update an existing project using the old workflow. If you are using `skeletonAnimation.Skeleton.UnshareSkin()` in your code, you can replace it with `Skin customSkin = new Skin("custom skin"); customSkin.AddSkin(skeletonAnimation.Skeleton.Skin);`. + * `Skin.GetAttachments()` has been replaced by `Skin.Attachments`, returning an `ICollection`. This makes access more consistent and intuitive. To fix any compile errors, replace any occurrances of `Skin.GetAttachments()` by `Skin.Attachments`. + * Removed redundant `Spine.Unity.AttachmentTools.AttachmentCloneExtensions` extension methods `Attachment.GetCopy()` and `Attachment.GetLinkedMesh()`. To fix any compile errors, replace any occurrances with `Attachment.Copy()` and `Attachment.NewLinkedMesh()`. + * Removed `Spine.Unity.AttachmentTools.AttachmentRegionExtensions` extension methods `Attachment.GetRegion()`. Use `Attachment.RendererObject as AtlasRegion` instead. + * Removed redundant `Spine.SkeletonExtensions` extension methods: + Replace: + * `Skeleton.SetPropertyToSetupPose()` + * `Skeleton.SetDrawOrderToSetupPose()` + * `Skeleton.SetSlotAttachmentsToSetupPose()` + * `Skeleton.SetSlotAttachmentToSetupPose()` + + with `Skeleton.SetSlotsToSetupPose()`. + Replace: + * `Slot.SetColorToSetupPose()` + * `Slot.SetAttachmentToSetupPose()` + + with `Slot.SetToSetupPose()`. + + Also removed less commonly used extension methods: + `TrackEntry.AllowImmediateQueue()`, `Animation.SetKeyedItemsToSetupPose()` and `Attachment.IsRenderable()`. + + * **`SkeletonGraphic` now no longer uses a `RawImage` component at each submesh renderer** GameObject when `allowMultipleCanvasRenderers` is true. Instead, a new custom component `SkeletonSubmeshGraphic` is used which is more resource friendly. Replacement of these components will be performed automatically through editor scripting, saving scenes or prefabs will persist the upgrade. + * **Linear color space:** Previously Slot colors were not displayed the same in Unity as in the Spine Editor. This is now fixed at all shaders, including URP and LWRP shaders. See section *Additions* below for more details. If you have tweaked Slot colors to look correct in `Linear` color space in Unity but incorrect in Spine, you might want to adjust the tweaked colors. Slot colors displayed in Unity should now match colors displayed in the Spine Editor when configured to display as `Linear` color space in the Spine Editor Settings. + * **Additive Slots have always been lit** before they were written to the target buffer. Now all lit shaders provide an additional parameter `Light Affects Additive` which defaults to `false`, as it is the more intuitive default value. You can enable the old behaviour by setting this parameter to `true`. + * **Corrected blending behaviour of all `Sprite` shaders** in `Premultiply Alpha` blend mode (including URP and LWRP packages). Previously vertex color alpha was premultiplied again, even though `Premultiply Alpha` blend mode assumes PMA texture and PMA vertex color input. Slot-alpha blending will thus be correctly lighter after upgrading to 4.0. If you have compensated this problem by disabling `Advanced - PMA Vertex Colors` you can now re-enable this parameter, also allowing for rendering Additive slots in a single pass. + * **Corrected all `Outline` shaders outline thickness** when `Advanced - Sample 8 Neighbourhood` is disabled (thus using `4 Neighbourhood`). Previously weighting was incorrectly thick (4x as thick) compared to 8 neighbourhood, now it is more consistent. This might require adjustment of all your outline materials where `Sample 8 Neighbourhood` is disabled to restore the previous outline thickness, by adjusting the `Outline Threshold` parameter through adding a `/4` to make the threshold 4 times smaller. + * Reverted changes: `BoneFollower` property `followLocalScale` has intermediately been renamed to `followScale` but was renamed back to `followLocalScale`. Serialized values (scenes and prefabs) will automatically be upgraded, only code accessing `followScale` needs to be adapted. + * Fixed Timeline not pausing (and resuming) clip playback on Director pause, this is now the default behaviour. If you require the old behaviour (e.g. to continue playing an idle animation during Director pause), there is now an additional parameter `Don't Pause with Director` provided that can be enabled for each Timeline clip. + * Fixed Timeline `Spine AnimationState Clips` ignoring empty space on the Timeline after a clip's end. Timeline clips now also offer `Don't End with Clip` and `Clip End Mix Out Duration` parameters if you prefer the old behaviour of previous versions. By default when empty space follows the clip on the timeline, the empty animation is set on the track with a MixDuration of `Clip End Mix Out Duration`. Set `Don't End with Clip` to `true` to continue playing the clip's animation instead and mimic the old 3.8 behaviour. If you prefer pausing the animation instead of mixing out to the empty animation, set `Clip End Mix Out Duration` to a value less than 0, then the animation is paused instead. + +* **Additions and Improvements** + * Additional **Fix Draw Order** parameter at SkeletonRenderer, defaults to `disabled` (previous behaviour). + Applies only when 3+ submeshes are used (2+ materials with alternating order, e.g. "A B A"). + If `true`, MaterialPropertyBlocks are assigned at each material to prevent aggressive batching of submeshes + by e.g. the LWRP renderer, leading to incorrect draw order (e.g. "A1 B A2" changed to "A1A2 B"). + You can leave this parameter disabled when everything is drawn correctly to save the additional performance cost. + * **Additional Timeline features.** SpineAnimationStateClip now provides a `Speed Multiplier`, a start time offset parameter `Clip In`, support for blending successive animations by overlapping tracks. An additional `Use Blend Duration` parameter *(defaults to true)* allows for automatic synchronisation of MixDuration with the current overlap blend duration. An additional Spine preferences parameter `Use Blend Duration` has been added which can be disabled to default to the previous behaviour before this update. + * Additional `SpriteMask and RectMask2D` example scene added for demonstration of mask setup and interaction. + * `Real physics hinge chains` for both 2D and 3D physics. The [SkeletonUtilityBone](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) Inspector provides an interface to create 2D and 3D hinge chains. Previously created chains have only been respecting gravity, but not momentum of the skeleton or parent bones. The new physics rig created when pressing `Create 3D Hinge Chain` and `Create 2D Hinge Chain` creates a more complex setup that also works when flipping the skeleton. Note that the chain root node is no longer parented to bones of the skeleton. This is a requirement in Unity to have momentum applied properly - do not reparent the chain root to bones of your skeleton, or you will loose any momentum applied by the skeleton's movement. + * `Outline rendering functionality for all shaders.` Every shader now provides an additional set of `Outline` parameters to enable custom outline rendering. When outline rendering is enabled via the `Material` inspector, it automatically switches the shader to the respective `Spine/Outline` shader variant. Outlines are generated by sampling neighbour pixels, so be sure to add enough transparent padding when exporting your atlas textures to fit the desired outline width. In order to enable outline rendering at a skeleton, it is recommended to first prepare an additional outline material copy and then switch the material of the target skeleton to this material. This prevents unnecessary additional runtime material copies and drawcalls. Material switching can be prepared via a [SkeletonRendererCustomMaterials](http://esotericsoftware.com/spine-unity#SkeletonRendererCustomMaterials) component and then enabled or disabled at runtime. Alternatively, you can also directly modify the `SkeletonRenderer.CustomMaterialOverride` property. + Outline rendering is fully supported on `SkeletonGraphic` shaders as well. + * Added `SkeletonRenderer.EditorSkipSkinSync` scripting API property to be able to set custom skins in editor scripts. Enable this property when overwriting the Skeleton's skin from an editor script. Without setting this parameter, changes will be overwritten by the next inspector update. Only affects Inspector synchronisation of skin with `initialSkinName`, not startup initialization. + * `AtlasUtilities.GetRepackedAttachments()` and `AtlasUtilities.GetRepackedSkin()` provide support for additional texture channels such as normal maps via the optional parameter `additionalTexturePropertyIDsToCopy `. See the spine-unity runtime documentation, section [Combining Skins - Advanced - Runtime Repacking with Normalmaps](http://esotericsoftware.com/spine-unity#Combining-Skins) for further info and example usage code. + * `BoneFollower` can now optionally follow (uniform) world scale of the reference bone. There is now a `Mode` dropdown selector in the Inspector which can be set to either `Local` or `World Uniform`. + * All `Spine/SkeletonGraphic` shaders now provide a parameter `CanvasGroup Compatible` which can be enabled to support `CanvasGroup` alpha blending. For correct results, you should then disable `Pma Vertex Colors` in the `SkeletonGraphic` Inspector, in section `Advanced` (otherwise Slot alpha will be applied twice). + * **Now supporting Universal Render Pipeline (URP), including the 2D Renderer pipeline, through an additional UPM package.** + * **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + * a) the `Packages` directory in your project where it will automatically be loaded, or + * b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + The Project panel should now show an entry `Spine Universal RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + * **Usage:** The package provides two shaders specifically built for the universal render pipeline: + * `Universal Render Pipeline/Spine/Skeleton`, as a universal variant of the `Spine/Skeleton` shader, + * `Universal Render Pipeline/Spine/Skeleton Lit`, as a universal variant of the `Spine/Skeleton Lit` shader, + * `Universal Render Pipeline/Spine/Sprite`, as a universal variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the universal render pipeline, + * `Universal Render Pipeline/2D/Spine/Skeleton Lit`, as a universal 2D Renderer variant of the `Spine/Skeleton Lit` shader, and + * `Universal Render Pipeline/2D/Spine/Sprite`, as a universal 2D Renderer variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders. + The shaders can be assigned to materials as usual and will respect your settings of the assigned `UniversalRenderPipelineAsset` under `Project Settings - Graphics`. + * **Restrictions** As all Spine shaders, the URP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + * **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.urp-shaders-3.8/Examples/URP Shaders.unity` that demonstrates usage of the URP shaders. + * Spine Preferences now provide an **`Atlas Texture Settings`** parameter for applying customizable texture import settings at all newly imported Spine atlas textures. + When exporting atlas textures from Spine with `Premultiply alpha` enabled (the default), you can leave it at `PMATexturePreset`. If you have disabled `Premultiply alpha`, set it to the included `StraightAlphaTexturePreset` asset. You can also create your own `TextureImporter` `Preset` asset and assign it here (include `PMA` or `Straight` in the name). In Unity versions before 2018.3 you can use `Texture2D` template assets instead of the newer `Preset` assets. Materials created for imported textures will also have the `Straight Alpha Texture` parameter configured accordingly. + * All `Sprite` shaders (including URP and LWRP extension packages) now provide an additional `Fixed Normal Space` option `World-Space`. PReviously options were limited to `View-Space` and `Model-Space`. + * `SkeletonGraphic` now fully supports [`SkeletonUtility`](http://esotericsoftware.com/spine-unity#SkeletonUtility) for generating a hierarchy of [`SkeletonUtilityBones`](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) in both modes `Follow` and `Override`. This also enables creating hinge chain physics rigs and using `SkeletonUtilityConstraints` such as `SkeletonUtilityGroundConstraint` and `SkeletonUtilityEyeConstraint` on `SkeletonGraphic`. + * Added **native support for slot blend modes** `Additive`, `Multiply` and `Screen` with automatic assignment at newly imported skeleton assets. `BlendModeMaterialAssets` are now obsolete and replaced by the native properties at `SkeletonDataAsset`. The `SkeletonDataAsset` Inspector provides a new `Blend Modes - Upgrade` button to upgrade an obsolete `BlendModeMaterialAsset` to the native blend modes properties. This upgrade will be performed automatically on imported and re-imported assets. + * `BoneFollower` and `BoneFollowerGraphic` components now provide better support for following bones when the skeleton's Transform is not the parent of the follower's Transform. Previously e.g. rotating a common parent Transform did not lead to the desired result, as well as negatively scaling a skeleton's Transform when it is not a parent of the follower's Transform. + * **Linear color space:** Previously Slot colors were not displayed the same in Unity as in the Spine Editor (when configured to display as `Linear` color space in Spine Editor Settings). This is now fixed at all shaders, including URP and LWRP shaders. + * All Spine shaders (also including URP and LWRP shaders) now support `PMA Vertex Colors` in combination with `Linear` color space. Thus when using Spine shaders, you should always enable `PMA Vertex Colors` at the `SkeletonRenderer` component. This allows using single pass `Additive` Slots rendering. Note that textures shall still be exported as `Straight alpha` when using `Linear` color space, so combine `PMA Vertex Colors` with `Straight Texture`. All `Sprite` shaders now provide an additional blend mode for this, named `PMA Vertex, Straight Texture` which shall be the preferred Sprite shader blend mode in `Linear` color space. + * Additive Slots have always been lit before they were written to the target buffer. Now all lit shaders provide an additional parameter `Light Affects Additive` which defaults to `false`, as it is the more intuitive default value. You can enable the old behaviour by setting this parameter to `true`. + * `SkeletonRootMotion` and `SkeletonMecanimRootMotion` components now support arbitrary bones in the hierarchy as `Root Motion Bone`. Previously there were problems when selecting a non-root bone as `Root Motion Bone`. `Skeleton.ScaleX` and `.ScaleY` and parent bone scale is now respected as well. + * URP and LWRP `Sprite` and `SkeletonLit` shaders no longer require `Advanced - Add Normals` enabled to properly cast and receive shadows. It is recommended to disable `Add Normals` if normals are otherwise not needed. + * Added an example component `RootMotionDeltaCompensation` located in `Spine Examples/Scripts/Sample Components` which can be used for applying simple delta compensation. You can enable and disable the component to toggle delta compensation of the currently playing animation on and off. + * `SkeletonRagdoll` and `SkeletonRagdoll2D` now support bone scale at any bone in the skeleton hierarchy. This includes negative scale and root bone scale. + * `Attachment.GetRemappedClone(Sprite)` method now provides an additional optional parameter `useOriginalRegionScale`. When set to `true`, the replaced attachment's scale is used instead of the Sprite's `Pixel per Unity` setting, allowing for more consistent scaling. *Note:* When remapping Sprites, be sure to set the Sprite's `Mesh Type` to `Full Rect` and not `Tight`, otherwise the scale will be wrong. + * `SkeletonGraphic` now **supports all Slot blend modes** when `Advanced - Multiple Canvas Renderers` is enabled in the Inspector. The `SkeletonGraphic` Inspector now provides a `Blend Mode Materials` section where you can assign `SkeletonGraphic` materials for each blend mode, or use the new default materials. New `SkeletonGraphic` shaders and materials have been added for each blend mode. The `BlendModes.unity` example scene has been extended to demonstrate this new feature. For detailed information see the [`SkeletonGraphic documentation page`](http://esotericsoftware.com/spine-unity#Parameters). + * Timeline clips now also offer `Don't End with Clip` and `Clip End Mix Out Duration` parameters. By default when empty space follows the clip on the timeline, the empty animation is set on the track with a MixDuration of `Clip End Mix Out Duration`. Set `Don't End with Clip` to `true` to continue playing the clip's animation instead and mimic the old 3.8 behaviour. If you prefer pausing the animation instead of mixing out to the empty animation, set `Clip End Mix Out Duration` to a value less than 0, then the animation is paused instead. + * Prefabs containing `SkeletonRenderer`, `SkeletonAnimation` and `SkeletonMecanim` now provide a proper Editor preview, including the preview thumbnail. + * `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`) now provide a property `Advanced - Fix Prefab Override MeshFilter`, which when enabled fixes the prefab always being marked as changed. It sets the MeshFilter's hide flags to `DontSaveInEditor`. Unfortunately this comes at the cost of references to the `MeshFilter` by other components being lost, therefore this parameter defaults to `false` to keep the safe existing behaviour. + * `BoundingBoxFollower` and `BoundingBoxFollowerGraphic` now provide previously missing `usedByEffector` and `usedByComposite` parameters to be set at all generated colliders. + * `BoneFollower` and `BoneFollowerGraphic` now provide an additional `Follow Parent World Scale` parameter to allow following simple scale of parent bones (rotated/skewed scale can't be supported). + * Improved `Advanced - Fix Prefab Override MeshFilter` property for `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`), now providing an additional option to use a global value which can be set in `Edit - Preferences - Spine`. + * Timeline naming improvements: `Spine AnimationState Clip` Inspector parameter `Custom Duration` changed and inverted to `Default Mix Duration` for more clarity. Shortened all Timeline add track menu entries from: `Spine.Unity.Playables - ` to `Spine - `, `Spine Animation State Track` to `SkeletonAnimation Track`, `Spine AnimationState Graphic Track` to `SkeletonGraphic Track`, and `Spine Skeleton Flip Track` to `Skeleton Flip Track`. + * Timeline track appearance and Inspector: Tracks now show icons and track colors to make them easier to distinguish. When a Track is selected, the Inspector now shows an editable track name which was previously only editable at the Timeline asset. + * Added example component `SkeletonRenderTexture` to render a `SkeletonRenderer` to a `RenderTexture`, mainly for proper transparency. Added an example scene named `RenderTexture FadeOut Transparency` that demonstrates usage for a fadeout transparency effect. + * Added another fadeout example component named `SkeletonRenderTextureFadeout` which takes over transparency fadeout when enabled. You can use this component as-is, attach it in disabled state and enable it to start a fadeout effect. + * Timeline clips now offer an additional `Alpha` parameter for setting a custom constant mix alpha value other than 1.0, just as `TrackEntry.Alpha`. Defaults to 1.0. + +* **Changes of default values** + +* **Deprecated** + +* **Restructuring (Non-Breaking)** + +### XNA/MonoGame +* Added normalmap support via `SpineEffectNormalmap` and support for loading multiple texture layers following a suffix-pattern. Please see the example code on how to use them. +* Added `Z` property to `SkeletonRenderer` to provide a constant Z offset that's added to all vertices. +* Added `ZSpacing` property to `SkeletonRenderer` to allow specifying the distance on the z-axis between attachments. +* SkeletonDebugRenderer bone color attributes are now public and modifiable by user. + + +## Java +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `Region.names` and `Region.values`. +* Added support for reverse animation playback via `TrackEntry.getReverse()` and `TrackEntry.setReverse()`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. +* **Breaking change:** Removed `SkeletonData` and `Skeleton` methods: `findBoneIndex`, `findSlotIndex`. Bones and slots have an `index` field that should be used instead. + +### libGDX +* Exposed colors in `SkeletonRendererDebug`. +* Updated to libGDX 1.10.0. + +## Lua +* Expose non-essential colors on bones, bounding box, clipping, and path attachments. +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +* Added support for reverse animation playback via `TrackEntry.reverse`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. + +### Love2D + +### Corona +* **Breaking change:** spine-corona has been renamed to spine-solar2d. Change your `require "spine-corona.spine"` statements to `require "spine-solar2d.spine"` + +## Typescript/Javascript +* **Breaking change:** refactored to ECMAScript modules. See this [blog post](http://esotericsoftware.com/blog/spine-goes-npm) as well as the updated [README.md](spine-ts/README.md). +* **Breaking change:** the `build/` folder and compiled artifacts are no longer part of the repository. Instead, `npm run build` in `spine-ts/` to generate ECMAScript modules and IIFE modules in `spine-/dist`. +* **Breaking change:** the `.npmignore` and `package.json` files in the root directory have been deleted. Use the corresponding files in `spine-ts/` instead, or better, depend on the packages from the NPM registry. +* Updated runtime to be compatible with TypeScript 3.6.3. +* Added `AssetManager#setRawDataURI(path, data)`. Allows to set raw data URIs for a specific path, which in turn enables embedding assets into JavaScript/HTML. +* Expose non-essential colors on bones, bounding box, clipping, and path attachments. +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +* Added support for reverse animation playback via `TrackEntry.reverse`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. +* `AssetManager` constructor now takes an option `Downloader` instance. Used to download assets only once and share them between `AssetManager` instances. +* Added web worker support to `AssetManager`. +* Added various default parameters to `AnimationState` methods for ease of use. +* Added `SpineCanvas`, a simpler way to render a scene via spine-webgl. See `spine-ts/spine-webgl/examples/barebones.html` and `spine-ts/spine-webgl/examples/mix-and-match.html`. + +### WebGL backend +* **Breaking change:** removed `SharedAssetManager`. Use `AssetManager` with a shared `Downloader` instance instead. +* **Breaking change:** the global object `spine.webgl` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.webgl.` in your source code with `spine.`. + +### Canvas backend +* Renderer now accounts for whitespace stripping. +* **Breaking change:** the global object `spine.canvas` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.canvas.` in your source code with `spine.`. + +### Three.js backend +* `SkeletonMesh` now takes an optional `SkeletonMeshMaterialParametersCustomizer` function that allows you to modify the `ShaderMaterialParameters` before the material is finalized. Use it to modify things like THREEJS' `Material.depthTest` etc. See #1590. +* **Breaking change:** the global object `spine.canvas` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.threejs.` in your source code with `spine.`. +* **Breaking change:** the default fragment shader of `SkeletonMeshMaterial` now explicitely discards fragments with alpha < 0.5. See https://github.com/EsotericSoftware/spine-runtimes/issues/1985 +* **Breaking change:** reversal of the previous breaking change: the default fragment shader of `SkeletonMeshMaterial` does no longer discard fragments with alpha < 0.5. Pass a `SkeletonMeshMaterialParametersCustomizer` to the `SkeletonMesh` constructor, and modify `parameters.alphaTest` to be > 0. + +### Player +* Added `SpinePlayerConfig.rawDataURIs`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. See the example for a demonstration. +* Added `SpinePlayerConfig.frame`. If set, the callback is called each frame, before the skeleton is posed or drawn. +* Added `SpinePlayerConfig.update`. If set, the callback is called each frame, just after the skeleton is posed. +* Added `SpinePlayerConfig.draw`. If set, the callback is called each frame, just after the skeleton is drawn. +* Added `SpinePlayerConfig.downloader`. The `spine.Downloader` instance can be shared between players so assets are only downloaded once. +* If `SpinePlayerConfig.jsonURL` ends with an anchor, the anchor text is used to find the skeleton in the specified JSON file. +* Added `SpinePlayer.dispose()`, disposes all CPU and GPU side resources, removes all listeners, and removes the player DOM from the parent. + +# 3.8 + +## AS3 +* **Breaking changes** + * Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + * Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + * Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. + +* **Additions** + * Added `SkeletonBinary` to load binary `.skel` files. See `MixAndMatchExample.as` in `spine-startling-example`. + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin#getAttachments()`. Returns all attachments in the skin. + * Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `Skin#addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin#copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### Starling +* Added `MixAndMatchExample.as` to demonstrate the new Skin API additions and how to load binary `.skel` files. +* Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. + +## C +* **Breaking changes** + * Renamed `spSlot#attachmentVertices` to `spSlot#deform`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `spSkin_addAttachment()` to `Skin#spSkin_addAttachment()`. + * Removed `spVertexAttachment_applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `spDeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `spMeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * Added `x` and `y` coordinates for setup pose AABB in `spSkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `spSkin_getAttachments()`. Returns all attachments in the skin. + * Added `spSkin_getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `spSkin_addSkin(spSkin* skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `spSkin_copySkin(spSkin* skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `spVertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * All attachments inserted into skins are reference counted. When the last skin referencing an attachment is disposed, the attachment will also be disposed. + * Added `spAttachment_copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `spMeshAttachment_newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### Cocos2d-Objc +* Added mix-and-match example to demonstrate the new Skin API. +* Added `IKExample`. +* Added `SkeletonAnimation preUpdateWorldTransformsListener` and `SkeletonAnimation postUpdateWorldTransformsListener`. When set, these callbacks will be invokved before and after the skeleton's `updateWorldTransforms()` method is called. See the `IKExample` how it can be used. + +### SFML +* Added mix-and-match example to demonstrate the new Skin API. +* Added `IKExample`. + +## C++ +* **Breaking Changes** + * Renamed `Slot::getAttachmentVertices()` to `Slot::getDeform()`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin::addAttachment()` to `Skin::setAttachment()`. + * Removed `VertexAttachment::applyDeform()` and replaced it with `VertexAttachment::getDeformAttachment()`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `_inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * `AnimationState` and `TrackEntry` now also accept a subclass of `AnimationStateListenerObject` as a listener for animation events in the overloaded `setListener()` method. + * `SkeletonBinary` and `SkeletonJson` now parse and set all non-essential data like audio path. + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin#getAttachments()`. Returns all attachments in the skin. + * Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `Skin#addSkin(Skin &skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin#copySkin(Skin &skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * All attachments inserted into skins are reference counted. When the last skin referencing an attachment is disposed, the attachment will also be disposed. + * Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + * Exposed `x` and `y` on `SkeletonData` through getters and setters. + +### Cocos2d-x +* Updated to cocos2d-x 3.17.1 +* Added mix-and-match example to demonstrate the new Skin API. +* Exmaple project requires Visual Studio 2019 on Windows +* Added `IKExample`. +* Added `SkeletonAnimation::setPreUpdateWorldTransformsListener()` and `SkeletonAnimation::setPreUpdateWorldTransformsListener()`. When set, these callbacks will be invokved before and after the skeleton's `updateWorldTransforms()` method is called. See the `IKExample` how it can be used. + +### SFML +* Added mix-and-match example to demonstrate the new Skin API. + +### UE4 +* Added `bAutoPlaying` flag to `USpineSkeletonAnimationComponent`. When `false`, the component will not update the internal animation state and skeleton. +* Updated example project to UE 4.22. +* (Re-)Importing Spine assets will perform a version compatibility check and alert users about mismatches in editor mode. +* `USpineSkeletonRendererComponent` allows passing a `USpineSkeletonComponent` to update it. This way, the renderer component can be used without a skeleton component on the same actor. +* Added blueprint-callable methods to `SpineSkeletonComponent` and `SpineSkeletonAnimationComponent` to query and set skins, and enumerate bones, slots, and animations. +* Extended skeleton data editor preview. The preview now shows bones, slots, animations, and skins found in the skeleton data. See this [blog post](http://esotericsoftware.com/blog/Unreal-Engine-4-quality-of-life-improvements). +* Added preview animation and skin fields, allowing you to preview animations and skins right in the editor. See this [blog post](http://esotericsoftware.com/blog/Unreal-Engine-4-quality-of-life-improvements). +* Removed dependency on `RHI`, `RenderCore`, and `ShaderCore`. +* Re-importing atlases and their textures now works consistently in all situations. +* Added mix-and-match example to demonstrate the new Skin API. +* Materials on `SkeletonRendererComponent` are now blueprint read and writeable. This allows setting dynamic material instances at runtime. +* Added `InitialSkin` property to `USpineWidget`. This allows previewing different skins in the UMG Designer. Initial skins can still be overridden via blueprint events such as `On Initialized`. + +## C# ## +* **Breaking changes** + * **Changed `IkConstraintData.Bones` type from `List` to `ExposedList`** for unification reasons. *Note: this modification will most likely not affect user code.* + * Renamed `Slot.AttachmentVertices` to `Slot.Deform`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin.AddAttachment()` to `Skin.SetAttachment()`. + * Removed `FindAttachmentsForSlot(int slotIndex, List attachments)` and `FindNamesForSlot (int slotIndex, List names)` and replaced it with `Skin.GetAttachments(int slotIndex, List attachments)` which returns the combined `SkinEntry` object holding both name and attachment. + * Removed `VertexAttachment.ApplyDeform()` and replaced it with `VertexAttachment.DeformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin.GetAttachments()`. Returns all attachments in the skin. + * Added `Skin.GetAttachments(int slotIndex, List attachments)`. Returns all attachements in the skin for the given slot index. This method replaces `FindAttachmentsForSlot` and `FindNamesForSlot`. + * Added `Skin.AddSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin.CopySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment.Copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment.NewLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### Unity + +* **Breaking changes** + * **Officially supported Unity versions are 2017.1-2020.2**. + * **Spine `.asmdef` files are again active by default**. They have previously been deactivated to `.txt` extension which is now no longer necessary. + * **Removed PoseSkeleton() and PoseWithAnimation()** extension methods to prevent issues where animations are not mixed out. Problem was that these methods did not set AnimationState, leaving incorrect state at e.g. attachments enabled at slots when starting subsequent animations. As a replacement you can use `AnimationState.ClearTrack(0);` followed by `var entry = AnimationState.SetAnimation(0, animation, loop); entry.TrackTime = time` to achieve similar behaviour. + * **The `Shadow alpha cutoff` shader parameter is now respecting slot-color alpha** values at all Spine shaders. A fragment's texture color alpha is multiplied with slot-color alpha before the result is tested against the `Shadow alpha cutoff` threshold. + * **Removed redundant `Attachment.GetClone()` and `MeshAttachment.GetLinkedClone()` extension methods**. Use methods `Attachment.Copy` and `MeshAttachment.NewLinkedMesh()` instead. + * **Renamed extension method `Attachment.GetClone(bool cloneMeshesAsLinked)` to `Attachment.GetCopy(bool cloneMeshesAsLinked)`** to follow the naming scheme of the Spine API. + * `SkeletonDataAsset.atlasAssets` is now an array of the base class `AtlasAssetBase` instead of `SpineAtlasAsset`, which provides `IEnumerable<> Materials` instead of `List<> materials`. Replace any access via `atlasAsset.materials[0]` with `atlasAsset.Materials.First()` and add a `using System.Linq;` statement. + * **Changed `MeshAttachment.GetLinkedMesh()` method signatures:** removed optional parameters `bool inheritDeform = true, bool copyOriginalProperties = false`. + * Changed namespace `Spine.Unity.Modules` to `Spine.Unity` and `Spine.Unity.Examples` after restructuring (see section below) in respective classes: + * When receiving namespace related errors, replace using statements of `using Spine.Unity.Modules.AttachmentTools;` with `using Spine.Unity.AttachmentTools;`. You can remove `using Spine.Unity.Modules;` statements when a `using Spine.Unity` statement is already present in the file. + * `AttachmentTools`, `SkeletonPartsRenderer`, `SkeletonRenderSeparator`, `SkeletonRendererCustomMaterials` changed to namespace `Spine.Unity`. + * `SkeletonGhost`, `SkeletonGhostRenderer`, `AtlasRegionAttacher`, `SkeletonGraphicMirror`, `SkeletonRagdoll`, `SkeletonRagdoll2D`, `SkeletonUtilityEyeConstraint`, `SkeletonUtilityGroundConstraint`, `SkeletonUtilityKinematicShadow` changed to namespace `Spine.Unity.Examples`. + * Split `Editor/Utility/SpineEditorUtilities` class into multiple files with partial class qualifier. + * Nested classes `SpineEditorUtilities.AssetUtility` and `SpineEditorUtilities.EditorInstantiation` are now no longer nested. If you receive namespace related errors, replace any occurrance of + * `SpineEditorUtilities.AssetUtility` with `AssetUtility` and + * `SpineEditorUtilities.EditorInstantiation` with `EditorInstantiation`. + * **Timeline Support has been moved to a separate UPM Package** Previously the Spine Timeline integration was located in the `Modules/Timeline` directory and was deactivated by default, making it necessary to activate it via the Spine Preferences. Now the Timeline integration has been moved to an additional UPM package which can be found under `Modules/com.esotericsoftware.spine.timeline`. + * **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + a) the `Packages` directory in your project where it will automatically be loaded, or + b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + The Project panel should now show an entry `Spine Timeline Extensions` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + * `SkeletonMecanim`'s `Layer Mix Mode` enum name `MixMode.SpineStyle` has been renamed to `MixMode.Hard`. This is most likely not set via code and thus unlikely to be a problem. Serialized scenes and prefabs are unaffected. + * `SkeletonRootMotion` and `SkeletonMecanimRootMotion` components now support arbitrary bones in the hierarchy as `Root Motion Bone`. Previously there were problems when selecting a non-root bone as `Root Motion Bone`. `Skeleton.ScaleX` and `.ScaleY` and parent bone scale is now respected as well. + +* **Additions** + * **Spine Preferences stored in Assets/Editor/SpineSettings.asset** Now Spine uses the new `SettingsProvider` API, storing settings in a SpineSettings.asset file which can be shared with team members. Your old preferences are automatically migrated to the new system. + * Added support for Unity's SpriteMask to `SkeletonAnimation` and `SkeletonMecanim`. All mask interaction modes are supported. See this [blog post](http://esotericsoftware.com/blog/Unity-SpriteMask-and-RectMask2D-support). + * Added support for Unity's RectMask2D to SkeletonGraphics. See this [blog post](http://esotericsoftware.com/blog/Unity-SpriteMask-and-RectMask2D-support). + * Added `Create 2D Hinge Chain` button at `SkeletonUtilityBone` inspector, previously only `Create 3D Hinge Chain` was available. + * **Now supporting Lightweight Render Pipeline (LWRP) through an additional UPM package.** + * **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + * a) the `Packages` directory in your project where it will automatically be loaded, or + * b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + > If you are using git and Unity 2019.2 or newer versions and receive an error that dependencies could not be resolved by the package manager (only higher versions of Unity's `Lightweight RP` package are available, e.g. `6.9.0` and up), please copy the prepared package-UNITYVERSION.json file for your Unity version (e.g. `package-2019.2.json`) over the existing package.json file to change the dependency accordingly. Unfortunately Unity's Package Manager does not provide a way to specify a version range for a dependency like "5.7.2 - 6.9.0" yet, so this manual step is necessary for git users. + + The Project panel should now show an entry `Spine Lightweight RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + * **Usage:** The package provides two shaders specifically built for the lightweight render pipeline: + * `Lightweight Render Pipeline/Spine/Skeleton`, as a lightweight variant of the `Spine/Skeleton` shader, + * `Lightweight Render Pipeline/Spine/Skeleton Lit`, as a lightweight variant of the `Spine/Skeleton Lit` shader and + * `Lightweight Render Pipeline/Spine/Sprite`, as a lightweight variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the lightweight render pipeline. The shaders can be assigned to materials as usual and will respect your settings of the assigned `LightweightRenderPipelineAsset` under `Project Settings - Graphics`. + * **Restrictions** As all Spine shaders, the LWRP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + * **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.lwrp-shaders-3.8/Examples/LWRP Shaders.unity` that demonstrates usage of the LWRP shaders. + * Added `Spine/Skeleton Lit ZWrite` shader. This variant of the `Spine/Skeleton Lit` shader writes to the depth buffer with configurable depth alpha threshold. Apart from that it is identical to `Spine/Skeleton Lit`. + * Additional yield instructions to wait for animation track events `End`, `Complete` and `Interrupt`. + * `WaitForSpineAnimationComplete` now proves an additional `bool includeEndEvent` parameter, defaults to `false` (previous behaviour). + * Added a new `WaitForSpineAnimationEnd` yield instruction. + * Added a new generic `WaitForSpineAnimation` yield instruction which can be configured to wait for any combination of animation track events. It is now used as base class for `WaitForSpineAnimationComplete` and `WaitForSpineAnimationEnd`. + * Additional **Fix Draw Order** parameter at SkeletonRenderer, defaults to `disabled` (previous behaviour). + Applies only when 3+ submeshes are used (2+ materials with alternating order, e.g. "A B A"). + If true, MaterialPropertyBlocks are assigned at each material to prevent aggressive batching of submeshes + by e.g. the LWRP renderer, leading to incorrect draw order (e.g. "A1 B A2" changed to "A1A2 B"). + You can leave this parameter disabled when everything is drawn correctly to save the additional performance cost. + * **Additional Timeline features.** SpineAnimationStateClip now provides a `Speed Multiplier`, a start time offset parameter `Clip In`, support for blending successive animations by overlapping tracks. An additional `Use Blend Duration` parameter *(defaults to true)* allows for automatic synchronisation of MixDuration with the current overlap blend duration. An additional Spine preferences parameter `Use Blend Duration` has been added which can be disabled to default to the previous behaviour before this update. + * Additional `SpriteMask and RectMask2D` example scene added for demonstration of mask setup and interaction. + * `Real physics hinge chains` for both 2D and 3D physics. The [SkeletonUtilityBone](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) Inspector provides an interface to create 2D and 3D hinge chains. Previously created chains have only been respecting gravity, but not momentum of the skeleton or parent bones. The new physics rig created when pressing `Create 3D Hinge Chain` and `Create 2D Hinge Chain` creates a more complex setup that also works when flipping the skeleton. Note that the chain root node is no longer parented to bones of the skeleton. This is a requirement in Unity to have momentum applied properly - do not reparent the chain root to bones of your skeleton, or you will loose any momentum applied by the skeleton's movement. + * `Outline rendering functionality for all shaders.` Every shader now provides an additional set of `Outline` parameters to enable custom outline rendering. When outline rendering is enabled via the `Material` inspector, it automatically switches the shader to the respective `Spine/Outline` shader variant. Outlines are generated by sampling neighbour pixels, so be sure to add enough transparent padding when exporting your atlas textures to fit the desired outline width. In order to enable outline rendering at a skeleton, it is recommended to first prepare an additional outline material copy and then switch the material of the target skeleton to this material. This prevents unnecessary additional runtime material copies and drawcalls. Material switching can be prepared via a [SkeletonRendererCustomMaterials](http://esotericsoftware.com/spine-unity#SkeletonRendererCustomMaterials) component and then enabled or disabled at runtime. Alternatively, you can also directly modify the `SkeletonRenderer.CustomMaterialOverride` property. + Outline rendering is fully supported on `SkeletonGraphic` shaders as well. + * Added `SkeletonRenderer.EditorSkipSkinSync` scripting API property to be able to set custom skins in editor scripts. Enable this property when overwriting the Skeleton's skin from an editor script. Without setting this parameter, changes will be overwritten by the next inspector update. Only affects Inspector synchronisation of skin with `initialSkinName`, not startup initialization. + * All `Spine/SkeletonGraphic` shaders now provide a parameter `CanvasGroup Compatible` which can be enabled to support `CanvasGroup` alpha blending. For correct results, you should then disable `Pma Vertex Colors` in the `SkeletonGraphic` Inspector, in section `Advanced` (otherwise Slot alpha will be applied twice). + * **Now supporting Universal Render Pipeline (URP), including the 2D Renderer pipeline, through an additional UPM package.** + * **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + * a) the `Packages` directory in your project where it will automatically be loaded, or + * b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + The Project panel should now show an entry `Spine Universal RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + * **Usage:** The package provides two shaders specifically built for the universal render pipeline: + * `Universal Render Pipeline/Spine/Skeleton`, as a universal variant of the `Spine/Skeleton` shader, + * `Universal Render Pipeline/Spine/Skeleton Lit`, as a universal variant of the `Spine/Skeleton Lit` shader, + * `Universal Render Pipeline/Spine/Sprite`, as a universal variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the universal render pipeline, + * `Universal Render Pipeline/2D/Spine/Skeleton Lit`, as a universal 2D Renderer variant of the `Spine/Skeleton Lit` shader, and + * `Universal Render Pipeline/2D/Spine/Sprite`, as a universal 2D Renderer variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders. + The shaders can be assigned to materials as usual and will respect your settings of the assigned `UniversalRenderPipelineAsset` under `Project Settings - Graphics`. + * **Restrictions** As all Spine shaders, the URP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + * **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.urp-shaders-3.8/Examples/URP Shaders.unity` that demonstrates usage of the URP shaders. + * Spine Preferences now provide an **`Atlas Texture Settings`** parameter for applying customizable texture import settings at all newly imported Spine atlas textures. + When exporting atlas textures from Spine with `Premultiply alpha` enabled (the default), you can leave it at `PMATexturePreset`. If you have disabled `Premultiply alpha`, set it to the included `StraightAlphaTexturePreset` asset. You can also create your own `TextureImporter` `Preset` asset and assign it here (include `PMA` or `Straight` in the name). In Unity versions before 2018.3 you can use `Texture2D` template assets instead of the newer `Preset` assets. Materials created for imported textures will also have the `Straight Alpha Texture` parameter configured accordingly. + * All `Sprite` shaders (including URP and LWRP extension packages) now provide an additional `Fixed Normal Space` option `World-Space`. PReviously options were limited to `View-Space` and `Model-Space`. + * `SkeletonGraphic` now fully supports [`SkeletonUtility`](http://esotericsoftware.com/spine-unity#SkeletonUtility) for generating a hierarchy of [`SkeletonUtilityBones`](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) in both modes `Follow` and `Override`. This also enables creating hinge chain physics rigs and using `SkeletonUtilityConstraints` such as `SkeletonUtilityGroundConstraint` and `SkeletonUtilityEyeConstraint` on `SkeletonGraphic`. + * Added `OnMeshAndMaterialsUpdated` callback event to `SkeletonRenderer` and `SkeletonGraphic`. It is issued at the end of `LateUpdate`, before rendering. + * Added `Skeleton-OutlineOnly` single pass shader to LWRP and URP extension modules. It can be assigned to materials as `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly`. This allows for separate outline child *GameObjects* that reference the existing Mesh of their parent, and re-draw the mesh using this outline shader. + * Added example component `RenderExistingMesh` to render a mesh again with different materials, as required by the new `Skeleton-OutlineOnly` shaders. + In URP the outline has to be rendered via a separate GameObject as URP does not allow multiple render passes. To add an outline to your SkeletenRenderer: + 1) Add a child GameObject and move it a bit back (e.g. position Z = 0.01). + 2) Add a `RenderExistingMesh` component, provided in the `Spine Examples/Scripts/Sample Components` directory. + 3) Copy the original material, add *_Outline* to its name and set the shader to `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly`. + 4) Assign this *_Outline* material at the `RenderExistingMesh` component under *Replacement Materials*. + * Added `Outline Shaders URP` example scene to URP extension module to demonstrate the above additions. + * Added support for Unity's [`SpriteAtlas`](https://docs.unity3d.com/Manual/class-SpriteAtlas.html) as atlas provider (as an alternative to `.atlas.txt` and `.png` files) alongside a skeleton data file. There is now an additional `Spine SpriteAtlas Import` tool window accessible via `Window - Spine - SpriteAtlas Import`. Additional information can be found in a new section on the [spine-unity documentation page](http://esotericsoftware.com/spine-unity#Advanced---Using-Unity-SpriteAtlas-as-Atlas-Provider). + * Added support for **multiple atlas textures at `SkeletonGraphic`**. You can enable this feature by enabling the parameter `Multiple CanvasRenders` in the `Advanced` section of the `SkeletonGraphic` Inspector. This automatically creates the required number of child `CanvasRenderer` GameObjects for each required draw call (submesh). + * Added support for **Render Separator Slots** at `SkeletonGraphic`. Render separation can be enabled directly in the `Advanced` section of the `SkeletonGraphic` Inspector, it does not require any additional components (like `SkeletonRenderSeparator` or `SkeletonPartsRenderer` for `SkeletonRenderer` components). When enabled, additional separator GameObjects will be created automatically for each separation part, and `CanvasRenderer` GameObjects re-parented to them accordingly. The separator GameObjects can be moved around and re-parented in the hierarchy according to your requirements to achieve the desired draw order within your `Canvas`. A usage example can be found in the updated `Spine Examples/Other Examples/SkeletonRenderSeparator` scene. + * Added `SkeletonGraphicCustomMaterials` component, providing functionality to override materials and textures of a `SkeletonGraphic`, similar to `SkeletonRendererCustomMaterials`. Note: overriding materials or textures per slot is not provided due to structural limitations. + * Added **Root Motion support** for `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic` via new components `SkeletonRootMotion` and `SkeletonMecanimRootMotion`. The `SkeletonAnimation` and `SkeletonGraphic` component Inspector now provides a line `Root Motion` with `Add Component` and `Remove Component` buttons to add/remove the new `SkeletonRootMotion` component to your GameObject. The `SkeletonMecanim` Inspector detects whether root motion is enabled at the `Animator` component and adds a `SkeletonMecanimRootMotion` component automatically. + * `SkeletonMecanim` now provides an additional `Custom MixMode` parameter under `Mecanim Translator`. It is enabled by default in version 3.8 to maintain current behaviour, using the set `Mix Mode` for each Mecanim layer. When disabled, `SkeletonMecanim` will use the recommended `MixMode` according to the layer blend mode. Additional information can be found in the [Mecanim Translator section](http://esotericsoftware.com/spine-unity#Parameters-for-animation-blending-control) on the spine-unity documentation pages. + * Added **SkeletonGraphic Timeline support**. Added supprot for multi-track Timeline preview in the Editor outside of play mode (multi-track scrubbing). See the [Timeline-Extension-UPM-Package](http://esotericsoftware.com/spine-unity#Timeline-Extension-UPM-Package) section of the spine-unity documentation for more information. + * Added support for double-sided lighting at all `SkeletonLit` shaders (including URP and LWRP packages). + * Added frustum culling update mode parameters `Update When Invisible` (Inspector parameter) and `UpdateMode` (available via code) to all Skeleton components. This provides a simple way to disable certain updates when the `Renderer` is no longer visible (outside all cameras, culled in frustum culling). The new `UpdateMode` property allows disabling updates at a finer granularity level than disabling the whole component. Available modes are: `Nothing`, `OnlyAnimationStatus`, `EverythingExceptMesh` and `FullUpdate`. + * Added a new `Spine/Outline/OutlineOnly-ZWrite` shader to provide correct outline-only rendering. Note: the shader requires two render passes and is therefore not compatible with URP. The `Spine Examples/Other Examples/Outline Shaders` example scene has been updated to demonstrate the new shader. + * Added `OnMeshAndMaterialsUpdated` callback event to `SkeletonRenderSeparator` and `SkeletonPartsRenderer`. It is issued at the end of `LateUpdate`, before rendering. + * Added `Root Motion Scale X/Y` parameters to `SkeletonRootMotionBase` subclasses (`SkeletonRootMotion` and `SkeletonMecanimRootMotion`). Also providing `AdjustRootMotionToDistance()` and other methods to allow for easy delta compensation. Delta compensation can be used to e.g. stretch a jump to a given distance. Root motion can be adjusted at the start of an animation or every frame via `skeletonRootMotion.AdjustRootMotionToDistance(targetPosition - transform.position, trackIndex);`. + * Now providing a `Canvas Group Tint Black` parameter at the `SkeletonGraphic` Inspector in the `Advanced` section. When using the `Spine/SkeletonGraphic Tint Black` shader you can enable this parameter to receive proper blending results when using `Additive` blend mode under a `CanvasGroup`. Be sure to also have the parameter `CanvasGroup Compatible` enabled at the shader. Note that the normal `Spine/SkeletonGraphic` does not support `Additive` blend mode at a `CanvasGroup`, as it requires additional shader channels to work. + * Added `Mix and Match Skins` example scene to demonstrate how the 3.8 Skin API and combining skins can be used for a wardrobe and equipment use case. + * Spine Timeline Extensions: Added `Hold Previous` parameter at `SpineAnimationStateClip`. + * Added more warning messages at incompatible SkeletonRenderer/SkeletonGraphic Component vs Material settings. They appear both as an info box in the Inspector as well as upon initialization in the Console log window. The Inspector box warnings can be disabled via `Edit - Preferences - Spine`. + * Now providing `BeforeApply` update callbacks at all skeleton animation components (`SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic`). + * Added `BoundingBoxFollowerGraphic` component. This class is a counterpart of `BoundingBoxFollower` that can be used with `SkeletonGraphic`. + * Added Inspector context menu functions `SkeletonRenderer - Add all BoundingBoxFollower GameObjects` and `SkeletonGraphic - Add all BoundingBoxFollowerGraphic GameObjects` that automatically generate bounding box follower GameObjects for every `BoundingBoxAttachment` for all skins of a skeleton. + * `GetRemappedClone()` now provides an additional parameter `pivotShiftsMeshUVCoords` for `MeshAttachment` to prevent uv shifts at a non-central Sprite pivot. This parameter defaults to `true` to maintain previous behaviour. + * `SkeletonRenderer` components now provide an additional update mode `Only Event Timelines` at the `Update When Invisible` property. This mode saves additional timeline updates compared to update mode `Everything Except Mesh`. + * Now all URP (Universal Render Pipeline) and LWRP (Lightweight Render Pipeline) shaders support SRP (Scriptable Render Pipeline) batching. See [Unity SRPBatcher documentation pages](https://docs.unity3d.com/Manual/SRPBatcher.html) for additional information. + * Sprite shaders now provide four `Diffuse Ramp` modes as an Inspector Material parameter: `Hard`, `Soft`, `Old Hard` and `Old Soft`. In spine-unity 3.8 it defaults to `Old Hard` to keep the behaviour of existing projects unchanged. From 4.0 on it defaults to `Hard` for newly created materials while existing ones remain unchanged. Note that `Old Hard` and `Old Soft` ramp versions were using only the right half of the ramp texture, and additionally multiplying the light intensity by 2, both leading to brighter lighting than without a ramp texture active. The new ramp modes `Hard` and `Soft` use the full ramp texture and do not modify light intensity, being consistent with lighting without a ramp texture active. + * Added **native support for slot blend modes** `Additive`, `Multiply` and `Screen` with automatic assignment at newly imported skeleton assets. `BlendModeMaterialAssets` are now obsolete and replaced by the native properties at `SkeletonDataAsset`. The `SkeletonDataAsset` Inspector provides a new `Blend Modes - Upgrade` button to upgrade an obsolete `BlendModeMaterialAsset` to the native blend modes properties. This upgrade will be performed automatically on imported and re-imported assets in Unity 2020.1 and newer to prevent reported `BlendModeMaterialAsset` issues in these Unity versions. spine-unity 4.0 and newer will automatically perform this upgrade regardless of the Unity version. + * `BoneFollower` and `BoneFollowerGraphic` components now provide better support for following bones when the skeleton's Transform is not the parent of the follower's Transform. Previously e.g. rotating a common parent Transform did not lead to the desired result, as well as negatively scaling a skeleton's Transform when it is not a parent of the follower's Transform. + * URP and LWRP `Sprite` and `SkeletonLit` shaders no longer require `Advanced - Add Normals` enabled to properly cast and receive shadows. It is recommended to disable `Add Normals` if normals are otherwise not needed. + * Added an example component `RootMotionDeltaCompensation` located in `Spine Examples/Scripts/Sample Components` which can be used for applying simple delta compensation. You can enable and disable the component to toggle delta compensation of the currently playing animation on and off. + * Root motion delta compensation now allows to only adjust X or Y components instead of both. Adds two parameters to `SkeletonRootMotionBase.AdjustRootMotionToDistance()` which default to adjusting both X and Y as before. The `RootMotionDeltaCompensation` example component exposes these parameters as public attributes. + * Root motion delta compensation now allows to also add translation root motion to e.g. adjust a horizontal jump upwards or downwards over time. This is necessary because a Y root motion of zero cannot be scaled to become non-zero. + * `Attachment.GetRemappedClone(Sprite)` method now provides an additional optional parameter `useOriginalRegionScale`. When set to `true`, the replaced attachment's scale is used instead of the Sprite's `Pixel per Unity` setting, allowing for more consistent scaling. *Note:* When remapping Sprites, be sure to set the Sprite's `Mesh Type` to `Full Rect` and not `Tight`, otherwise the scale will be wrong. + +* **Changes of default values** + * `SkeletonMecanim`'s `Layer Mix Mode` now defaults to `MixMode.MixNext` instead of `MixMode.MixAlways`. + * `BlendModeMaterialAsset` and it's instance `Default BlendModeMaterials.asset` now have `Apply Additive Material` set to `true` by default in order to apply all blend modes by default. + +* **Deprecated** + * Deprecated `Modules/SlotBlendModes/SlotBlendModes` component. Changed namespace from `Spine.Unity.Modules` to `Spine.Unity.Deprecated`. Moved to `Deprecated/SlotBlendModes`. + +* **Restructuring (Non-Breaking)** + + Note: The following changes will most likely not affect users of the Spine-Unity runtime as the API remains unchanged and no references are invalidated. + * Removed duplicates of `.cginc` files in `Modules/Shaders/Sprite` that were also present in the `Modules/Shaders/Sprite/CGIncludes` directory. + * Moved shaders from `Modules/Shaders` to `Shaders` directory. + * Moved shaders from `Modules/SkeletonGraphic/Shaders` to `Shaders/SkeletonGraphic`. + * Renamed shader `Shaders/Spine-SkeletonLit.shader` to `Shaders/Spine-Skeleton-Lit.shader`. + * Moved components from `SkeletonGraphic` to `Components` and `Components/Following` except for `SkeletonGraphicMirror` which was moved to `Spine Examples/Scripts/Sample Components`. + * Moved `BoneFollower`, `BoneFollowerGraphic` and `PointFollower` from `Components` directory to `Components/Following`. + * Moved `BoundingBoxFollower` component from `Modules/BoundingBoxFollower` to `Components/Following`. + * Moved `Modules/SkeletonRenderSeparator` directory to `Components/SkeletonRenderSeparator`. + * Moved `Modules/CustomMaterials` directory to `Components/SkeletonRendererCustomMaterials`. + * Moved `Asset Types/BlendModeMaterialsAsset.cs` class, `Shaders/BlendModes/Default BlendModeMaterials.asset` and materials from `Shaders/BlendModes` to `SkeletonDataModifierAssets/BlendModeMaterials` directory. + * Moved `Modules/Ghost` directory to `Spine Examples/Scripts/Sample Components/Ghost`. + * Moved `Modules/SkeletonUtility Modules` directory to `Spine Examples/Scripts/Sample Components/SkeletonUtility Modules`. + * Moved `Modules/AnimationMatchModifier` directory to `Spine Examples/Scripts/MecanimAnimationMatchModifier`. + * Moved `SkeletonRagdoll` and `SkeletonRagdoll2D` components from `Modules/Ragdoll` directory to `Spine Examples/Scripts/Sample Components/SkeletonUtility Modules`. + * Moved `AttachmentTools.cs` to `Utility` directory. + * Split the file `AttachmentTools` into 5 separate files for each contained class. No namespace or other API changes performed. + * Split the file `Mesh Generation/SpineMesh` into 4 separate files for each contained class. No namespace or other API changes performed. + * Moved `SkeletonExtensions.cs` to `Utility` directory. + * Moved `Modules/YieldInstructions` directory to `Utility/YieldInstructions`. + * Moved corresponding editor scripts of the above components to restructured directories as well. + * Renamed inspector editor class `PointFollowerEditor` to `PointFollowerInspector` for consistency reasons. + +### XNA/MonoGame +* Updated to latest MonoGame version 3.7.1 +* Rewrote example project to be cleaner and better demonstrate basic Spine features. +* Added mix-and-match example to demonstrate the new Skin API. +* Added normalmap support via `SpineEffectNormalmap` and support for loading multiple texture layers following a suffix-pattern. Please see the example code on how to use them. + +## Java +* **Breaking changes** + * Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + * Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * `JsonRollback` tool now converts from 3.8 JSON to 3.7. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin#getAttachments()`. Returns all attachments in the skin. + * Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `Skin#addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin#copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### libGDX +* `SkeletonViewer` can load a skeleton by specifying it as the first argument on the command line. +* Added mix-and-match example to demonstrate the new Skin API. + +## Lua +* **Breaking changes** + * Renamed `Slot:getAttachmentVertices()` to `Slot#deform`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin:addAttachment()` to `Skin#setAttachment()`. + * Removed `VertexAttachment:applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed the `.json` file format to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin:getAttachments()`. Returns all attachments in the skin. + * Added `Skin:getAttachments(slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `Skin:addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin:copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment:copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment:newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### Love2D +* Added support for 0-1 RGBA color component range change in Löve 0.11+. Older Löve versions using the 0-255 range are still supported! +* Added mix-and-match example to demonstrate the new Skin API. + +### Corona +* Added mix-and-match example to demonstrate the new Skin API. + +## Typescript/Javascript +* **Breaking changes** + * Renamed `MixDirection.in/out` to `MixDirection.mixIn/mixOut` as it was crashing a JS compressor. + * Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + * Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + * Updated runtime to be compatible with TypeScript 3.6.3. + +* **Additions** + * Added support for loading binary data via `AssetManager#loadBinary()`. `AssetManager#get()` will return a `Uint8Array` for such assets. + * Added support for loading binaries via new `SkeletonBinary`. Parses a `Uint8Array`. + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin#getAttachments()`. Returns all attachments in the skin. + * Added `Skin#getAttachments(slotIndex: number)`. Returns all attachements in the skin for the given slot index. + * Added `Skin#addSkin(skin: Skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin#copySkin(skin: Skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + * Added `AssetManager.setRawDataURI(path, data)`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. + * Added `AssetManager.loadAll()` to allow Promise/async/await based waiting for completion of asset load. See the `spine-canvas` examples. + * Added `Skeleton.getBoundRect()` helper method to calculate the bouding rectangle of the current pose, returning the result as `{ x, y, width, height }`. Note that this method will create temporary objects which can add to garbage collection pressure. + +### WebGL backend +* `Input` can now take a partially defined implementation of `InputListener`. +* Added mix-and-match example to demonstrate the new Skin API. + +### Canvas backend + +### Three.js backend +* `SkeletonMesh` now takes an optional `SkeletonMeshMaterialParametersCustomizer` function that allows you to modify the `ShaderMaterialParameters` before the material is finalized. Use it to modify things like THREEJS' `Material.depthTest` etc. See #1590. + +### Player +* `SpinePlayer#setAnimation()` can now be called directly to set the animation being displayed. +* The player supports loading `.skel` binary skeleton files by setting the `SpinePlayerConfig#skelUrl` field instead of `SpinePlayerConfig#jsonUrl`. +* Added `SpinePlayerConfig#rawDataURIs`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. See the example for a demonstration. + +# 3.7 + +## AS3 +* **Breaking changes** + * The completion event will fire for looped 0 duration animations every frame. + * `MixPose` is now called `MixBlend` + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Starling +* Added support for vertex effects. See `RaptorExample.as` +* Added 'getTexture()' method to 'StarlingTextureAtlasAttachmentLoader' +* Breaking change: if a skeleton requires two color tinting, you have to enable it via `SkeletonSprite.twoColorTint = true`. In this case the skeleton will use the `TwoColorMeshStyle`, which internally uses a different vertex layout and shader. This means that skeletons with two color tinting enabled will break batching and hence increase the number of draw calls in your app. +* Added `VertexEffect` and implementations `JitterEffect` and `SwirlEffect`. Allows you to modify vertices before they are submitted for drawing. See Starling changes. +* Fix issues with StarlingAtlasAttachmentLoader, see https://github.com/EsotericSoftware/spine-runtimes/issues/939 +* Fix issues with region trimming support, see https://github.com/EsotericSoftware/spine-runtimes/commit/262bc26c64d4111002d80e201cb1a3345e6727df +* Added support for overriding `StarlingAtlasAttachmentLoader#getTexture()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/ea7dbecb98edc74e439aa9ef90dcf6eed865f718 +* Texture atlas operations are no longer handled in `Starling#newRegionAttachment` and `Starling#newMeshAttachment` but delegated to the atlas. +* Added sample for additive animation blending, see https://github.com/EsotericSoftware/spine-runtimes/blob/6a556de01429878df47bb276a97959a8bdbbe32f/spine-starling/spine-starling-example/src/spine/examples/OwlExample.as +* Added sample on how to use bounding box attachment vertices https://github.com/EsotericSoftware/spine-runtimes/commit/e20428b02699226164fa73ba4b12f7d029ae6f4d +* Fully transparent meshes are not submitted for rendering. +* No hit-tests are performed when a skeleton is invisible. + +## C +* **Breaking changes** + * Listeners on `spAnimationState` and `spTrackEntry` will now also be called if a track entry gets disposed as part of disposing an animation state. + * The completion event will fire for looped 0 duration animations every frame. + * The spine-cocos2dx and spine-ue4 runtimes are now based on spine-cpp. See below for changes. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 + * `spMeshAttachment` has two new fields `regionTextureWith` and `regionTextureHeight`. These must be set in custom attachment loader. See `AtlasAttachmentLoader`. +* **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `spTransformConstraintData`. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `spVertexEffect` and corresponding implementations `spJitterVertexEffect` and `spSwirlVertexEffect`. Create/dispose through the corresponding `spXXXVertexEffect_create()/dispose()` functions. Set on framework/engine specific renderer. + * Functions in `extension.h` are not prefixed with `_sp` instead of just `_` to avoid interference with other libraries. + * Introduced `SP_API` macro. Every spine-c function is prefixed with this macro. By default, it is an empty string. Can be used to markup spine-c functions with e.g. ``__declspec` when compiling to a dll or linking to that dll. + * Added `void *userData` to `spAnimationState`to be consumed in callbacks. + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `spTrackEntry->mixBlend = SP_MIXBLEND_ADD)` on each track. To specify the blend percentage, set `spTrackEntry->alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Optimized attachment lookup to give a 40x speed-up. See https://github.com/EsotericSoftware/spine-runtimes/commit/cab81276263890b65d07fa2329ace16db1e365ff + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `spTrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Cocos2d-Objc +* Added vertex effect support to modify vertices of skeletons on the CPU. See `RaptorExample.m`. +* Explanation how to handle ARC, see https://github.com/EsotericSoftware/spine-runtimes/commit/a4f122b08c5e2a51d6aad6fc5a947f7ec31f2eb8 +* The super class `::update()` method of `SkeletonRenderer` is now called, see https://github.com/EsotericSoftware/spine-runtimes/commit/f7bb98185236a6d8f35bfefc70afe4f31e9ec9d2 +* Added improved tint-black shader. + +### SFML +* `spine-sfml.h` no longer defines `SPINE_SHORT_NAMES` to avoid collisions with other APIs. See #1058. +* Added support for vertex effects. See raptor example. +* Added premultiplied alpha support to `SkeletonDrawable`. Use `SkeletonDrawable::setUsePremultipliedAlpha()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/34086c1f41415309b2ecce86055f6656fcba2950 +* Added additive animation blending sample, see https://github.com/EsotericSoftware/spine-runtimes/blob/b7e712d3ca1d6be3ebcfe3254dc2cea9c44dda71/spine-sfml/example/main.cpp#L369 + +## C++ +* ** Additions ** + * Added C++ Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. + * Added parsing of non-essential data (fps, images path, audio path) to for `.json`/`.skel` parsers. + +### Cocos2d-x +* Added ETC1 alpha support, thanks @halx99! Does not work when two color tint is enabled. +* Added `spAtlasPage_setCustomTextureLoader()` which let's you do texture loading manually. Thanks @jareguo. +* Added `SkeletonRenderer:setSlotsRange()` and `SkeletonRenderer::createWithSkeleton()`. This allows you to split rendering of a skeleton up into multiple parts, and render other nodes in between. See `SkeletonRendererSeparatorExample.cpp` for an example. +* Fully transparent attachments will not be rendered, improving rendering performance. +* Added improved tint-black shader. +* Updated to cocos2d-x 3.16 +* The skeleton setup pose and world transform are now calculated on initialization to avoid flickering on start-up. +* Updated to cocos2d-x 3.17.1 +* **Breaking change**: Switched from [spine-c](spine-c) to [spine-cpp](spine-cpp) as the underlying Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. + * Added `Cocos2dAttachmentLoader` to be used when constructing an `Atlas`. Used by default by `SkeletonAnimation` and `SkeletonRenderer` when creating instances via the `createXXX` methods. + * All C structs and enums `spXXX` have been replaced with their C++ equivalents `spine::XXX` in all public interfaces. + * All instantiations via `new` of C++ classes from spine-cpp should contain `(__FILE__, __LINE__)`. This allows the tracking of instantations and detection of memory leaks via the `spine::DebugExtension`. + +### SFML +* Create a second SFML backend using [spine-cpp](spine-cpp/). See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. +* Added support for vertex effects. See raptor example. +* Added premultiplied alpha support to `SkeletonDrawable`. Use `SkeletonDrawable::setUsePremultipliedAlpha()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/34086c1f41415309b2ecce86055f6656fcba2950 +* Added additive animation blending sample, see https://github.com/EsotericSoftware/spine-runtimes/blob/b7e712d3ca1d6be3ebcfe3254dc2cea9c44dda71/spine-sfml/example/main.cpp#L369 + +### UE4 + * spine-c is now exposed from the plugin shared library on Windows via __declspec. + * Updated to Unreal Engine 4.18 + * Added C++ example, see https://github.com/EsotericSoftware/spine-runtimes/commit/15011e81b7061495dba45e28b4d3f4efb10d7f40 + * `SkeletonRendererComponent` generates collision meshes by default. + * Disabled generation of collision meshes by `SkeletonRendererComponent`. Both `ProceduralMeshComponent` and `RuntimeMeshComponent` have a bug that generates a new PhysiX file every frame per component. Users are advised to add a separate collision shape to the root scene component of an actor instead. + * Using UE4 `FMemory` allocator by default. This should fix issues on some consoles. + * **Breaking change** moved away from `RuntimeMeshComponent`, as its maintainance has seized, back to `ProceduralMeshComponent`. Existing projects should just work. However, if you run into issues, you may have to remove the old `SpineSkeletonRendererComponent` and add a new one to your existing actors. + * **Breaking change** due to the removal of `RuntimeMeshComponent` and reversal to `ProceduralMeshComponent`, two color tinting is currently not supported. `ProceduralMeshComponent` does not support enough vertex attributes for us to encode the second color in the vertex stream. You can remove the `RuntimeMeshComponent/` directory from your plugins directory and remove the component from any `build.cs` files that may reference it. + * **Breaking change**: Switched from [spine-c](spine-c) to [spine-cpp](spine-cpp) as the underlying Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. + * All C structs and enums `spXXX` have been replaced with their C++ equivalents `spine::XXX` in all public interfaces. + * All instantiations via `new` of C++ classes from spine-cpp should contain `(__FILE__, __LINE__)`. This allows the tracking of instantations and detection of memory leaks via the `spine::DebugExtension`. +* Updated to Unreal Engine 4.20 (samples require 4.17+), see the `spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.build.cs` file on how to compile in 4.20 with the latest UBT API changes. +* Updated to Unreal Engine 4.21 (samples require 4.21). +* **Breaking change**: `UBoneDriverComponent` and `UBoneFollowerComponent` are now `USceneComponent` instead of `UActorComponent`. They either update only themselves, or also the owning `UActor`, depending on whether the new flag `UseComponentTransform` is set. See https://github.com/EsotericSoftware/spine-runtimes/pull/1175 +* Added query methods for slots, bones, skins and animations to `SpineSkeletonComponent` and `UTrackEntry`. These allow you to query these objects by name in both C++ and blueprints. +* Added `Preview Animation` and `Preview Skin` properties to `SpineSkeletonAnimationComponent`. Enter an animation or skin name to live-preview it in the editor. Enter an empty string to reset the animation or skin. + +## C# ## +* **Breaking changes** + * The completion event will fire for looped 0 duration animations every frame. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#MixBlend = MixBlend.add` on each track. To specify the blend percentage, set `TrackEntry#Alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Unity +* **Runtime and Editor, and Assembly Definition** Files and folders have been reorganized into "Runtime" and "Editor". Each of these have an `.asmdef` file that defines these separately as their own assembly in Unity *(Note: Spine `.asmdef` files are currently deactivated to `.txt` extension, see below)*. For projects not using assembly definition, you may delete the `.asmdef` files. These assembly definitions will be ignored by older versions of Unity that don't support it. + * In this scheme, the entirety of the base spine-csharp runtime is inside the "Runtime" folder, to be compiled in the same assembly as spine-unity so they can continue to share internal members. +* **Spine `.asmdef` files are now deactivated (using `.txt` extension) by default** This prevents problems when updating Spine through unitypackages, overwriting the Timeline reference entry in `spine-unity.asmdef` (added automatically when enabling Unity 2019 Timeline support, see `Timeline Support for Unity 2019`), causing compile errors. In case you want to enable the `.asmdef` files, rename the files: + `Spine/Runtime/spine-unity.txt` to `Spine/Runtime/spine-unity.asmdef` and + `Spine/Editor/spine-unity-editor.txt` to `Spine/Editor/spine-unity-editor.asmdef`. +* **SkeletonAnimator is now SkeletonMecanim** The Spine-Unity Mecanim-driven component `SkeletonAnimator` has been renamed `SkeletonMecanim` to make it more autocomplete-friendly and more obvious at human-glance. The .meta files and guids should remain intact so existing projects and prefabs should not break. However, user code needs to be updated to use `SkeletonMecanim`. +* **SpineAtlasAsset** The existing `AtlasAsset` type has been renamed to `SpineAtlasAsset` to signify that it specifically uses a Spine/libGDX atlas as its source. Serialization should be intact but user code will need to be updated to refer to existing atlases as `SpineAtlasAsset`. + * **AtlasAssetBase** `SpineAtlasAsset` now has an abstract base class called `SpineAtlasAsset`. This is the base class to derive when using alternate atlas sources. Existing SkeletonDataAsset field "atlasAssets" now have the "AtlasAssetBase" type. Serialization should be intact, but user code will need to be updated to refer to the atlas assets accordingly. + * This change is in preparation for alternate atlas options such as Unity's SpriteAtlas. +* **Optional Straight Alpha for shaders** Spine-Unity's included Unity shaders now have a `_STRAIGHT_ALPHA_INPUT` shader_feature, toggled as a checkbox in the Material's inspector. This allows the Material to use a non-premultiplied alpha/straight alpha input texture. + * The following shaders now have the "Straight Alpha Texture" checkbox when used on a material: + * `Spine/Skeleton` + * `Spine/Skeleton Tint Black` + * `Spine/Skeleton Lit` + * `Spine/Skeleton Tint` + * `Spine/Skeleton Fill` + * `Spine/SkeletonGraphic (Premultiply Alpha)` was renamed to `Spine/SkeletonGraphic` + * `Spine/SkeletonGraphic Tint Black (Premultiply Alpha)` was renamed to `Spine/SkeletonGraphic Tint Black` + * `Spine/Skeleton PMA Multiply` + * `Spine/Skeleton PMA Screen` + * Dedicated straight alpha shaders were removed from the runtime. + * `Spine/Straight Alpha/Skeleton Fill` + * `Spine/Straight Alpha/Skeleton Tint` +* **Detection of Incorrect Texture Settings** Especially when atlas textures are exported with setting `Premultiply alpha` enabled, it is important to configure Unity's texture import settings correctly. By default, you will now receive warnings where texture settings are expected to cause incorrect rendering. + * The following rules apply: + * `sRGB (Color Texture)` shall be disabled when `Generate Mip Maps` is enabled, otherwise you will receive white border outlines. + * `Alpha Is Transparency` shall be disabled on `Premultiply alpha` textures, otherwise you will receive light ghosting artifacts in transparent areas. + * These warnings can be disabled in `Edit - Preferences - Spine`. +* **Sprite Mask Support for all Included Shaders** The `Skeleton Animation` and `Skeleton Mecanim` components now provide an additional `Mask Interaction` field in the Inspector, covering identical functionality as Unity's built in `Sprite Renderer` component: + * `Mask Interaction` modes: + * `None` - The sprite will not interact with the masking system. Default behavior. + * `Visible Inside Mask` - The sprite will be visible only in areas where a mask is present. + * `Visible Outside Mask` - The sprite will be visible only in areas where no mask is present. + * `Automatically Generated Materials` When switching `Mask Interaction` modes in the Inspector outside of Play mode, the required additional material assets are generated for the respective `Stencil Compare` parameters - with file suffixes `'_InsideMask'` and `'_OutsideMask'`, placed in the same folder as the original materials. By default all generated materials are kept as references by the `Skeleton Animation` component for switching at runtime. + These materials can be managed and optimized via the `SkeletonAnimation`'s `Advanced` section: + * Using the `Clear` button you can clear the reference to unneeded materials, + * Using the `Delete` button the respective assets are deleted as well as references cleared. Note that other `Skeleton Animation` GameObjects might still reference the materials, so use with caution! + * With the `Set` button you can again assign a link to the respective materials to prepare them for runtime use. If the materials were not present or have been deleted, they are generated again based on the default materials. + * When switching `Mask Interaction` mode at runtime, the previously prepared materials are switched active automatically. When the respective materials have not been prepared, material copies of the default materials are created on the fly. Note that these materials are not shared between similar `Skeleton Animation` GameObjects, so it is recommended to use the generated material assets where possible. + * **Every shader now exposes the `Stencil Compare` parameter** for further customization. This way you have maximum flexibility to use custom mechanisms to switch materials at runtime if you should ever need more than the three materials generated by `Skeleton Animation`'s `Mask Interaction` parameter. Reference `Stencil Compare` values are: + * `CompareFunction.Disabled` for `Mask Interaction - None` + * `CompareFunction.LessEqual` for `Mask Interaction - Visible Inside Mask` + * `CompareFunction.Greater` for `Mask Interaction - Visible Outside Mask` +* **RectMask2D Support for SkeletonGraphic** Both `SkeletonGraphic` shaders '`Spine/SkeletonGraphic`' and '`Spine/SkeletonGraphic Tint Black`' now respect masking areas defined via Unity's `RectMask2D` component. +* **Timeline Support for Unity 2019** using the existing Timeline components. By default, all Spine Timeline components are deactivated in Unity 2019 and **can be activated via the Spine Preferences menu**. This step became necessary because in Unity 2019, Timeline has been moved to a separate Package and is no longer included in the Unity core. Please visit `Edit - Preferences - Spine` and at `Timeline Package Support` hit `Enable` to automatically perform all necessary steps to activate the Timeline components. +This will automatically: + 1. download the Unity Timeline package + 2. activate the Spine Timeline components by setting the compile definition `SPINE_TIMELINE_PACKAGE_DOWNLOADED` for all platforms + 3. modify the `spine-unity.asmdef` file by adding the reference to the Unity Timeline library. +* Added `Create 2D Hinge Chain` functionality at `SkeletonUtilityBone` inspector, previously only `Create 3D Hinge Chain` was available. + +### XNA/MonoGame +* Added support for any `Effect` to be used by `SkeletonRenderer` +* Added support for `IVertexEffect` to modify vertices of skeletons on the CPU. `IVertexEffect` instances can be set on the `SkeletonRenderer`. See example project. +* Added `SkeletonDebugRenderer` +* Made `MeshBatcher` of SkeletonRenderer accessible via a getter. Allows user to batch their own geometry together with skeleton meshes for maximum batching instead of using XNA SpriteBatcher. + +## Java +* **Breaking changes** + * Skeleton attachments: Moved update of attached skeleton out of libGDX `SkeletonRenderer`, added overloaded method `Skeleton#updateWorldTransform(Bone)`, used for `SkeletonAttachment`. You now MUST call this new method with the bone of the parent skeleton to which the child skeleton is attached. See `SkeletonAttachmentTest` for and example. + * The completion event will fire for looped 0 duration animations every frame. + * `MixPose` is now called `MixBlend`. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added `EventData#audioPath` field. This field contains the file name of the audio file used for the event. + * Added convenience method to add all attachments from one skin to another, see https://github.com/EsotericSoftware/spine-runtimes/commit/a0b7bb6c445efdfac12b0cdee2057afa3eff3ead + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### libGDX +* Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect` and `VertexEffectTest`. +* Added improved tint-black shader. +* Improved performance by avoiding batch flush when not switching between normal and additive rendering with PMA +* Improvements to skeleton viewer. +* `TwoColorPolygonBatch` implements the `Batch` interface, allowing to the be used with other libGDX classes that require a batcher for drawing, potentially improving performance. See https://github.com/EsotericSoftware/spine-runtimes/commit/a46b3d1d0c135d51f9bef9ca17a5f8e5dda69927 +* Added `SkeletonDrawable` to render skeletons in scene2d UI https://github.com/EsotericSoftware/spine-runtimes/commit/b93686c185e2c9d5466969a8e07eee573ebe4b97 + +## Lua +* **Breaking changes** + * The completion event will fire for looped 0 duration animations every frame. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added `JitterEffect` and `SwirlEffect` and support for vertex effects in Corona and Love + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry:setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry.alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Love2D +* Added support for vertex effects. Set an implementation like "JitterEffect" on `Skeleton.vertexEffect`. See `main.lua` for an example. + +### Corona +* Added support for vertex effects. Set an implementation like "JitterEffect" on `SkeletonRenderer.vertexEffect`. See `main.lua` for an example + +## Typescript/Javascript +* **Breaking changes** + * The completion event will fire for looped 0 duration animations every frame. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added `AssetManager.loadTextureAtlas`. Instead of loading the `.atlas` and corresponding image files manually, you can simply specify the location of the `.atlas` file and AssetManager will load the atlas and all its images automatically. `AssetManager.get("atlasname.atlas")` will then return an instance of `spine.TextureAtlas`. + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. See https://github.com/EsotericSoftware/spine-runtimes/blob/f045d221836fa56191ccda73dd42ae884d4731b8/spine-ts/webgl/tests/test-additive-animation-blending.html for an example. + * Added work-around for iOS WebKit JIT bug, see https://github.com/EsotericSoftware/spine-runtimes/commit/c28bbebf804980f55cdd773fed9ff145e0e7e76c + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + * Added `AssetManager#setRawDataURI(path, data)`. Allows to set raw data URIs for a specific path, which in turn enables embedding assets into JavaScript/HTML. + +### WebGL backend +* Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`, and the example which allows to set effects. +* Added `slotRangeStart` and `slotRangeEnd` parameters to `SkeletonRenderer#draw` and `SceneRenderer#drawSkeleton`. This allows you to render only a range of slots in the draw order. See `spine-ts/webgl/tests/test-slot-range.html` for an example. +* Added improved tint-black shader. +* Added `SceneRenderer#drawTextureUV()`, allowing to draw a texture with manually specified texture coordinates. +* Exposed all renderers in `SceneRenderer`. + +### Canvas backend +* Added support for shearing and non-uniform scaling inherited from parent bones. +* Added support for alpha tinting. + +### Three.js backend +* Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`. +* Added support for multi-page atlases + +### Widget backend + * Added fields `atlasContent`, `atlasPagesContent`, and `jsonContent` to `WidgetConfiguration` allowing you to directly pass the contents of the `.atlas`, atlas page `.png` files, and the `.json` file without having to do a request. See `README.md` and the example for details. + * `SpineWidget.setAnimation()` now takes an additional optional parameter for callbacks when animations are completed/interrupted/etc. + +# 3.6 + +## AS3 +* **Breaking changes** + * Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Made `Bone` fields `_a`, `_b`, `_c`, `_d`, `_worldX` and `_worldY` public, removed underscore prefix. + * Removed `VertexAttachment.computeWorldVertices` overload, changed `VertexAttachment.computeWorldVertices2` to `VertexAttachment.computeWorldVertices`, added `stride` parameter. + * Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + * Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + * Replaced `r`, `g`, `b`, `a` fields with instances of new `Color` class in `RegionAttachment`, `MeshAttachment`, `Skeleton`, `SkeletonData`, `Slot` and `SlotData`. + * The completion event will fire for looped 0 duration animations every frame. + +* **Additions** + * Added `Skeleton.getBounds` from reference implementation. + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `VertexEffect` and implementations `JitterEffect` and `SwirlEffect`. Allows you to modify vertices before they are submitted for drawing. See Starling changes. + +### Starling + * Fixed renderer to work with 3.6 changes. + * Added support for two color tinting. + * Added support for clipping. + * Added support for rotated regions in texture atlas loaded via StarlingAtlasAttachmentLoader. + * Added support for vertex effects. See `RaptorExample.as` + * Added 'getTexture()' method to 'StarlingTextureAtlasAttachmentLoader' + * Breaking change: if a skeleton requires two color tinting, you have to enable it via `SkeletonSprite.twoColorTint = true`. In this case the skeleton will use the `TwoColorMeshStyle`, which internally uses a different vertex layout and shader. This means that skeletons with two color tinting enabled will break batching and hence increase the number of draw calls in your app. + +## C +* **Breaking changes** + * `spVertexAttachment_computeWorldVertices` and `spRegionAttachment_computeWorldVerticeS` now take new parameters to make it possible to directly output the calculated vertex positions to a vertex buffer. Removes the need for additional copies in the backends' respective renderers. + * Removed `spBoundingBoxAttachment_computeWorldVertices`, superseded by `spVertexAttachment_computeWorldVertices`. + * Removed `spPathAttachment_computeWorldVertices` and `spPathAttachment_computeWorldVertices1`, superseded by `spVertexAttachment_computeWorldVertices`. + * Removed `sp_MeshAttachment_computeWorldVertices`, superseded by `spVertexAttachment_computeWorldVertices`. + * Removed `spBone_worldToLocalRotationX` and `spBone_worldToLocalRotationY`. Replaced by `spBone_worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Replaced `r`, `g`, `b`, `a` fields with instances of new `spColor` struct in `spRegionAttachment`, `spMeshAttachment`, `spSkeleton`, `spSkeletonData`, `spSlot` and `spSlotData`. + * Removed `spVertexIndex`from public API. + * Listeners on `spAnimationState` or `spTrackEntry` will now be also called in case a track entry is disposed as part of dispoing the `spAnimationState`. + * The completion event will fire for looped 0 duration animations every frame. +* **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `spTransformConstraintData`. + * Added `spPointAttachment`, additional method `spAtlasAttachmentLoadeR_newPointAttachment`. + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `spBone_localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `spTwoColorTimeline` and additional fields on `spSlot` and `spSlotData`. + * Added `userData` field to `spTrackEntry`, so users can expose data in `spAnimationState` callbacks. + * Modified kvec.h used by SkeletonBinary.c to use Spine's MALLOC/FREE macros. That way there's only one place to inject custom allocators ([extension.h](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-c/spine-c/include/spine/extension.h)) [commit](https://github.com/EsotericSoftware/spine-runtimes/commit/c2cfbc6cb8709daa082726222d558188d75a004f) + * Added macros to define typed dynamic arrays, see `Array.h/.c` + * Added `spClippingAttachment` and respective enum. + * Added `spSkeletonClipper` and `spTriangulator`, used to implement software clipping of attachments. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `spVertexEffect` and corresponding implementations `spJitterVertexEffect` and `spSwirlVertexEffect`. Create/dispose through the corresponding `spXXXVertexEffect_create()/dispose()` functions. Set on framework/engine specific renderer. See changes for spine-c based frameworks/engines below. + * Functions in `extension.h` are not prefixed with `_sp` instead of just `_` to avoid interference with other libraries. + * Introduced `SP_API` macro. Every spine-c function is prefixed with this macro. By default, it is an empty string. Can be used to markup spine-c functions with e.g. ``__declspec` when compiling to a dll or linking to that dll. + +### Cocos2d-X + * Fixed renderer to work with 3.6 changes + * Optimized rendering by removing all per-frame allocation in `SkeletonRenderer`, resulting in 15% performance increase for large numbers of skeletons being rendered per frame. + * Added support for two color tinting. Tinting is enabled/disabled per `SkeletonRenderer`/`SkeletonAnimation` instance. Use `SkeletonRenderer::setTwoColorTint()`. Note that two color tinting requires the use of a non-standard shader and vertex format. This means that skeletons rendered with two color tinting will break batching. However, skeletons with two color tinting enabled and rendered after each other will be batched. + * Updated example to use Cocos2d-x 3.14.1. + * Added mesh debug rendering. Enable/Disable via `SkeletonRenderer::setDebugMeshesEnabled()`. + * Added support for clipping. + * SkeletonRenderer now combines the displayed color of the Node (cascaded from all parents) with the skeleton color for tinting. + * Added support for vertex effects. See `RaptorExample.cpp`. + * Added ETC1 alpha support, thanks @halx99! Does not work when two color tint is enabled. + * Added `spAtlasPage_setCustomTextureLoader()` which let's you do texture loading manually. Thanks @jareguo. + * Added `SkeletonRenderer:setSlotsRange()` and `SkeletonRenderer::createWithSkeleton()`. This allows you to split rendering of a skeleton up into multiple parts, and render other nodes in between. See `SkeletonRendererSeparatorExample.cpp` for an example. + +### Cocos2d-Objc + * Fixed renderer to work with 3.6 changes + * Added support for two color tinting. Tinting is enabled/disabled per `SkeletonRenderer/SkeletonAnimation.twoColorTint = true`. Note that two color tinted skeletons do not batch with other nodes. + * Added support for clipping. + +### SFML + * Fixed renderer to work with 3.6 changes. Sadly, two color tinting does not work, as the vertex format in SFML is fixed. + * Added support for clipping. + * Added support for vertex effects. See raptor example. + * Added premultiplied alpha support to `SkeletonDrawable`. + +### Unreal Engine 4 + * Fixed renderer to work with 3.6 changes + * Added new UPROPERTY to SpineSkeletonRendererComponent called `Color`. This allows to set the tint color of the skeleton in the editor, C++ and Blueprints. Under the hood, the `spSkeleton->color` will be set on every tick of the renderer component. + * Added support for clipping. + * Switched from built-in ProceduralMeshComponent to RuntimeMeshComponent by Koderz (https://github.com/Koderz/UE4RuntimeMeshComponent, MIT). Needed for more flexibility regarding vertex format, should not have an impact on existing code/assets. You need to copy the RuntimeMeshComponentPlugin from our repository in `spine-ue4\Plugins\` to your project as well! + * Added support for two color tinting. All base materials, e.g. SpineUnlitNormalMaterial, now do proper two color tinting. No material parameters have changed. + * Updated to Unreal Engine 4.16.1. Note that 4.16 has a regression which will make it impossible to compile plain .c files! + * spine-c is now exposed from the plugin shared library on Windows via __declspec. + +## C# +* **Breaking changes** + * `MeshAttachment.parentMesh` is now a private field to enforce using the `.ParentMesh` setter property in external code. The `MeshAttachment.ParentMesh` property is an appropriate replacement wherever `.parentMesh` was used. + * `Skeleton.GetBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + * Removed `Bone.WorldToLocalRotationX` and `Bone.WorldToLocalRotationY`. Replaced by `Bone.WorldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Added `stride` parameter to `VertexAttachment.ComputeWorldVertices`. + * Removed `RegionAttachment.Vertices` field. The vertices array is provided to `RegionAttachment.ComputeWorldVertices` by the API user now. + * Removed `RegionAttachment.UpdateWorldVertices`, added `RegionAttachment.ComputeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + * The completion event will fire for looped 0 duration animations every frame. + + * **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `NewPointAttachment` in `AttachmentLoader` interface. + * Added `ClippingAttachment`, additional method `NewClippingAttachment` in `AttachmentLoader` interface. + * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + * `AnimationState.Apply` returns a bool indicating if any timeline was applied or not. + * `Animation.Apply` and `Timeline.Apply`` now take enums `MixPose` and `MixDirection` instead of bools. + +### Unity + * Refactored renderer to work with new 3.6 features. + * **Two color tinting** is currently supported via extra UV2 and UV3 mesh vertex streams. To use Two color tinting, you need to: + * switch on "Tint Black" under "Advanced...", + * use the new `Spine/Skeleton Tint Black` shader, or your own shader that treats the UV2 and UV3 streams similarly. + * Additionally, for SkeletonGraphic, you can use `Spine/SkeletonGraphic Tint Black` (or the bundled SkeletonGraphicTintBlack material) or your own shader that uses UV2 and UV3 streams similarly. **Additional Shader Channels** TexCoord1 and TexCoord2 will need to be enabled from the Canvas component's inspector. These correspond to UV2 and UV3. + * **Clipping** is now supported. Caution: The SkeletonAnimation switches to slightly slower mesh generation code when clipping so limit your use of `ClippingAttachment`s when using on large numbers of skeletons. + * **SkeletonRenderer.initialFlip** Spine components such as SkeletonRenderer, SkeletonAnimation, SkeletonAnimator now has `initialFlipX` and `initialFlipY` fields which are also visible in the inspector under "Advanced...". It will allow you to set and preview a starting flip value for your skeleton component. This is applied immediately when the internal skeleton object is instantiated. + * **[SpineAttribute] Improvements** + * **Icons have been added to SpineAttributeDrawers**. This should make your default inspectors easier to understand at a glance. + * **Added Constraint Attributes** You can now use `[SpineIkConstraint]` `[SpineTransformConstraint]` `[SpinePathConstraint]` + * **SpineAttribute dataField** parameter can also now detect sibling fields within arrays and serializable structs/classes. + * **[SpineAttribute(includeNone:false)]** SpineAttributes now have an `includeNone` optional parameter to specify if you want to include or exclude a none ("") value option in the dropdown menu. Default is `includeNone:true`. + * **[SpineAttachment(skinField:"mySkin")]** The SpineAttachment attribute now has a skinField optional parameter to limit the dropdown items to attachments in a specific skin instead of the just default skin or all the skins in SkeletonData. + * **SkeletonDebugWindow**. Debugging tools have been moved from the SkeletonAnimation and SkeletonUtility component inspectors into its own utility window. You can access "Skeleton Debug" under the `Advanced...` foldout in the SkeletonAnimation inspector, or in SkeletonAnimation's right-click/context menu. + * **Skeleton Baking Window** The old Skeleton Baking feature is also now accessible through the SkeletonDataAsset's right-click/context menu. + * **AttachmentTools source material**. `AttachmentTools` methods can now accept a `sourceMaterial` argument to copy material properties from. + * **AttachmentTools Skin Extensions**. Using AttachmentTools, you can now add entries by slot name by also providing a skeleton argument. Also `Append(Skin)`, `RemoveAttachment` and `Clear` have been added. + * **BoneFollower and SkeletonUtilityBone Add RigidBody Button**. The BoneFollower and SkeletonUtilityBone component inspectors will now offer to add a `Rigidbody` or `Rigidbody2D` if it detects a collider of the appropriate type. Having a rigidbody on a moving transform with a collider fits better with the Unity physics systems and prevents excess calculations. It will not detect colliders on child objects so you have to add Rigidbody components manually accordingly. + * **SkeletonRenderer.OnPostProcessVertices** is a new callback that gives you a reference to the MeshGenerator after it has generated a mesh from the current skeleton pose. You can access `meshGenerator.VertexBuffer` or `meshGenerator.ColorBuffer` to modify these before they get pushed into the UnityEngine.Mesh for rendering. This can be useful for non-shader vertex effects. + * **Examples** + * **Examples now use properties**. The code in the example scripts have been switched over to using properties instead of fields to encourage their use for consistency. This is in anticipation of both users who want to move the Spine folders to the Unity Plugins folder (compiled as a different assembly), and of Unity 2017's ability to manually define different assemblies for shorter compilation times. + * **Mix And Match**. The mix-and-match example scene, code and data have been updated to reflect the current recommended setup for animation-compatible custom equip systems The underlying API has changed since 3.5 and the new API calls in MixAndMatch.cs is recommended. Documentation is in progress. + * **Sample Components**. `AtasRegionAttacher` and `SpriteAttacher` are now part of `Sample Components`, to reflect that they are meant to be used as sample code rather than production. A few other sample components have also been added. New imports of the unitypackage Examples folder will see a "Legacy" folder comprised of old sample components that no longer contain the most up-to-date and recommended workflows, but are kept in case old setups used them for production. + * **Spine folder**. In the unitypackage, the "spine-csharp" and "spine-unity" folders are now inside a "Spine" folder. This change will only affect fresh imports. Importing the unitypackage to update Spine-Unity in your existing project will update the appropriate files however you chose to arrange them, as long as the meta files are intact. + * **Breaking changes** + * The Sprite shaders module was updated to the latest version from the [source](https://github.com/traggett/UnitySpriteShaders/commits/master). Some changes were made to the underlying keyword structure. You may need to review the settings of your lit materials. Particularly, your Fixed Normals settings. + * The `Spine/Skeleton Lit` shader was switched over to non-fixed-function code. It now no longer requires mesh normals and has fixed normals at the shader level. + * The old MeshGenerator classes, interfaces and code in `Spine.Unity.MeshGeneration` are now deprecated. All mesh-generating components now share the class `Spine.Unity.MeshGenerator` defined in `SpineMesh.cs`. MeshGenerator is a serializable class. + * The `SkeletonRenderer.renderMeshes` optimization is currently non-functional. + * Old triangle-winding code has been removed from `SkeletonRenderer`. Please use shaders that have backface culling off. + * Render settings in `SkeletonGraphic` can now be accessed under `SkeletonGraphic.MeshGenerator.settings`. This is visible in the SkeletonGraphic inspector as `Advanced...` + * We will continue to bundle the unitypackage with the empty .cs files of deprecated classes until Spine 3.7 to ensure the upgrade process does not break. + * The [SpineAttachment(slotField:)] optional parameter found property value now acts as a Find(slotName) argument rather than Contains(slotName). + * `SkeletonAnimator` now uses a `SkeletonAnimator.MecanimTranslator` class to translate an Animator's Mecanim State Machine into skeleton poses. This makes code reuse possible for a Mecanim version of SkeletonGraphic. + * `SkeletonAnimator` `autoreset` and the `mixModes` array are now a part of SkeletonAnimator's MecanimTranslator `.Translator`. `autoReset` is set to `true` by default. Old prefabs and scene objects with Skeleton Animator may no longer have correct values set. + * Warnings and conditionals checking for specific Unity 5.2-and-below incompatibility have been removed. + +## XNA/MonoGame + * Added support for clipping + * Removed `RegionBatcher` and `SkeletonRegionRenderer`, renamed `SkeletonMeshRenderer` to `SkeletonRenderer` + * Added support for two color tint. For it to work, you need to add the `SpineEffect.fx` file to your content project, then load it via `var effect = Content.Load("SpineEffect");`, and set it on the `SkeletonRenderer`. See the example project for code. + * Added support for any `Effect` to be used by `SkeletonRenderer` + * Added support for `IVertexEffect` to modify vertices of skeletons on the CPU. `IVertexEffect` instances can be set on the `SkeletonRenderer`. See example project. + * Added `SkeletonDebugRenderer` + * Made `MeshBatcher` of SkeletonRenderer accessible via a getter. Allows user to batch their own geometry together with skeleton meshes for maximum batching instead of using XNA SpriteBatcher. + +## Java +* **Breaking changes** + * `Skeleton.getBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + * Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Added `stride` parameter to `VertexAttachment.computeWorldVertices`. + * Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + * Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + * Skeleton attachments: Moved update of attached skeleton out of libGDX `SkeletonRenderer`, added overloaded method `Skeleton#updateWorldTransform(Bone), used for `SkeletonAttachment`. You now MUST call this new method + with the bone of the parent skeleton to which the child skeleton is attached. See `SkeletonAttachmentTest` for and example. + * The completion event will fire for looped 0 duration animations every frame. + +* **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + +### libGDX + * Fixed renderer to work with 3.6 changes + * Added support for two color tinting. Use the new `TwoColorPolygonBatch` together with `SkeletonRenderer` + * Added support for clipping. See `SkeletonClipper`. Used automatically by `SkeletonRenderer`. Does not work when using a `SpriteBatch` with `SkeletonRenderer`. Use `PolygonSpriteBatch` or `TwoColorPolygonBatch` instead. + * Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect` and `VertexEffectTest`. + +## Lua +* **Breaking changes** + * Removed `Bone:worldToLocalRotationX` and `Bone:worldToLocalRotationY`. Replaced by `Bone:worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * `VertexAttachment:computeWorldVertices` now takes offsets and stride to allow compositing vertices directly in a vertex buffer to be send to the GPU. The compositing is now performed in the backends' respective renderers. This also affects the subclasses `MeshAttachment`, `BoundingBoxAttachment` and `PathAttachment`. + * Removed `RegionAttachment:updateWorldVertices`, added `RegionAttachment:computeWorldVertices`, which takes offsets and stride to allow compositing vertices directly in a vertex buffer to be send to the GPU. The compositing is now performed in the backends' respective renderers. + * Removed `MeshAttachment.worldVertices` field. Computation is now performed in each backends' respective renderer. The `uv` coordinates are now stored in `MeshAttachment.uvs`. + * Removed `RegionAttachment.vertices` field. Computation is now performed in each backends respective renderer. The `uv` coordinates for each vertex are now stored in the `RegionAttachment.uvs` field. + * The completion event will fire for looped 0 duration animations every frame. + * **Additions** + * Added `Bone:localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `JitterEffect` and `SwirlEffect` and support for vertex effects in Corona and Love + +### Love2D + * Fixed renderer to work with 3.6 changes + * Added support for two color tinting. Enable it via `SkeletonRenderer.new(true)`. + * Added clipping support. + * Added support for vertex effects. Set an implementation like "JitterEffect" on `Skeleton.vertexEffect`. See `main.lua` for an example. + +### Corona + * Fixed renderer to work with 3.6 changes. Sadly, two color tinting is not supported, as Corona doesn't let us change the vertex format needed and its doesn't allow to modify shaders in the way needed for two color tinting + * Added clipping support. + * Added support for vertex effects. Set an implementation like "JitterEffect" on `SkeletonRenderer.vertexEffect`. See `main.lua` for an example + +## Typescript/Javascript +* **Breaking changes** + * `Skeleton.getBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + * Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Removed `VertexAttachment.computeWorldVertices` overload, changed `VertexAttachment.computeWorldVerticesWith` to `VertexAttachment.computeWorldVertices`, added `stride` parameter. + * Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + * Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + * The completion event will fire for looped 0 duration animations every frame. + * Removed the Spine Widget in favor of [Spine Web Player](https://esotericsoftware.com/spine-player). + +* **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `AssetManager.loadTextureAtlas`. Instead of loading the `.atlas` and corresponding image files manually, you can simply specify the location of the `.atlas` file and AssetManager will load the atlas and all its images automatically. `AssetManager.get("atlasname.atlas")` will then return an instance of `spine.TextureAtlas`. + * Added the [Spine Web Player](https://esotericsoftware.com/spine-player) + + +### WebGL backend + * Fixed WebGL context loss + * Added `Restorable` interface, implemented by any WebGL resource that needs restoration after a context loss. All WebGL resource classes (`Shader`, `Mesh`, `GLTexture`) implement this interface. + * Added `ManagedWebGLRenderingContext`. Handles setup of a `WebGLRenderingContext` given a canvas element and restoration of WebGL resources (`Shader`, `Mesh`, `GLTexture`) on WebGL context loss. WebGL resources register themselves with the `ManagedWebGLRenderingContext`. If the context is informed of a context loss and restoration, the registered WebGL resources' `restore()` method is called. The `restore()` method implementation on each resource type will recreate the GPU side objects. + * All classes that previously took a `WebGLRenderingContext` in the constructor now also allow a `ManagedWebGLRenderingContext`. This ensures existing applications do not break. + * To use automatic context restauration: + 1. Create or fetch a canvas element from the DOM + 2. Instantiate a `ManagedWebGLRenderingContext`, passing the canvas to the constructor. This will setup a `WebGLRenderingContext` internally and manage context loss/restoration. + 3. Pass the `ManagedWebGLRenderingContext` to the constructors of classes that you previously passed a `WebGLRenderingContext` to (`AssetManager`, `GLTexture`, `Mesh`, `Shader`, `PolygonBatcher`, `SceneRenderer`, `ShapeRenderer`, `SkeletonRenderer`, `SkeletonDebugRenderer`). + * Fixed renderer to work with 3.6 changes. + * Added support for two color tinting. + * Improved performance by using `DYNAMIC_DRAW` for vertex buffer objects and fixing bug that copied to much data to the GPU each frame in `PolygonBatcher`/`Mesh`. + * Added two color tinting support, enabled by default. You can disable it via the constructors of `SceneRenderer`, `SkeletonRenderer`and `PolygonBatcher`. Note that you will need to use a shader created via `Shader.newTwoColoredTexturedShader` shader with `SkeletonRenderer` and `PolygonBatcher` if two color tinting is enabled. + * Added clipping support + * Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`, and the example which allows to set effects. + * Added `slotRangeStart` and `slotRangeEnd` parameters to `SkeletonRenderer#draw` and `SceneRenderer#drawSkeleton`. This allows you to render only a range of slots in the draw order. See `spine-ts/webgl/tests/test-slot-range.html` for an example. + +### Canvas backend + * Fixed renderer to work for 3.6 changes. Sadly, we can't support two color tinting via the Canvas API. + * Added support for shearing and non-uniform scaling inherited from parent bones. + * Added support for alpha tinting. + +### Three.js backend + * Fixed renderer to work with 3.6 changes. Two color tinting is not supported. + * Added clipping support + * Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`. + * Added support for multi-page atlases + +### Widget backend + * Fixed WebGL context loss (see WebGL backend changes). Enabled automatically. + * Fixed renderer to work for 3.6 changes. Supports two color tinting & clipping (see WebGL backend changes for details). + * Added fields `atlasContent`, `atlasPagesContent`, and `jsonContent` to `WidgetConfiguration` allowing you to directly pass the contents of the `.atlas`, atlas page `.png` files, and the `.json` file without having to do a request. See `README.md` and the example for details. + * `SpineWidget.setAnimation()` now takes an additional optional parameter for callbacks when animations are completed/interrupted/etc. diff --git a/DateToSpine/third_party/spine-runtimes/4.0/CMakeLists.txt b/DateToSpine/third_party/spine-runtimes/4.0/CMakeLists.txt new file mode 100644 index 0000000..4ec5c62 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/CMakeLists.txt @@ -0,0 +1,47 @@ +cmake_minimum_required(VERSION 3.17) +project(spine) + +set(CMAKE_INSTALL_PREFIX "./") +set(CMAKE_VERBOSE_MAKEFILE ON) +set(SPINE_SFML FALSE CACHE BOOL FALSE) +set(SPINE_COCOS2D_OBJC FALSE CACHE BOOL FALSE) +set(SPINE_COCOS2D_X FALSE CACHE BOOL FALSE) +set(SPINE_SANITIZE FALSE CACHE BOOL FALSE) + +if(MSVC) + message("MSCV detected") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + set (CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}") +else() + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wunused-value -Wno-c++11-long-long -Wno-variadic-macros -Wextra -pedantic -Wnonportable-include-path -Wshadow -std=c89") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunused-value -Wno-c++11-long-long -Wno-variadic-macros -Wextra -Wnon-virtual-dtor -pedantic -Wnonportable-include-path -Wshadow -std=c++11 -fno-exceptions -fno-rtti") + + if (${SPINE_SANITIZE}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize=undefined") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize=undefined") + endif() +endif() + +if((${SPINE_SFML}) OR (${CMAKE_CURRENT_BINARY_DIR} MATCHES "spine-sfml")) + if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(CMAKE_OSX_ARCHITECTURES x86_64) + set(ONLY_ACTIVE_ARCH NO) + endif() + add_subdirectory(spine-c) + add_subdirectory(spine-sfml/c) + add_subdirectory(spine-cpp) + add_subdirectory(spine-sfml/cpp) +endif() + +if((${SPINE_COCOS2D_OBJC}) OR (${CMAKE_CURRENT_BINARY_DIR} MATCHES "spine-cocos2d-objc")) + if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + add_subdirectory(spine-cocos2d-objc) + endif() +endif() + +if((${SPINE_COCOS2D_X}) OR (${CMAKE_CURRENT_BINARY_DIR} MATCHES "spine-cocos2dx")) + add_subdirectory(spine-cocos2dx) +endif() + +# add_subdirectory(spine-c/spine-c-unit-tests) +add_subdirectory(spine-cpp/spine-cpp-unit-tests) diff --git a/DateToSpine/third_party/spine-runtimes/4.0/LICENSE b/DateToSpine/third_party/spine-runtimes/4.0/LICENSE new file mode 100644 index 0000000..4501a61 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/LICENSE @@ -0,0 +1,26 @@ +Spine Runtimes License Agreement +Last updated May 1, 2019. Replaces all prior versions. + +Copyright (c) 2013-2019, Esoteric Software LLC + +Integration of the Spine Runtimes into software or otherwise creating +derivative works of the Spine Runtimes is permitted under the terms and +conditions of Section 2 of the Spine Editor License Agreement: +http://esotericsoftware.com/spine-editor-license + +Otherwise, it is permitted to integrate the Spine Runtimes into software +or otherwise create derivative works of the Spine Runtimes (collectively, +"Products"), provided that each user of the Products must obtain their own +Spine Editor license and redistribution of the Products in any form must +include this license and copyright notice. + +THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS +INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.0/README.md b/DateToSpine/third_party/spine-runtimes/4.0/README.md new file mode 100644 index 0000000..3245185 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/README.md @@ -0,0 +1,33 @@ +# Spine Runtimes + +This GitHub project hosts the Spine Runtimes which are needed to use [Spine](http://esotericsoftware.com/) 2D skeletal animation data with various game toolkits. + +## Licensing + +You are welcome to evaluate the Spine Runtimes and the examples we provide in this repository free of charge. + +You can integrate the Spine Runtimes into your software free of charge, but users of your software must have their own [Spine license](https://esotericsoftware.com/spine-purchase). Please make your users aware of this requirement! This option is often chosen by those making development tools, such as an SDK, game toolkit, or software library. + +In order to distribute your software containing the Spine Runtimes to others that don't have a Spine license, you need a [Spine license](https://esotericsoftware.com/spine-purchase) at the time of integration. Then you can distribute your software containing the Spine Runtimes however you like, provided others don't modify it or use it to create new software. If others want to do that, they'll need their own Spine license. + +For the official legal terms governing the Spine Runtimes, please read the [Spine Runtimes License Agreement](http://esotericsoftware.com/spine-runtimes-license) and Section 2 of the [Spine Editor License Agreement](http://esotericsoftware.com/spine-editor-license#s2). + +## Documentation + +See the [Spine Runtimes Guide](http://esotericsoftware.com/spine-runtimes-guide) for detailed information about using the Spine Runtimes. The Spine [documentation page](http://esotericsoftware.com/spine-documentation#runtimesTitle) provides further information about tools and data formats. For runtime specific documentation, refer to the `README.md` file in each runtime directory. + +## Bugs, enhancements, and tasks + +Review our backlog of bugs, enhancements, and tasks in the [spine-runtimes](https://github.com/EsotericSoftware/spine-runtimes/issues) and [spine-editor](https://github.com/EsotericSoftware/spine-editor/issues) issue trackers. Our [roadmap](http://esotericsoftware.com/spine-roadmap) provides a more convenient view of the same issue tracker information. + +## Versioning + +The default branch on GitHub is stable and works with data exported from the latest, non-beta version of the Spine editor. New development is done in an `X.X-beta` branch, which may be a work in progress. Important changes to the runtimes can be reviewed in the [CHANGELOG.md file](CHANGELOG.md). Occasionally the Spine Runtimes are [tagged](https://github.com/EsotericSoftware/spine-runtimes/releases) with the specific Spine editor version they work with. + +It is highly suggested to [freeze](http://esotericsoftware.com/spine-settings#Version) the Spine editor version to match the Spine Runtimes source being used and to update them in lock step. See the [Spine Runtimes Guide](http://esotericsoftware.com/spine-runtime-architecture#Versioning) for more information. + +## Contributing + +In order to merge your contributions, we need a signed [contributor license agreement (CLA)](http://esotericsoftware.com/licenses/cla.txt) from you. You can send a copy of the CLA to contact@esotericsoftware.com. + +When possible, it is best to base your contributions on the current beta branch (`X.X-beta`). Please be sure to follow the style and formatting you find in the respective runtime code to which you are contributing. diff --git a/DateToSpine/third_party/spine-runtimes/4.0/examples/readme.txt b/DateToSpine/third_party/spine-runtimes/4.0/examples/readme.txt new file mode 100644 index 0000000..21ee01a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/examples/readme.txt @@ -0,0 +1,27 @@ +These example projects show off many of Spine's features. Below are a number +of other example resources that may prove useful. + +We have detailed documentation for how many of the example projects are built: +http://esotericsoftware.com/spine-examples + +See our online demos, which render Spine animations right in your browser: +http://esotericsoftware.com/spine-demos + +Learn how to use Spine with the Spine User Guide: +http://esotericsoftware.com/spine-user-guide +And the accompanying Spine User Guide videos: +https://www.youtube.com/playlist?list=PLwGl7Ikd_6GRFo7d0uRu_fN2RIlvkxW7b +And our other videos: +https://www.youtube.com/user/EsotericSoftware/videos + +Learn how to integrate Spine into your software: +http://esotericsoftware.com/spine-runtime-documentation + +Super Spineboy is a full example game using Spine and libgdx: +https://github.com/EsotericSoftware/spine-superspineboy + +Many companies around the world are doing great things with Spine: +http://esotericsoftware.com/spine-showcase + +Tag your tweets using #madewithspine to show up on our Twitter page: +http://esotericsoftware.com/madewithspine diff --git a/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-ess.json b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-ess.json new file mode 100644 index 0000000..f998222 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-ess.json @@ -0,0 +1,3672 @@ +{ +"skeleton": { + "hash": "lS/mQzJwi+I", + "spine": "4.0.31", + "x": -221.27, + "y": -8.57, + "width": 470.72, + "height": 731.57, + "images": "./images/", + "audio": "" +}, +"bones": [ + { "name": "root" }, + { "name": "hip", "parent": "root", "y": 247.47 }, + { + "name": "torso", + "parent": "hip", + "length": 127.56, + "rotation": 103.82, + "x": -1.62, + "y": 4.9, + "color": "e0da19ff" + }, + { + "name": "front-upper-arm", + "parent": "torso", + "length": 69.45, + "rotation": 168.38, + "x": 103.76, + "y": 19.33, + "color": "00ff04ff" + }, + { + "name": "front-bracer", + "parent": "front-upper-arm", + "length": 40.57, + "rotation": 18.3, + "x": 68.8, + "y": -0.68, + "color": "00ff04ff" + }, + { + "name": "front-fist", + "parent": "front-bracer", + "length": 65.39, + "rotation": 12.43, + "x": 40.57, + "y": 0.2, + "color": "00ff04ff" + }, + { + "name": "front-thigh", + "parent": "hip", + "length": 74.81, + "rotation": -95.51, + "x": -17.46, + "y": -11.64, + "color": "00ff04ff" + }, + { + "name": "front-shin", + "parent": "front-thigh", + "length": 128.77, + "rotation": -2.21, + "x": 78.69, + "y": 1.6, + "color": "00ff04ff" + }, + { + "name": "front-foot", + "parent": "front-shin", + "length": 91.34, + "rotation": 77.91, + "x": 128.76, + "y": -0.34, + "color": "00ff04ff" + }, + { + "name": "rear-upper-arm", + "parent": "torso", + "length": 51.94, + "rotation": -169.56, + "x": 92.36, + "y": -19.22, + "color": "ff000dff" + }, + { "name": "rear-bracer", "parent": "rear-upper-arm", "length": 34.56, "rotation": 23.15, "x": 51.36, "color": "ff000dff" }, + { + "name": "gun", + "parent": "rear-bracer", + "length": 43.11, + "rotation": 5.35, + "x": 34.42, + "y": -0.45, + "color": "ff000dff" + }, + { "name": "gun-tip", "parent": "gun", "rotation": 6.83, "x": 201.05, "y": 52.14, "color": "ff000dff" }, + { + "name": "neck", + "parent": "torso", + "length": 25.45, + "rotation": -31.54, + "x": 127.5, + "y": -0.31, + "color": "e0da19ff" + }, + { + "name": "head", + "parent": "neck", + "length": 263.58, + "rotation": 23.18, + "x": 27.66, + "y": -0.26, + "color": "e0da19ff" + }, + { + "name": "rear-thigh", + "parent": "hip", + "length": 85.72, + "rotation": -72.54, + "x": 8.91, + "y": -5.63, + "color": "ff000dff" + }, + { + "name": "rear-shin", + "parent": "rear-thigh", + "length": 121.88, + "rotation": -19.83, + "x": 86.1, + "y": -1.33, + "color": "ff000dff" + }, + { + "name": "rear-foot", + "parent": "rear-shin", + "length": 82.57, + "rotation": 69.3, + "x": 121.46, + "y": -0.76, + "color": "ff000dff" + } +], +"slots": [ + { "name": "rear-upper-arm", "bone": "rear-upper-arm", "attachment": "rear-upper-arm" }, + { "name": "rear-bracer", "bone": "rear-bracer", "attachment": "rear-bracer" }, + { "name": "gun", "bone": "gun", "attachment": "gun" }, + { "name": "rear-foot", "bone": "rear-foot", "attachment": "rear-foot" }, + { "name": "rear-thigh", "bone": "rear-thigh", "attachment": "rear-thigh" }, + { "name": "rear-shin", "bone": "rear-shin", "attachment": "rear-shin" }, + { "name": "neck", "bone": "neck", "attachment": "neck" }, + { "name": "torso", "bone": "torso", "attachment": "torso" }, + { "name": "front-upper-arm", "bone": "front-upper-arm", "attachment": "front-upper-arm" }, + { "name": "head", "bone": "head", "attachment": "head" }, + { "name": "eye", "bone": "head", "attachment": "eye-indifferent" }, + { "name": "front-thigh", "bone": "front-thigh", "attachment": "front-thigh" }, + { "name": "front-foot", "bone": "front-foot", "attachment": "front-foot" }, + { "name": "front-shin", "bone": "front-shin", "attachment": "front-shin" }, + { "name": "mouth", "bone": "head", "attachment": "mouth-smile" }, + { "name": "goggles", "bone": "head", "attachment": "goggles" }, + { "name": "front-bracer", "bone": "front-bracer", "attachment": "front-bracer" }, + { "name": "front-fist", "bone": "front-fist", "attachment": "front-fist-closed" }, + { "name": "muzzle", "bone": "gun-tip", "blend": "additive" }, + { "name": "head-bb", "bone": "head" } +], +"skins": [ + { + "name": "default", + "attachments": { + "eye": { + "eye-indifferent": { "x": 85.72, "y": -28.18, "rotation": -70.63, "width": 93, "height": 89 }, + "eye-surprised": { "x": 85.72, "y": -28.18, "rotation": -70.63, "width": 93, "height": 89 } + }, + "front-bracer": { + "front-bracer": { "x": 12.03, "y": -1.68, "rotation": 79.6, "width": 58, "height": 80 } + }, + "front-fist": { + "front-fist-closed": { "x": 35.5, "y": 6, "rotation": 67.16, "width": 75, "height": 82 }, + "front-fist-open": { "x": 39.57, "y": 7.76, "rotation": 67.16, "width": 86, "height": 87 } + }, + "front-foot": { + "front-foot": { "x": 29.52, "y": 7.84, "rotation": 18.69, "width": 126, "height": 69 } + }, + "front-shin": { + "front-shin": { "x": 55.12, "y": -3.54, "rotation": 96.59, "width": 82, "height": 184 } + }, + "front-thigh": { + "front-thigh": { "x": 42.48, "y": 4.45, "rotation": 84.87, "width": 45, "height": 112 } + }, + "front-upper-arm": { + "front-upper-arm": { "x": 25.2, "y": 1.17, "rotation": 97.9, "width": 46, "height": 97 } + }, + "goggles": { + "goggles": { "x": 97.08, "y": 6.54, "rotation": -70.63, "width": 261, "height": 166 } + }, + "gun": { + "gun": { "x": 77.3, "y": 16.4, "rotation": 60.83, "width": 210, "height": 203 } + }, + "head": { + "head": { "x": 128.96, "y": 0.3, "rotation": -70.63, "width": 271, "height": 298 } + }, + "head-bb": { + "head": { + "type": "boundingbox", + "vertexCount": 6, + "vertices": [ -19.14, -70.3, 40.8, -118.07, 257.77, -115.62, 285.16, 57.18, 120.77, 164.95, -5.07, 76.95 ] + } + }, + "mouth": { + "mouth-grind": { "x": 23.69, "y": -32.24, "rotation": -70.63, "width": 93, "height": 59 }, + "mouth-oooo": { "x": 23.69, "y": -32.24, "rotation": -70.63, "width": 93, "height": 59 }, + "mouth-smile": { "x": 23.69, "y": -32.24, "rotation": -70.63, "width": 93, "height": 59 } + }, + "muzzle": { + "muzzle01": { + "x": 159.26, + "y": 5.83, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 133, + "height": 79 + }, + "muzzle02": { + "x": 191.23, + "y": 5.91, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 135, + "height": 84 + }, + "muzzle03": { + "x": 230.67, + "y": 6.02, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 166, + "height": 106 + }, + "muzzle04": { + "x": 218.54, + "y": 5.99, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 149, + "height": 90 + } + }, + "neck": { + "neck": { "x": 9.77, "y": -3.01, "rotation": -55.22, "width": 36, "height": 41 } + }, + "rear-bracer": { + "rear-bracer": { "x": 11.15, "y": -2.2, "rotation": 66.17, "width": 56, "height": 72 } + }, + "rear-foot": { + "rear-foot": { "x": 31.51, "y": 3.58, "rotation": 23.07, "width": 113, "height": 60 } + }, + "rear-shin": { + "rear-shin": { "x": 58.29, "y": -2.75, "rotation": 92.37, "width": 75, "height": 178 } + }, + "rear-thigh": { + "rear-thigh": { "x": 33.11, "y": -4.11, "rotation": 72.54, "width": 55, "height": 94 } + }, + "rear-upper-arm": { + "rear-upper-arm": { "x": 21.13, "y": 4.09, "rotation": 89.33, "width": 40, "height": 87 } + }, + "torso": { + "torso": { "x": 63.61, "y": 7.12, "rotation": -94.54, "width": 98, "height": 180 } + } + } + } +], +"events": { + "footstep": {} +}, +"animations": { + "aim": { + "bones": { + "front-fist": { + "rotate": [ + { "value": 36.08 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": -26.55 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "value": 62.31 } + ] + }, + "front-bracer": { + "rotate": [ + { "value": 9.11 } + ] + }, + "gun": { + "rotate": [ + { "value": -0.31 } + ] + } + } + }, + "death": { + "slots": { + "eye": { + "attachment": [ + { "name": "eye-surprised" }, + { "time": 0.4667, "name": "eye-indifferent" }, + { "time": 2.2333, "name": "eye-surprised" }, + { "time": 4.5333, "name": "eye-indifferent" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "name": "mouth-oooo" }, + { "time": 2.2333, "name": "mouth-grind" }, + { "time": 4.5333, "name": "mouth-oooo" } + ] + } + }, + "bones": { + "head": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.044, -2.83, 0.105, -14.97 ] + }, + { + "time": 0.1333, + "value": -21.89, + "curve": [ 0.158, -28.04, 0.2, -34.87 ] + }, + { + "time": 0.2333, + "value": -34.87, + "curve": [ 0.267, -34.87, 0.3, -34.22 ] + }, + { + "time": 0.3333, + "value": -33.33, + "curve": [ 0.356, -32.74, 0.374, -30.69 ] + }, + { + "time": 0.4, + "value": -27.7, + "curve": [ 0.433, -23.82, 0.467, -10.64 ] + }, + { + "time": 0.5, + "value": -10.64, + "curve": [ 0.522, -10.64, 0.544, -16.82 ] + }, + { + "time": 0.5667, + "value": -23.05, + "curve": [ 0.589, -29.28, 0.611, -49.33 ] + }, + { + "time": 0.6333, + "value": -55.92, + "curve": [ 0.678, -69.1, 0.722, -82.35 ] + }, + { + "time": 0.7667, + "value": -82.35, + "curve": [ 0.787, -78.36, 0.912, -75.47 ] + }, + { "time": 1, "value": -78.9 }, + { + "time": 2.2333, + "value": -78.72, + "curve": [ 2.289, -78.72, 2.345, -66.24 ] + }, + { + "time": 2.4, + "value": -58.4, + "curve": [ 2.434, -53.72, 2.468, -52.12 ] + }, + { + "time": 2.5, + "value": -51.96, + "curve": [ 2.683, -51.05, 2.856, -50.86 ] + }, + { + "time": 3.0333, + "value": -50.86, + "curve": [ 3.343, -50.86, 3.712, -53.09 ] + }, + { + "time": 3.9333, + "value": -55.94, + "curve": [ 4.2, -59.38, 4.463, -65.17 ] + }, + { + "time": 4.5333, + "value": -69.07, + "curve": [ 4.598, -72.69, 4.635, -81.74 ] + }, + { "time": 4.6667, "value": -85.29 } + ], + "scale": [ + { + "time": 0.5, + "curve": [ 0.511, 1, 0.522, 1.041, 0.511, 1, 0.522, 0.953 ] + }, + { + "time": 0.5333, + "x": 1.041, + "y": 0.953, + "curve": [ 0.556, 1.041, 0.589, 1.038, 0.544, 0.953, 0.589, 0.959 ] + }, + { + "time": 0.6, + "x": 1.033, + "y": 0.966, + "curve": [ 0.633, 1.018, 0.667, 0.989, 0.633, 0.989, 0.667, 1.014 ] + }, + { + "time": 0.7, + "x": 0.989, + "y": 1.014, + "curve": [ 0.733, 0.989, 0.8, 1, 0.733, 1.014, 0.8, 1 ] + }, + { "time": 0.8333 } + ] + }, + "neck": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.033, -2.83, 0.1, 12.35 ] + }, + { + "time": 0.1333, + "value": 12.35, + "curve": [ 0.158, 12.35, 0.267, 2.18 ] + }, + { + "time": 0.3333, + "value": -8.48, + "curve": [ 0.389, -17.37, 0.444, -46.28 ] + }, + { + "time": 0.5, + "value": -46.28, + "curve": [ 0.522, -46.28, 0.551, -12.18 ] + }, + { + "time": 0.5667, + "value": -2.91, + "curve": [ 0.591, 11.16, 0.611, 20.82 ] + }, + { + "time": 0.6333, + "value": 23.43, + "curve": [ 0.756, 37.76, 0.878, 47.9 ] + }, + { + "time": 1, + "value": 47.91, + "curve": [ 1.411, 47.95, 1.935, 47.95 ] + }, + { + "time": 2.2333, + "value": 47.95, + "curve": [ 2.322, 47.95, 2.432, 19.53 ] + }, + { + "time": 2.5, + "value": 18.51, + "curve": [ 2.666, 16, 2.767, 14.59 ] + }, + { + "time": 2.9, + "value": 14.59, + "curve": [ 3.156, 14.59, 3.425, 14.72 ] + }, + { + "time": 3.6667, + "value": 15.23, + "curve": [ 4.026, 16, 4.28, 17.21 ] + }, + { + "time": 4.4667, + "value": 18.51, + "curve": [ 4.527, 18.71, 4.61, 45.05 ] + }, + { "time": 4.6667, "value": 47.95 } + ] + }, + "torso": { + "rotate": [ + { + "value": -8.62, + "curve": [ 0.031, -16.41, 0.1, -26.52 ] + }, + { + "time": 0.1333, + "value": -26.52, + "curve": [ 0.167, -26.52, 0.233, 3.45 ] + }, + { + "time": 0.2667, + "value": 21.92, + "curve": [ 0.326, 54.76, 0.422, 108.54 ] + }, + { + "time": 0.5, + "value": 108.54, + "curve": [ 0.522, 108.54, 0.559, 79.42 ] + }, + { + "time": 0.5667, + "value": 76.67, + "curve": [ 0.577, 72.83, 0.633, 68.68 ] + }, + { + "time": 0.6667, + "value": 68.68, + "curve": [ 0.733, 68.68, 0.8, 74.71 ] + }, + { "time": 0.8667, "value": 74.71, "curve": "stepped" }, + { + "time": 2.3333, + "value": 74.71, + "curve": [ 2.58, 74.71, 2.79, 72.33 ] + }, + { + "time": 2.9667, + "value": 72, + "curve": [ 3.439, 71.12, 3.668, 70.89 ] + }, + { + "time": 4, + "value": 71.29, + "curve": [ 4.189, 71.52, 4.286, 72.55 ] + }, + { "time": 4.6667, "value": 74.71 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -35.85, + "curve": [ 0.024, -41.49, 0.089, -48.72 ] + }, + { + "time": 0.1333, + "value": -48.72, + "curve": [ 0.178, -48.72, 0.225, -18.52 ] + }, + { + "time": 0.2667, + "value": -2.77, + "curve": [ 0.313, 14.63, 0.356, 29.38 ] + }, + { + "time": 0.4, + "value": 42.91, + "curve": [ 0.411, 46.3, 0.422, 47.99 ] + }, + { + "time": 0.4333, + "value": 47.99, + "curve": [ 0.456, 47.99, 0.482, 40.58 ] + }, + { + "time": 0.5, + "value": 35.07, + "curve": [ 0.533, 24.91, 0.567, 12.21 ] + }, + { + "time": 0.6, + "value": 12.36, + "curve": [ 0.633, 12.52, 0.667, 35.68 ] + }, + { + "time": 0.7, + "value": 35.68, + "curve": [ 0.789, 35.68, 0.878, 20.08 ] + }, + { "time": 0.9667, "value": 12.28, "curve": "stepped" }, + { "time": 2.2333, "value": 12.28 }, + { + "time": 2.5667, + "value": 64.63, + "curve": [ 2.589, 66.48, 2.611, 69.77 ] + }, + { + "time": 2.6333, + "value": 70.2, + "curve": [ 2.756, 72.57, 2.878, 73.08 ] + }, + { + "time": 3, + "value": 73.04, + "curve": [ 3.189, 72.97, 3.378, 69.18 ] + }, + { + "time": 3.5667, + "value": 68.76, + "curve": [ 3.735, 68.38, 3.902, 72.6 ] + }, + { + "time": 4.0667, + "value": 72.12, + "curve": [ 4.224, 71.68, 4.378, 72.12 ] + }, + { + "time": 4.5333, + "value": 64.63, + "curve": [ 4.622, 60.34, 4.711, 42.63 ] + }, + { "time": 4.8, "value": 31.63 }, + { "time": 4.9333, "value": 10.72 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": -44.7, + "curve": [ 0.044, -44.7, 0.089, 52.3 ] + }, + { + "time": 0.1333, + "value": 52.3, + "curve": [ 0.178, 52.3, 0.227, 48.52 ] + }, + { + "time": 0.2667, + "value": 41.27, + "curve": [ 0.332, 29.13, 0.356, 21.33 ] + }, + { + "time": 0.4, + "value": 21.33, + "curve": [ 0.511, 21.33, 0.577, 177.32 ] + }, + { + "time": 0.6667, + "value": 178.37, + "curve": [ 0.703, 178.79, 0.822, 158.2 ] + }, + { "time": 0.9, "value": 158.2 } + ], + "translate": [ + { "time": 0.4 }, + { "time": 0.9, "x": -32.41, "y": 0.65 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 21.88, + "curve": [ 0.048, 21.49, 0.089, 20.61 ] + }, + { + "time": 0.1333, + "value": 11.49, + "curve": [ 0.156, 6.92, 0.178, -12.78 ] + }, + { + "time": 0.2, + "value": -19.19, + "curve": [ 0.222, -25.6, 0.244, -26.96 ] + }, + { + "time": 0.2667, + "value": -26.96, + "curve": [ 0.311, -26.96, 0.356, -25.04 ] + }, + { + "time": 0.4, + "value": -15.9, + "curve": [ 0.433, -9.05, 0.467, 21.01 ] + }, + { + "time": 0.5, + "value": 21.01, + "curve": [ 0.533, 21.01, 0.567, -6.78 ] + }, + { + "time": 0.6, + "value": -18.23, + "curve": [ 0.622, -25.86, 0.644, -36.22 ] + }, + { + "time": 0.6667, + "value": -36.22, + "curve": [ 0.689, -36.22, 0.72, 1.23 ] + }, + { + "time": 0.7333, + "value": 10.31, + "curve": [ 0.761, 28.71, 0.822, 44.2 ] + }, + { + "time": 0.8667, + "value": 44.2, + "curve": [ 0.911, 44.2, 1, -14.97 ] + }, + { "time": 1, "value": -18.88, "curve": "stepped" }, + { + "time": 2.2333, + "value": -18.88, + "curve": [ 2.389, -18.88, 2.544, -1.96 ] + }, + { + "time": 2.7, + "value": -1.96, + "curve": [ 2.811, -1.96, 2.923, -10.35 ] + }, + { + "time": 3.0333, + "value": -10.35, + "curve": [ 3.224, -10.35, 3.411, -1.76 ] + }, + { + "time": 3.6, + "value": -1.76, + "curve": [ 3.922, -1.76, 4.244, -1.96 ] + }, + { + "time": 4.5667, + "value": -1.96, + "curve": [ 4.644, -1.96, 4.722, 34.31 ] + }, + { + "time": 4.8, + "value": 34.31, + "curve": [ 4.844, 34.31, 4.889, -1.06 ] + }, + { "time": 4.9333, "value": -18.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -2.33, + "curve": [ 0.044, -1.82, 0.089, -0.79 ] + }, + { + "time": 0.1333, + "value": -0.79, + "curve": [ 0.178, -0.79, 0.222, -12.86 ] + }, + { + "time": 0.2667, + "value": -12.86, + "curve": [ 0.322, -12.86, 0.378, -5.51 ] + }, + { + "time": 0.4333, + "value": -5.51, + "curve": [ 0.522, -5.51, 0.611, -23.93 ] + }, + { + "time": 0.7, + "value": -23.93, + "curve": [ 0.767, -23.93, 0.833, 6.31 ] + }, + { + "time": 0.9, + "value": 6.31, + "curve": [ 0.978, 6.31, 1.114, -2.63 ] + }, + { "time": 1.1333, "value": -5.63, "curve": "stepped" }, + { "time": 2.2333, "value": -5.63 }, + { "time": 2.4333, "value": -17.37 }, + { "time": 2.7, "value": 5.73, "curve": "stepped" }, + { + "time": 3.3667, + "value": 5.73, + "curve": [ 3.5, 5.73, 3.633, 1.93 ] + }, + { + "time": 3.7667, + "value": 1.93, + "curve": [ 3.867, 1.93, 3.967, 7.13 ] + }, + { + "time": 4.0667, + "value": 7.13, + "curve": [ 4.267, 7.13, 4.467, 5.73 ] + }, + { + "time": 4.6667, + "value": 5.73, + "curve": [ 4.678, 5.73, 4.732, 13.73 ] + }, + { + "time": 4.7667, + "value": 13.89, + "curve": [ 4.833, 14.19, 4.933, 4.95 ] + }, + { "time": 4.9333, "value": 3.65 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": 10.36 }, + { "time": 0.1333, "value": -23.12 }, + { "time": 0.2667, "value": -23.12 }, + { "time": 0.4, "value": -23.16, "curve": "stepped" }, + { "time": 0.4333, "value": -23.16 }, + { "time": 0.5667, "value": -23.2 } + ] + }, + "gun": { + "rotate": [ + { "value": -2.79 }, + { "time": 0.1333, "value": -24.58 } + ] + }, + "front-thigh": { + "rotate": [ + { + "curve": [ 0.052, 4.38, 0.089, 28.31 ] + }, + { + "time": 0.1333, + "value": 48.45, + "curve": [ 0.178, 68.6, 0.222, 99.39 ] + }, + { + "time": 0.2667, + "value": 120.87, + "curve": [ 0.311, 142.34, 0.356, 169.02 ] + }, + { + "time": 0.4, + "value": 177.3, + "curve": [ 0.433, 183.51, 0.467, 183.51 ] + }, + { + "time": 0.5, + "value": 183.51, + "curve": [ 0.544, 183.51, 0.589, 176.55 ] + }, + { + "time": 0.6333, + "value": 162.29, + "curve": [ 0.678, 148.03, 0.752, 108.37 ] + }, + { + "time": 0.7667, + "value": 97.94, + "curve": [ 0.819, 105.34, 0.856, 110.74 ] + }, + { + "time": 0.9, + "value": 110.74, + "curve": [ 0.944, 110.74, 1.016, 102.2 ] + }, + { "time": 1.0333, "value": 97.93 } + ] + }, + "front-shin": { + "rotate": [ + { + "curve": [ 0.044, 0.09, 0.1, -7.14 ] + }, + { + "time": 0.1333, + "value": -14.67, + "curve": [ 0.169, -22.83, 0.222, -43.77 ] + }, + { + "time": 0.2667, + "value": -43.77, + "curve": [ 0.311, -43.77, 0.344, -43.27 ] + }, + { + "time": 0.4, + "value": -33.94, + "curve": [ 0.433, -28.34, 0.467, 4.15 ] + }, + { + "time": 0.5, + "value": 9.2, + "curve": [ 0.533, 14.25, 0.567, 14.25 ] + }, + { + "time": 0.6, + "value": 14.25, + "curve": [ 0.733, 14.25, 0.867, 4.73 ] + }, + { "time": 1, "value": -0.03 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "curve": [ 0.044, 21.88, 0.089, 41.01 ] + }, + { + "time": 0.1333, + "value": 65.64, + "curve": [ 0.178, 90.28, 0.222, 127.15 ] + }, + { + "time": 0.2667, + "value": 147.79, + "curve": [ 0.311, 168.43, 0.356, 189.48 ] + }, + { + "time": 0.4, + "value": 189.48, + "curve": [ 0.433, 189.48, 0.473, 161.8 ] + }, + { + "time": 0.5, + "value": 142.56, + "curve": [ 0.542, 113.14, 0.589, 83.04 ] + }, + { + "time": 0.6, + "value": 78.15, + "curve": [ 0.613, 83.04, 0.733, 108.16 ] + }, + { + "time": 0.8, + "value": 108.16, + "curve": [ 0.878, 108.16, 1.009, 88.71 ] + }, + { "time": 1.0333, "value": 82.7 } + ] + }, + "rear-shin": { + "rotate": [ + { + "curve": [ 0.044, -19.59, 0.089, -58.76 ] + }, + { + "time": 0.1333, + "value": -58.76, + "curve": [ 0.178, -58.76, 0.222, -54.53 ] + }, + { + "time": 0.2667, + "value": -47.85, + "curve": [ 0.311, -41.16, 0.356, -33.24 ] + }, + { + "time": 0.4, + "value": -18.63, + "curve": [ 0.433, -7.68, 0.467, 28.83 ] + }, + { + "time": 0.5, + "value": 28.83, + "curve": [ 0.533, 28.83, 0.567, 15.17 ] + }, + { + "time": 0.6, + "value": 15.17, + "curve": [ 0.633, 15.17, 0.667, 16.17 ] + }, + { + "time": 0.7, + "value": 18.37, + "curve": [ 0.744, 21.32, 0.789, 27.27 ] + }, + { + "time": 0.8333, + "value": 30.61, + "curve": [ 0.878, 33.95, 0.922, 38.42 ] + }, + { + "time": 0.9667, + "value": 38.42, + "curve": [ 1.011, 38.42, 1.079, 17.39 ] + }, + { "time": 1.1, "value": 9.11 } + ] + }, + "rear-foot": { + "rotate": [ + { + "curve": [ 0.044, 0, 0.114, -5.44 ] + }, + { + "time": 0.1333, + "value": -11.63, + "curve": [ 0.158, -19.61, 0.222, -57.59 ] + }, + { + "time": 0.2667, + "value": -57.59, + "curve": [ 0.311, -57.59, 0.356, -45.6 ] + }, + { + "time": 0.4, + "value": -45.6, + "curve": [ 0.433, -45.6, 0.467, -65.99 ] + }, + { + "time": 0.5, + "value": -65.99, + "curve": [ 0.522, -65.99, 0.544, -21.7 ] + }, + { + "time": 0.5667, + "value": -21.7, + "curve": [ 0.6, -21.7, 0.633, -47.61 ] + }, + { + "time": 0.6667, + "value": -47.61, + "curve": [ 0.722, -47.61, 0.778, -25.68 ] + }, + { + "time": 0.8333, + "value": -15.6, + "curve": [ 0.878, -7.54, 0.922, 6.79 ] + }, + { + "time": 0.9667, + "value": 6.79, + "curve": [ 1.022, 6.79, 1.093, 2.23 ] + }, + { + "time": 1.1333, + "value": -6.82, + "curve": [ 1.165, -13.89, 1.178, -28.53 ] + }, + { + "time": 1.2, + "value": -28.53, + "curve": [ 1.267, -28.53, 1.333, -23.77 ] + }, + { "time": 1.4, "value": -23.77 } + ] + }, + "front-foot": { + "rotate": [ + { + "curve": [ 0.022, -21.9, 0.044, -65.7 ] + }, + { + "time": 0.0667, + "value": -65.7, + "curve": [ 0.089, -65.7, 0.111, -65.7 ] + }, + { + "time": 0.1333, + "value": -64.65, + "curve": [ 0.222, -60.43, 0.311, -52.48 ] + }, + { + "time": 0.4, + "value": -42.68, + "curve": [ 0.433, -39, 0.467, -33.17 ] + }, + { + "time": 0.5, + "value": -24.22, + "curve": [ 0.544, -12.29, 0.589, 19.98 ] + }, + { + "time": 0.6333, + "value": 19.98, + "curve": [ 0.656, 19.98, 0.678, 13.2 ] + }, + { + "time": 0.7, + "value": 2.45, + "curve": [ 0.733, -13.69, 0.767, -60.68 ] + }, + { + "time": 0.8, + "value": -60.68, + "curve": [ 0.878, -60.68, 0.956, 0.38 ] + }, + { + "time": 1.0333, + "value": 0.38, + "curve": [ 1.078, 0.38, 1.122, -31.77 ] + }, + { + "time": 1.1667, + "value": -31.77, + "curve": [ 1.211, -31.77, 1.256, -26.74 ] + }, + { "time": 1.3, "value": -24.22 } + ] + }, + "hip": { + "translate": [ + { + "curve": [ 0.081, -41.14, 0.178, -93.27, 0.038, 78.73, 0.156, 168.49 ] + }, + { + "time": 0.2667, + "x": -137.74, + "y": 169.66, + "curve": [ 0.333, -171.09, 0.4, -202.84, 0.377, 170.82, 0.467, 29.16 ] + }, + { + "time": 0.4667, + "x": -233.47, + "y": -76.63, + "curve": [ 0.5, -248.79, 0.533, -265.16, 0.521, -158.34, 0.516, -167.9 ] + }, + { + "time": 0.5667, + "x": -275.61, + "y": -209.28, + "curve": [ 0.589, -282.57, 0.608, -285.14, 0.572, -213.87, 0.611, -216.23 ] + }, + { + "time": 0.6333, + "x": -285.69, + "y": -216.23, + "curve": [ 0.713, -287.45, 0.789, -288.08, 0.711, -216.23, 0.812, -213.49 ] + }, + { + "time": 0.8667, + "x": -288.44, + "y": -209.28, + "curve": [ 0.911, -288.65, 0.965, -288.65, 0.919, -209.28, 0.967, -209.28 ] + }, + { "time": 1, "x": -288.65, "y": -209.28 } + ] + } + } + }, + "hit": { + "slots": { + "front-fist": { + "attachment": [ + { "time": 0.1667, "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "name": "mouth-grind" }, + { "time": 0.3333, "name": "mouth-smile" } + ] + } + }, + "bones": { + "torso": { + "rotate": [ + { "value": 56.42 }, + { "time": 0.3333, "value": 8.89 } + ] + }, + "neck": { + "rotate": [ + { "value": 35.39 }, + { "time": 0.2333, "value": 24.95 } + ] + }, + "head": { + "rotate": [ + { "value": 10.22 }, + { "time": 0.3333, "value": -41.3 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -310.93, + "curve": [ 0.127, -397.15, 0.248, -472.6 ] + }, + { "time": 0.3333, "value": -472.6 } + ], + "translate": [ + { "x": 7.23, "y": -13.13 } + ] + }, + "front-bracer": { + "rotate": [ + { "value": 36.99 }, + { "time": 0.3333, "value": -28.65 } + ] + }, + "front-fist": { + "rotate": [ + { "value": 13.59 }, + { "time": 0.3333, "value": 7.56 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 271.02, + "curve": [ 0.114, 297.63, 0.227, 322.97 ] + }, + { "time": 0.3333, "value": 344.16 } + ], + "translate": [ + { "time": 0.3333, "x": -0.1, "y": -0.46 } + ] + }, + "rear-bracer": { + "rotate": [ + {}, + { "time": 0.3333, "value": 40.03 } + ] + }, + "gun": { + "rotate": [ + { "value": 14.98 }, + { "time": 0.3333, "value": 39.76 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 90.94, + "curve": [ 0.076, 75.29, 0.144, 32.03 ] + }, + { "time": 0.3333, "value": 32.03 } + ], + "translate": [ + { "x": 7.21, "y": -4 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 40.52, + "curve": [ 0.099, 55.81, 0.197, 90.52 ] + }, + { "time": 0.3333, "value": 90.77 } + ], + "translate": [ + { "x": -1.96, "y": -0.32 } + ] + }, + "front-shin": { + "rotate": [ + { "value": -96.63 }, + { "time": 0.3333, "value": -15.13 } + ] + }, + "rear-shin": { + "rotate": [ + { "value": 8 }, + { "time": 0.3333, "value": -67.54 } + ] + }, + "front-foot": { + "rotate": [ + { "value": 5.4 }, + { "time": 0.3333, "value": -16.27 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": 2.67 }, + { "time": 0.3333, "value": -10.31 } + ] + }, + "hip": { + "translate": [ + { "x": -75.55, "y": -78.04 }, + { "time": 0.2333, "x": -36.48, "y": 12.42 }, + { "time": 0.3333, "x": -36.48, "y": -3 } + ] + } + } + }, + "idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "torso": { + "rotate": [ + { + "value": -16.11, + "curve": [ 0.057, -15.7, 0.268, -14.61 ] + }, + { + "time": 0.4333, + "value": -14.6, + "curve": [ 0.591, -14.59, 0.73, -15.81 ] + }, + { + "time": 0.8333, + "value": -16.63, + "curve": [ 0.915, -17.27, 1.074, -18.04 ] + }, + { + "time": 1.2333, + "value": -18.02, + "curve": [ 1.385, -18, 1.619, -16.57 ] + }, + { "time": 1.6667, "value": -16.11 } + ], + "translate": [ + { "x": -6.5 } + ], + "scale": [ + { + "curve": [ 0.156, 0.996, 0.525, 0.994, 0.106, 1.002, 0.525, 1.01 ] + }, + { + "time": 0.8333, + "x": 0.994, + "y": 1.01, + "curve": [ 1.15, 0.994, 1.52, 0.997, 1.15, 1.01, 1.519, 1.004 ] + }, + { "time": 1.6667 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -59.85, + "curve": [ 0.329, -59.85, 0.447, -64.99 ] + }, + { + "time": 0.6667, + "value": -64.99, + "curve": [ 0.997, -64.99, 1.417, -59.85 ] + }, + { "time": 1.6667, "value": -59.85 } + ], + "translate": [ + { + "x": -7.12, + "y": -8.24, + "curve": [ 0.167, -7.12, 0.5, -3.66, 0.167, -8.24, 0.5, -5.93 ] + }, + { + "time": 0.6667, + "x": -3.66, + "y": -5.93, + "curve": [ 0.917, -3.66, 1.417, -7.12, 0.917, -5.93, 1.417, -8.24 ] + }, + { "time": 1.6667, "x": -7.12, "y": -8.24 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 39.08, + "curve": [ 0.37, 38.67, 0.55, 32.29 ] + }, + { + "time": 0.7333, + "value": 32.29, + "curve": [ 0.967, 32.29, 1.433, 39.08 ] + }, + { "time": 1.6667, "value": 39.08 } + ], + "translate": [ + { + "x": -1.83, + "y": -6.48, + "curve": [ 0.167, -1.83, 0.5, 0.35, 0.167, -6.48, 0.447, -4.92 ] + }, + { + "time": 0.6667, + "x": 0.35, + "y": -4.92, + "curve": [ 0.917, 0.35, 1.417, -1.83, 0.917, -4.92, 1.417, -6.48 ] + }, + { "time": 1.6667, "x": -1.83, "y": -6.48 } + ] + }, + "neck": { + "rotate": [ + { + "curve": [ 0.167, 0, 0.5, 2.39 ] + }, + { + "time": 0.6667, + "value": 2.39, + "curve": [ 0.917, 2.39, 1.417, 0 ] + }, + { "time": 1.6667 } + ], + "translate": [ + { "x": -1.89, "y": -4.76 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 0.65, + "curve": [ 0.157, 0.6, 0.372, -4.31 ] + }, + { + "time": 0.6667, + "value": -4.34, + "curve": [ 1.262, -4.34, 1.32, 0.65 ] + }, + { "time": 1.6667, "value": 0.65 } + ], + "translate": [ + { "x": -13.4, "y": 6.7 } + ], + "scale": [ + { + "x": 0.945, + "curve": [ 0.157, 0.945, 0.372, 0.917, 0.157, 1, 0.372, 1 ] + }, + { + "time": 0.6667, + "x": 0.917, + "curve": [ 1.262, 0.917, 1.32, 0.945, 1.262, 1, 1.32, 1 ] + }, + { "time": 1.6667, "x": 0.945 } + ] + }, + "front-shin": { + "rotate": [ + { "value": -19.59 } + ], + "scale": [ + { + "curve": [ 0.157, 1, 0.372, 0.994, 0.157, 1, 0.372, 1 ] + }, + { + "time": 0.6667, + "x": 0.994, + "curve": [ 1.262, 0.994, 1.32, 1, 1.262, 1, 1.32, 1 ] + }, + { "time": 1.6667 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 30.51, + "curve": [ 0.157, 30.6, 0.372, 40.09 ] + }, + { + "time": 0.6667, + "value": 40.15, + "curve": [ 1.262, 40.14, 1.32, 30.51 ] + }, + { "time": 1.6667, "value": 30.51 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -24.14, + "curve": [ 0.157, -24.33, 0.372, -43.64 ] + }, + { + "time": 0.6667, + "value": -43.77, + "curve": [ 1.262, -43.76, 1.32, -23.83 ] + }, + { "time": 1.6667, "value": -23.83 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 4.83, + "curve": [ 0.157, 4.88, 0.372, 10.02 ] + }, + { + "time": 0.6667, + "value": 10.05, + "curve": [ 1.262, 10.05, 1.32, 5.14 ] + }, + { "time": 1.6667, "value": 5.14 } + ], + "scale": [ + { "x": 0.755, "y": 1.31 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -7.65, + "curve": [ 0.157, -7.54, 0.372, 3.78 ] + }, + { + "time": 0.6667, + "value": 3.85, + "curve": [ 1.262, 3.84, 1.32, -7.34 ] + }, + { "time": 1.6667, "value": -7.34 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": -17.16, + "curve": [ 0.167, -17.16, 0.447, -4.1 ] + }, + { + "time": 0.6667, + "value": -4.1, + "curve": [ 0.997, -4.1, 1.417, -17.16 ] + }, + { "time": 1.6667, "value": -17.16 } + ] + }, + "head": { + "rotate": [ + { + "value": -5.51, + "curve": [ 0.167, -5.51, 0.7, -3.12 ] + }, + { + "time": 0.8667, + "value": -3.12, + "curve": [ 1.117, -3.12, 1.417, -5.51 ] + }, + { "time": 1.6667, "value": -5.51 } + ], + "scale": [ + { + "curve": [ 0.217, 1, 0.546, 0.996, 0.217, 1, 0.546, 1.007 ] + }, + { + "time": 0.8667, + "x": 0.996, + "y": 1.007, + "curve": [ 1.171, 0.996, 1.467, 1, 1.171, 1.007, 1.467, 1 ] + }, + { "time": 1.6667 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 35.2, + "curve": [ 0.086, 36.03, 0.514, 40.31 ] + }, + { + "time": 0.6667, + "value": 40.3, + "curve": [ 0.859, 40.29, 0.969, 32.24 ] + }, + { + "time": 1.2, + "value": 32.31, + "curve": [ 1.401, 32.37, 1.561, 34.14 ] + }, + { "time": 1.6667, "value": 35.2 } + ] + }, + "gun": { + "rotate": [ + { + "curve": [ 0.167, 0, 0.581, -12.7 ] + }, + { + "time": 0.8667, + "value": -12.7, + "curve": [ 1.131, -12.7, 1.437, -0.11 ] + }, + { "time": 1.6667 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -6.85, + "curve": [ 0.181, -5.23, 0.5, -3.97 ] + }, + { + "time": 0.6667, + "value": -3.89, + "curve": [ 0.84, -3.81, 1.042, -9.89 ] + }, + { + "time": 1.2667, + "value": -9.76, + "curve": [ 1.428, -9.66, 1.537, -8.3 ] + }, + { "time": 1.6667, "value": -6.85 } + ], + "scale": [ + { + "curve": [ 0.167, 1, 0.5, 0.886, 0.167, 1, 0.5, 1.101 ] + }, + { + "time": 0.6667, + "x": 0.886, + "y": 1.101, + "curve": [ 0.917, 0.886, 1.417, 1, 0.917, 1.101, 1.417, 1 ] + }, + { "time": 1.6667 } + ] + }, + "hip": { + "translate": [ + { + "x": -6.64, + "y": -23.02, + "curve": [ 0.157, -6.51, 0.372, 6.19, 0.157, -23.13, 0.372, -34.93 ] + }, + { + "time": 0.6667, + "x": 6.28, + "y": -35.01, + "curve": [ 1.262, 6.27, 1.32, -6.64, 1.262, -35, 1.32, -23.02 ] + }, + { "time": 1.6667, "x": -6.64, "y": -23.02 } + ] + } + } + }, + "jump": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" }, + { "time": 0.1, "name": "front-fist-closed" }, + { "time": 0.8333, "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { + "value": 55.08, + "curve": [ 0.007, 46.66, 0.043, 26.3 ] + }, + { + "time": 0.0667, + "value": 22.84, + "curve": [ 0.1, 17.99, 0.165, 15.78 ] + }, + { + "time": 0.2333, + "value": 15.71, + "curve": [ 0.309, 15.63, 0.411, 36.56 ] + }, + { + "time": 0.5, + "value": 36.56, + "curve": [ 0.656, 36.56, 0.811, 33.41 ] + }, + { + "time": 0.9667, + "value": 26.43, + "curve": [ 1.011, 24.43, 1.056, 9.63 ] + }, + { + "time": 1.1, + "value": 9.63, + "curve": [ 1.122, 9.63, 1.144, 9.63 ] + }, + { + "time": 1.1667, + "value": 12.33, + "curve": [ 1.178, 13.68, 1.189, 47.62 ] + }, + { + "time": 1.2, + "value": 56.85, + "curve": [ 1.211, 66.08, 1.222, 67.7 ] + }, + { + "time": 1.2333, + "value": 67.72, + "curve": [ 1.261, 67.77, 1.322, 58.12 ] + }, + { "time": 1.3333, "value": 55.08 } + ], + "translate": [ + { + "x": -5.13, + "y": 11.55, + "curve": [ 0.422, -5.13, 0.733, -5.25, 0.422, 11.55, 0.733, 11.55 ] + }, + { + "time": 1.1, + "x": -5.25, + "y": 11.55, + "curve": [ 1.133, -5.25, 1.167, -4.54, 1.133, 11.55, 1.167, -1.07 ] + }, + { + "time": 1.2, + "x": -3.98, + "y": -1.07, + "curve": [ 1.211, -3.79, 1.222, -3.62, 1.211, -1.07, 1.222, 5.22 ] + }, + { + "time": 1.2333, + "x": -3.5, + "y": 5.73, + "curve": [ 1.245, -3.37, 1.289, -3.68, 1.245, 6.24, 1.283, 5.14 ] + }, + { + "time": 1.3, + "x": -4.1, + "y": 5.23, + "curve": [ 1.311, -4.52, 1.322, -4.99, 1.32, 5.32, 1.322, 9.78 ] + }, + { "time": 1.3333, "x": -5.13, "y": 11.55 } + ] + }, + "torso": { + "rotate": [ + { + "value": -45.57, + "curve": [ 0.022, -44.61, 0.03, -39.06 ] + }, + { + "time": 0.0667, + "value": -35.29, + "curve": [ 0.12, -29.77, 0.28, -19.95 ] + }, + { + "time": 0.4333, + "value": -19.95, + "curve": [ 0.673, -19.95, 0.871, -22.38 ] + }, + { + "time": 0.9667, + "value": -27.08, + "curve": [ 1.094, -33.33, 1.176, -44.93 ] + }, + { "time": 1.3333, "value": -45.57 } + ], + "translate": [ + { "x": -3.79, "y": -0.77 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 12.81, + "curve": [ 0.067, 12.81, 0.242, 67.88 ] + }, + { + "time": 0.2667, + "value": 74.11, + "curve": [ 0.314, 86.02, 0.454, 92.23 ] + }, + { + "time": 0.5667, + "value": 92.24, + "curve": [ 0.753, 92.26, 0.966, 67.94 ] + }, + { + "time": 1, + "value": 61.32, + "curve": [ 1.039, 53.75, 1.218, 12.68 ] + }, + { "time": 1.3333, "value": 12.81 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -115.64, + "curve": [ 0.067, -117.17, 0.125, -117.15 ] + }, + { + "time": 0.1667, + "value": -117.15, + "curve": [ 0.225, -117.15, 0.332, -108.76 ] + }, + { + "time": 0.4, + "value": -107.15, + "curve": [ 0.48, -105.26, 0.685, -103.49 ] + }, + { + "time": 0.7667, + "value": -101.97, + "curve": [ 0.826, -100.87, 0.919, -92.3 ] + }, + { + "time": 1, + "value": -92.28, + "curve": [ 1.113, -92.26, 1.297, -114.22 ] + }, + { "time": 1.3333, "value": -115.64 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -40.21, + "curve": [ 0.054, -35.46, 0.15, -31.12 ] + }, + { + "time": 0.2, + "value": -31.12, + "curve": [ 0.308, -31.12, 0.547, -80.12 ] + }, + { + "time": 0.6333, + "value": -96.56, + "curve": [ 0.697, -108.56, 0.797, -112.54 ] + }, + { + "time": 0.8667, + "value": -112.6, + "curve": [ 1.137, -112.84, 1.274, -49.19 ] + }, + { "time": 1.3333, "value": -40.21 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 20.54, + "curve": [ 0.054, 32.23, 0.192, 55.84 ] + }, + { + "time": 0.2333, + "value": 62.58, + "curve": [ 0.29, 71.87, 0.375, 79.28 ] + }, + { + "time": 0.4333, + "value": 79.18, + "curve": [ 0.555, 78.98, 0.684, 27.54 ] + }, + { + "time": 0.7333, + "value": 13.28, + "curve": [ 0.786, -1.85, 0.874, -24.76 ] + }, + { + "time": 1, + "value": -25.45, + "curve": [ 1.165, -26.36, 1.303, 9.1 ] + }, + { "time": 1.3333, "value": 20.54 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16, + "curve": [ 0.114, -39.59, 0.3, -45.61 ] + }, + { + "time": 0.4, + "value": -45.61, + "curve": [ 0.442, -45.61, 0.537, -21.54 ] + }, + { + "time": 0.5667, + "value": -15.4, + "curve": [ 0.592, -10.23, 0.692, 11.89 ] + }, + { + "time": 0.7333, + "value": 11.73, + "curve": [ 0.783, 11.54, 0.831, 1.8 ] + }, + { + "time": 0.8667, + "value": -5.78, + "curve": [ 0.897, -12.22, 0.901, -14.22 ] + }, + { + "time": 0.9333, + "value": -14.51, + "curve": [ 0.974, -14.89, 0.976, 10.38 ] + }, + { + "time": 1, + "value": 10.55, + "curve": [ 1.027, 10.74, 1.023, -8.44 ] + }, + { + "time": 1.0333, + "value": -8.42, + "curve": [ 1.059, -8.36, 1.074, 10.12 ] + }, + { + "time": 1.1, + "value": 10.22, + "curve": [ 1.168, 10.48, 1.27, -36.07 ] + }, + { "time": 1.3333, "value": -36.16 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.5, + "curve": [ 0.048, 36.1, 0.168, 20.45 ] + }, + { + "time": 0.3, + "value": 20.45, + "curve": [ 0.476, 20.45, 0.571, 33.76 ] + }, + { + "time": 0.6, + "value": 38.67, + "curve": [ 0.642, 45.8, 0.681, 57.44 ] + }, + { + "time": 0.7333, + "value": 62.91, + "curve": [ 0.829, 72.8, 0.996, 77.61 ] + }, + { + "time": 1.0333, + "value": 80.37, + "curve": [ 1.082, 83.94, 1.148, 90.6 ] + }, + { + "time": 1.2, + "value": 90.6, + "curve": [ 1.248, 90.46, 1.289, 44.58 ] + }, + { "time": 1.3333, "value": 40.5 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.022, 25.12, 0.187, -0.89 ] + }, + { + "time": 0.2, + "value": -2.52, + "curve": [ 0.257, -9.92, 0.372, -17.38 ] + }, + { + "time": 0.4333, + "value": -17.41, + "curve": [ 0.54, -17.47, 0.659, -16.91 ] + }, + { + "time": 0.7667, + "value": -12.1, + "curve": [ 0.907, -5.79, 1.025, 14.58 ] + }, + { + "time": 1.1, + "value": 20.58, + "curve": [ 1.191, 27.85, 1.283, 29.67 ] + }, + { "time": 1.3333, "value": 29.67 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.88, + "curve": [ 0.104, 11.82, 0.179, 11.15 ] + }, + { + "time": 0.2, + "value": 10.08, + "curve": [ 0.255, 7.29, 0.405, -8.15 ] + }, + { + "time": 0.4333, + "value": -9.35, + "curve": [ 0.508, -12.48, 0.595, -13.14 ] + }, + { + "time": 0.6667, + "value": -12.61, + "curve": [ 0.714, -12.26, 0.815, -5.57 ] + }, + { + "time": 0.8333, + "value": -4.08, + "curve": [ 0.883, -0.07, 1.011, 10.6 ] + }, + { + "time": 1.1, + "value": 15.01, + "curve": [ 1.178, 18.87, 1.279, 20.64 ] + }, + { "time": 1.3333, "value": 20.73 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.14, + "curve": [ 0.063, 13.1, 0.222, -20.78 ] + }, + { + "time": 0.3333, + "value": -20.78, + "curve": [ 0.467, -20.78, 0.6, 7.26 ] + }, + { + "time": 0.7333, + "value": 11.44, + "curve": [ 0.811, 13.88, 0.889, 13.88 ] + }, + { + "time": 0.9667, + "value": 13.88, + "curve": [ 1.044, 13.88, 1.122, 7.56 ] + }, + { + "time": 1.2, + "value": 7.56, + "curve": [ 1.244, 7.56, 1.289, 11.28 ] + }, + { "time": 1.3333, "value": 13.14 } + ], + "scale": [ + { + "curve": [ 0.041, 1, 0.052, 0.962, 0.041, 1, 0.052, 1.137 ] + }, + { + "time": 0.1, + "x": 0.954, + "y": 1.137, + "curve": [ 0.202, 0.962, 0.318, 1, 0.202, 1.137, 0.252, 1.002 ] + }, + { "time": 0.4667 }, + { + "time": 1.0667, + "x": 1.002, + "curve": [ 1.092, 1.002, 1.126, 1.173, 1.092, 1, 1.128, 0.975 ] + }, + { + "time": 1.1667, + "x": 1.174, + "y": 0.973, + "curve": [ 1.204, 1.175, 1.233, 0.959, 1.206, 0.972, 1.227, 1.062 ] + }, + { + "time": 1.2667, + "x": 0.958, + "y": 1.063, + "curve": [ 1.284, 0.958, 1.311, 1, 1.288, 1.063, 1.311, 1 ] + }, + { "time": 1.3333 } + ] + }, + "hip": { + "translate": [ + { + "y": -45.46, + "curve": [ 0.042, -0.09, 0.15, 15.22, 0.031, 44.98, 0.123, 289.73 ] + }, + { + "time": 0.2, + "x": 15.22, + "y": 415.85, + "curve": [ 0.332, 15.22, 0.539, -34.52, 0.271, 532.93, 0.483, 753.87 ] + }, + { + "time": 0.7667, + "x": -34.52, + "y": 754.96, + "curve": [ 0.888, -34.52, 1.057, -21.95, 1.049, 754.54, 1.098, 379.84 ] + }, + { + "time": 1.1333, + "x": -15.67, + "y": 266.77, + "curve": [ 1.144, -14.77, 1.188, -10.53, 1.15, 213.72, 1.172, -61.32 ] + }, + { + "time": 1.2333, + "x": -6.53, + "y": -61.34, + "curve": [ 1.272, -3.22, 1.311, 0.05, 1.291, -61.36, 1.296, -44.8 ] + }, + { "time": 1.3333, "y": -45.46 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -74.19, + "curve": [ 0, -51.14, 0.042, -12.54 ] + }, + { + "time": 0.1667, + "value": -12.28, + "curve": [ 0.285, -12.32, 0.389, -51.96 ] + }, + { + "time": 0.5, + "value": -51.96, + "curve": [ 0.633, -51.96, 0.767, -40.17 ] + }, + { + "time": 0.9, + "value": -30.59, + "curve": [ 0.967, -25.8, 1.033, -16.01 ] + }, + { + "time": 1.1, + "value": -8.85, + "curve": [ 1.122, -6.46, 1.144, -1.91 ] + }, + { + "time": 1.1667, + "value": -1.91, + "curve": [ 1.178, -1.91, 1.189, -58.19 ] + }, + { + "time": 1.2, + "value": -72.71, + "curve": [ 1.211, -87.23, 1.222, -89.05 ] + }, + { + "time": 1.2333, + "value": -89.05, + "curve": [ 1.273, -89.05, 1.308, -79.55 ] + }, + { "time": 1.3333, "value": -74.19 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 15.88, + "curve": [ 0, 13.33, 0.05, -26.64 ] + }, + { + "time": 0.0667, + "value": -26.64, + "curve": [ 0.192, -26.64, 0.442, -11.77 ] + }, + { + "time": 0.5667, + "value": -11.77, + "curve": [ 0.692, -11.77, 0.942, -19.36 ] + }, + { + "time": 1.0667, + "value": -19.36, + "curve": [ 1.089, -19.36, 1.127, -67.74 ] + }, + { + "time": 1.1667, + "value": -63.62, + "curve": [ 1.178, -62.51, 1.189, 5.83 ] + }, + { + "time": 1.2, + "value": 11.39, + "curve": [ 1.222, 22.51, 1.244, 22.51 ] + }, + { + "time": 1.2667, + "value": 22.51, + "curve": [ 1.289, 22.51, 1.333, 16.45 ] + }, + { "time": 1.3333, "value": 15.88 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -7.14, + "curve": [ 0.044, -17.32, 0.089, -37.67 ] + }, + { + "time": 0.1333, + "value": -37.67, + "curve": [ 0.311, -37.67, 0.521, -26.72 ] + }, + { + "time": 0.6667, + "value": -15.71, + "curve": [ 0.776, -7.49, 0.911, 14.92 ] + }, + { + "time": 1.0333, + "value": 14.92, + "curve": [ 1.133, 14.92, 1.233, 0.21 ] + }, + { "time": 1.3333, "value": -7.14 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.36, + "curve": [ 0.022, 16.28, 0.15, 30.81 ] + }, + { + "time": 0.2, + "value": 30.81, + "curve": [ 0.258, 30.81, 0.375, 13.26 ] + }, + { + "time": 0.4333, + "value": 13.26, + "curve": [ 0.508, 13.26, 0.658, 15.05 ] + }, + { + "time": 0.7333, + "value": 14.98, + "curve": [ 0.789, 14.94, 0.828, 13.62 ] + }, + { + "time": 0.8667, + "value": 12.72, + "curve": [ 0.887, 12.25, 0.984, 9.83 ] + }, + { + "time": 1.0333, + "value": 8.6, + "curve": [ 1.045, 8.31, 1.083, 7.55 ] + }, + { + "time": 1.1333, + "value": 7.13, + "curve": [ 1.175, 6.78, 1.283, 6.18 ] + }, + { "time": 1.3333, "value": 6.18 } + ] + } + }, + "events": [ + { "time": 1.2, "name": "footstep" } + ] + }, + "run": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { + "value": 49.77, + "curve": [ 0.007, 49.71, 0.022, 41.99 ] + }, + { + "time": 0.0333, + "value": 32.26, + "curve": [ 0.044, 22.54, 0.056, 0.1 ] + }, + { + "time": 0.0667, + "value": -8.56, + "curve": [ 0.078, -17.22, 0.089, -19.05 ] + }, + { + "time": 0.1, + "value": -19.71, + "curve": [ 0.144, -22.38, 0.189, -22.38 ] + }, + { + "time": 0.2333, + "value": -22.38, + "curve": [ 0.267, -22.38, 0.3, 36.57 ] + }, + { + "time": 0.3333, + "value": 54.69, + "curve": [ 0.367, 72.82, 0.4, 86.37 ] + }, + { + "time": 0.4333, + "value": 86.37, + "curve": [ 0.478, 86.37, 0.522, 46.94 ] + }, + { + "time": 0.5667, + "value": 46.94, + "curve": [ 0.589, 46.94, 0.652, 49.34 ] + }, + { "time": 0.6667, "value": 49.77 } + ], + "translate": [ + { + "x": -7.86, + "y": 10.34, + "curve": [ 0.036, -7.85, 0.123, -6.71, 0.056, 10.34, 0.108, 9.74 ] + }, + { + "time": 0.1667, + "x": -5.7, + "y": 7.99, + "curve": [ 0.22, -4.49, 0.295, -0.78, 0.236, 5.93, 0.28, 3.22 ] + }, + { + "time": 0.3333, + "x": 1.68, + "y": 3.19, + "curve": [ 0.358, 3.28, 0.449, 9.99, 0.384, 3.16, 0.449, 4.98 ] + }, + { + "time": 0.5, + "x": 9.99, + "y": 6.76, + "curve": [ 0.556, 10, 0.611, -7.86, 0.556, 8.69, 0.611, 10.34 ] + }, + { "time": 0.6667, "x": -7.86, "y": 10.34 } + ] + }, + "torso": { + "rotate": [ + { + "value": -38.65, + "curve": [ 0.022, -39.16, 0.067, -41.4 ] + }, + { + "time": 0.1, + "value": -41.4, + "curve": [ 0.156, -41.4, 0.211, -37.6 ] + }, + { + "time": 0.2667, + "value": -37.6, + "curve": [ 0.289, -37.6, 0.315, -38.2 ] + }, + { + "time": 0.3333, + "value": -38.63, + "curve": [ 0.369, -39.48, 0.434, -41.38 ] + }, + { + "time": 0.4667, + "value": -41.39, + "curve": [ 0.512, -41.39, 0.556, -37.69 ] + }, + { + "time": 0.6, + "value": -37.69, + "curve": [ 0.622, -37.69, 0.652, -38.3 ] + }, + { "time": 0.6667, "value": -38.65 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 17.72, + "curve": [ 0.025, 28.51, 0.067, 54.38 ] + }, + { + "time": 0.1, + "value": 54.38, + "curve": [ 0.144, 54.38, 0.189, 19.31 ] + }, + { + "time": 0.2333, + "value": 19.31, + "curve": [ 0.254, 19.31, 0.278, 32.87 ] + }, + { + "time": 0.3, + "value": 32.87, + "curve": [ 0.311, 32.87, 0.322, 32.87 ] + }, + { + "time": 0.3333, + "value": 28.23, + "curve": [ 0.344, 23.6, 0.356, 4.08 ] + }, + { + "time": 0.3667, + "value": -3.6, + "curve": [ 0.389, -18.95, 0.411, -38.43 ] + }, + { + "time": 0.4333, + "value": -40.85, + "curve": [ 0.478, -45.69, 0.522, -45.69 ] + }, + { + "time": 0.5667, + "value": -45.69, + "curve": [ 0.6, -45.69, 0.633, -7.24 ] + }, + { "time": 0.6667, "value": 17.72 } + ], + "translate": [ + { + "x": -13.59, + "y": 3.21, + "curve": [ 0.013, -12.85, 0.183, -8.55, 0.03, 4.05, 0.183, 6.17 ] + }, + { + "time": 0.2333, + "x": -8.55, + "y": 6.17, + "curve": [ 0.308, -8.55, 0.492, -19.75, 0.308, 6.17, 0.492, 0.61 ] + }, + { + "time": 0.5667, + "x": -19.75, + "y": 0.61, + "curve": [ 0.592, -19.75, 0.633, -15.46, 0.592, 0.61, 0.633, 2.28 ] + }, + { "time": 0.6667, "x": -13.59, "y": 3.21 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": 324.21, + "curve": [ 0.051, 363.15, 0.145, 449.66 ] + }, + { + "time": 0.2333, + "value": 449.66, + "curve": [ 0.28, 450.07, 0.324, 419.51 ] + }, + { + "time": 0.3333, + "value": 411.11, + "curve": [ 0.358, 390.19, 0.445, 293.13 ] + }, + { + "time": 0.5667, + "value": 292.23, + "curve": [ 0.599, 291.99, 0.633, 298.54 ] + }, + { "time": 0.6667, "value": 324.21 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 7.49, + "curve": [ 0.032, 2.15, 0.089, -2.82 ] + }, + { + "time": 0.1333, + "value": -2.8, + "curve": [ 0.186, -2.78, 0.221, 26.29 ] + }, + { + "time": 0.2333, + "value": 32.37, + "curve": [ 0.247, 39.19, 0.286, 61.45 ] + }, + { + "time": 0.3333, + "value": 61.58, + "curve": [ 0.371, 61.69, 0.42, 55.79 ] + }, + { + "time": 0.4667, + "value": 49.68, + "curve": [ 0.533, 40.96, 0.643, 13.39 ] + }, + { "time": 0.6667, "value": 7.49 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -10.96, + "curve": [ 0.014, -13.6, 0.036, -43.27 ] + }, + { + "time": 0.0667, + "value": -43.37, + "curve": [ 0.102, -43.49, 0.182, -28.46 ] + }, + { + "time": 0.2, + "value": -23.04, + "curve": [ 0.23, -13.87, 0.264, 3.86 ] + }, + { + "time": 0.3333, + "value": 3.7, + "curve": [ 0.38, 3.64, 0.489, -21.29 ] + }, + { + "time": 0.5667, + "value": -21.29, + "curve": [ 0.6, -21.29, 0.633, -10.96 ] + }, + { "time": 0.6667, "value": -10.96 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 35.32, + "curve": [ 0.028, 18.56, 0.128, -79.86 ] + }, + { + "time": 0.2333, + "value": -79.87, + "curve": [ 0.38, -79.88, 0.403, 63.25 ] + }, + { + "time": 0.5667, + "value": 64.13, + "curve": [ 0.607, 64.35, 0.633, 55.07 ] + }, + { "time": 0.6667, "value": 35.32 } + ], + "translate": [ + { + "x": -4.58, + "y": 0.93, + "curve": [ 0.044, -5.37, 0.169, -5.48, 0.044, 2.63, 0.169, 2.85 ] + }, + { + "time": 0.2333, + "x": -5.48, + "y": 2.85, + "curve": [ 0.346, -5.48, 0.475, -2.68, 0.346, 2.85, 0.475, -3.13 ] + }, + { + "time": 0.5667, + "x": -2.68, + "y": -3.13, + "curve": [ 0.611, -2.68, 0.633, -3.98, 0.611, -3.13, 0.633, -0.35 ] + }, + { "time": 0.6667, "x": -4.58, "y": 0.93 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": 17.03 }, + { + "time": 0.2333, + "value": -13.07, + "curve": [ 0.252, -16.08, 0.297, -19.37 ] + }, + { + "time": 0.3333, + "value": -19.38, + "curve": [ 0.435, -19.41, 0.522, 38.96 ] + }, + { + "time": 0.5667, + "value": 38.87, + "curve": [ 0.619, 38.76, 0.625, 24.64 ] + }, + { "time": 0.6667, "value": 17.03 } + ] + }, + "neck": { + "rotate": [ + { + "value": 10.23, + "curve": [ 0.024, 9.75, 0.075, 9.74 ] + }, + { + "time": 0.1, + "value": 9.74, + "curve": [ 0.125, 9.74, 0.208, 13.36 ] + }, + { + "time": 0.2333, + "value": 13.36, + "curve": [ 0.258, 13.36, 0.3, 10.88 ] + }, + { + "time": 0.3333, + "value": 10.3, + "curve": [ 0.367, 9.72, 0.408, 9.72 ] + }, + { + "time": 0.4333, + "value": 9.72, + "curve": [ 0.458, 9.72, 0.542, 13.36 ] + }, + { + "time": 0.5667, + "value": 13.36, + "curve": [ 0.592, 13.36, 0.633, 10.91 ] + }, + { "time": 0.6667, "value": 10.23 } + ] + }, + "head": { + "rotate": [ + { + "value": 8.93, + "curve": [ 0.033, 7.96, 0.065, 6.03 ] + }, + { + "time": 0.1, + "value": 6.03, + "curve": [ 0.146, 6.03, 0.189, 10.78 ] + }, + { + "time": 0.2333, + "value": 10.78, + "curve": [ 0.267, 10.78, 0.309, 9.94 ] + }, + { + "time": 0.3333, + "value": 8.93, + "curve": [ 0.358, 7.93, 0.388, 6.1 ] + }, + { + "time": 0.4333, + "value": 6.1, + "curve": [ 0.486, 6.1, 0.544, 10.76 ] + }, + { + "time": 0.6, + "value": 10.76, + "curve": [ 0.622, 10.76, 0.652, 9.58 ] + }, + { "time": 0.6667, "value": 8.93 } + ], + "scale": [ + { + "x": 0.992, + "y": 1.01, + "curve": [ 0.036, 0.991, 0.068, 0.991, 0.014, 1.013, 0.083, 1.026 ] + }, + { + "time": 0.1, + "x": 0.991, + "y": 1.026, + "curve": [ 0.128, 0.991, 0.205, 1.038, 0.128, 1.026, 0.197, 0.982 ] + }, + { + "time": 0.2333, + "x": 1.038, + "y": 0.982, + "curve": [ 0.272, 1.038, 0.305, 1.008, 0.262, 0.982, 0.311, 0.995 ] + }, + { + "time": 0.3333, + "curve": [ 0.351, 0.995, 0.417, 0.981, 0.359, 1.006, 0.417, 1.026 ] + }, + { + "time": 0.4333, + "x": 0.981, + "y": 1.026, + "curve": [ 0.467, 0.981, 0.533, 1.037, 0.467, 1.026, 0.533, 0.982 ] + }, + { + "time": 0.5667, + "x": 1.037, + "y": 0.982, + "curve": [ 0.592, 1.037, 0.636, 0.993, 0.592, 0.982, 0.64, 1.004 ] + }, + { "time": 0.6667, "x": 0.992, "y": 1.01 } + ] + }, + "gun": { + "rotate": [ + { + "value": 18.25, + "curve": [ 0.033, 19.24, 0.087, 20.25 ] + }, + { + "time": 0.1333, + "value": 20.19, + "curve": [ 0.168, 20.32, 0.254, -8.82 ] + }, + { + "time": 0.2667, + "value": -11.88, + "curve": [ 0.291, -17.91, 0.344, -24.11 ] + }, + { + "time": 0.4, + "value": -23.88, + "curve": [ 0.448, -23.69, 0.533, -15.47 ] + }, + { "time": 0.5667, "value": -8.69 }, + { "time": 0.6667, "value": 18.25 } + ] + }, + "hip": { + "translate": [ + { + "x": 0.63, + "y": -34.19, + "curve": [ 0.042, 0.39, 0.118, 7.62, 0.042, -33.83, 0.084, 20.04 ] + }, + { + "time": 0.1667, + "x": 7.61, + "y": 20.36, + "curve": [ 0.194, 7.6, 0.21, 5.06, 0.204, 20.65, 0.217, -8.69 ] + }, + { + "time": 0.2333, + "x": 1.68, + "y": -18.48, + "curve": [ 0.279, -4.99, 0.297, -5.64, 0.254, -31.08, 0.292, -34.55 ] + }, + { + "time": 0.3333, + "x": -5.76, + "y": -35, + "curve": [ 0.379, -5.9, 0.451, 6.8, 0.384, -35.56, 0.416, 17.6 ] + }, + { + "time": 0.5, + "x": 6.61, + "y": 17.01, + "curve": [ 0.536, 6.47, 0.545, 3.56, 0.533, 16.75, 0.548, -8.71 ] + }, + { + "time": 0.5667, + "x": 0.35, + "y": -18.81, + "curve": [ 0.597, -4.07, 0.633, 0.82, 0.584, -28.58, 0.633, -34.48 ] + }, + { "time": 0.6667, "x": 0.63, "y": -34.19 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -27.81, + "curve": [ 0.078, -27.81, 0.156, 17.7 ] + }, + { + "time": 0.2333, + "value": 17.7, + "curve": [ 0.256, 17.7, 0.278, 12.8 ] + }, + { + "time": 0.3, + "value": 12.8, + "curve": [ 0.311, 12.8, 0.322, 17.93 ] + }, + { + "time": 0.3333, + "value": 20.49, + "curve": [ 0.344, 20.49, 0.356, 36.91 ] + }, + { + "time": 0.3667, + "value": 33.49, + "curve": [ 0.378, 30.04, 0.389, 28.84 ] + }, + { + "time": 0.4, + "value": 19.93, + "curve": [ 0.411, 10.9, 0.422, -5.84 ] + }, + { + "time": 0.4333, + "value": -8.18, + "curve": [ 0.478, -17.39, 0.523, 4.88 ] + }, + { + "time": 0.5667, + "value": 2.21, + "curve": [ 0.6, 0.19, 0.633, -27.81 ] + }, + { "time": 0.6667, "value": -27.81 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 11.76, + "curve": [ 0.008, 11.76, 0.02, 19.97 ] + }, + { + "time": 0.0333, + "value": 20.38, + "curve": [ 0.044, 20.72, 0.056, 17.21 ] + }, + { + "time": 0.0667, + "value": 11.96, + "curve": [ 0.079, 6.01, 0.089, -24.56 ] + }, + { + "time": 0.1, + "value": -25.8, + "curve": [ 0.144, -30.78, 0.189, -30.78 ] + }, + { + "time": 0.2333, + "value": -30.78, + "curve": [ 0.267, -30.78, 0.3, -29.2 ] + }, + { + "time": 0.3333, + "value": -24.64, + "curve": [ 0.389, -17.03, 0.444, -0.27 ] + }, + { + "time": 0.5, + "value": 5.74, + "curve": [ 0.556, 11.76, 0.633, 11.76 ] + }, + { "time": 0.6667, "value": 11.76 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -66.44, + "curve": [ 0.011, -66.44, 0.022, -65.11 ] + }, + { + "time": 0.0333, + "value": -58, + "curve": [ 0.044, -50.9, 0.056, -28.78 ] + }, + { + "time": 0.0667, + "value": -23.84, + "curve": [ 0.078, -18.9, 0.089, -18.9 ] + }, + { + "time": 0.1, + "value": -18.9, + "curve": [ 0.144, -18.9, 0.189, -66.55 ] + }, + { + "time": 0.2333, + "value": -85.8, + "curve": [ 0.267, -100.25, 0.3, -120 ] + }, + { + "time": 0.3333, + "value": -120, + "curve": [ 0.367, -120, 0.4, -116.77 ] + }, + { + "time": 0.4333, + "value": -103.62, + "curve": [ 0.456, -94.85, 0.478, -73.54 ] + }, + { + "time": 0.5, + "value": -54.26, + "curve": [ 0.522, -34.99, 0.544, -5.08 ] + }, + { + "time": 0.5667, + "value": -5.08, + "curve": [ 0.589, -5.08, 0.611, -31.56 ] + }, + { + "time": 0.6333, + "value": -45.19, + "curve": [ 0.644, -52.01, 0.656, -66.44 ] + }, + { "time": 0.6667, "value": -66.44 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -99.91, + "curve": [ 0.048, -99.45, 0.067, -87.25 ] + }, + { + "time": 0.1, + "value": -72.41, + "curve": [ 0.144, -52.61, 0.189, 4.01 ] + }, + { + "time": 0.2333, + "value": 4.01, + "curve": [ 0.256, 4.01, 0.278, -32.4 ] + }, + { + "time": 0.3, + "value": -46.27, + "curve": [ 0.311, -53.2, 0.322, -58.41 ] + }, + { + "time": 0.3333, + "value": -58.41, + "curve": [ 0.367, -58.41, 0.4, -2.86 ] + }, + { + "time": 0.4333, + "value": -2.86, + "curve": [ 0.478, -2.86, 0.522, -61.56 ] + }, + { + "time": 0.5667, + "value": -80.05, + "curve": [ 0.6, -93.91, 0.632, -99.87 ] + }, + { "time": 0.6667, "value": -99.91 } + ] + }, + "gun-tip": { + "rotate": [ + { "time": 0.4333, "value": 12.93 } + ] + } + }, + "drawOrder": [ + { + "offsets": [ + { "slot": "head", "offset": -2 } + ] + } + ], + "events": [ + { "time": 0.2667, "name": "footstep" }, + { "time": 0.6, "name": "footstep" } + ] + }, + "shoot": { + "slots": { + "muzzle": { + "rgba": [ + { "time": 0.3667, "color": "ffffff00" } + ], + "attachment": [ + { "time": 0.1333, "name": "muzzle01" }, + { "time": 0.2, "name": "muzzle02" }, + { "time": 0.2667, "name": "muzzle03" }, + { "time": 0.3333, "name": "muzzle04" }, + { "time": 0.3667, "name": null } + ] + } + }, + "bones": { + "gun-tip": { + "translate": [ + { "time": 0.1333 }, + { "time": 0.2333, "x": 32.31, "y": 2.94 } + ] + }, + "gun": { + "rotate": [ + { "value": 1.91, "curve": "stepped" }, + { + "time": 0.1, + "value": 1.91, + "curve": [ 0.113, 4.95, 0.122, 6.56 ] + }, + { + "time": 0.1333, + "value": 6.56, + "curve": [ 0.167, 6.56, 0.2, -0.97 ] + }, + { + "time": 0.2333, + "value": -0.97, + "curve": [ 0.289, -0.97, 0.344, 0.95 ] + }, + { "time": 0.4, "value": 1.91 } + ], + "translate": [ + { "x": 7.95, "y": 5.85, "curve": "stepped" }, + { + "time": 0.1, + "x": 7.95, + "y": 5.85, + "curve": [ 0.167, 7.95, 0.204, -9.3, 0.167, 5.85, 0.204, -1.41 ] + }, + { + "time": 0.3, + "x": -9.3, + "y": -1.41, + "curve": [ 0.333, -9.3, 0.367, 7.95, 0.333, -1.41, 0.367, 5.85 ] + }, + { "time": 0.4, "x": 7.95, "y": 5.85 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": -30.47 } + ], + "translate": [ + { + "time": 0.1, + "curve": [ 0.156, -4.39, 0.204, -6, 0.167, -3.38, 0.204, -3.72 ] + }, + { "time": 0.3, "x": -6, "y": -3.72 }, + { "time": 0.4 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "value": 62.31 } + ], + "translate": [ + { + "time": 0.1, + "curve": [ 0.167, 0, 0.204, 2.81, 0.16, 11.74, 0.23, 11.7 ] + }, + { "time": 0.3, "x": 2.81, "y": 11.53 }, + { "time": 0.4 } + ] + } + } + }, + "walk": { + "bones": { + "hip": { + "rotate": [ + { "value": 0.94 } + ], + "translate": [ + { + "x": -2.86, + "y": -13.86, + "curve": [ 0.025, -2.84, 0.067, -2.82, 0.028, -19.14, 0.054, -31.19 ] + }, + { + "time": 0.1, + "x": -2.61, + "y": -31.36, + "curve": [ 0.143, -2.34, 0.202, -1.79, 0.152, -31.16, 0.213, -14.81 ] + }, + { + "time": 0.2667, + "x": -1.21, + "y": -7.12, + "curve": [ 0.308, -0.86, 0.345, -0.51, 0.306, -1.63, 0.341, 3.15 ] + }, + { + "time": 0.3667, + "x": -0.33, + "y": 3.15, + "curve": [ 0.41, 0.02, 0.458, 0.26, 0.427, 3.3, 0.481, -6.75 ] + }, + { + "time": 0.5, + "x": 0.26, + "y": -10.59, + "curve": [ 0.553, 0.26, 0.559, 0.2, 0.519, -14.41, 0.548, -31.74 ] + }, + { + "time": 0.6, + "x": -0.17, + "y": -31.56, + "curve": [ 0.632, -0.45, 0.683, -0.94, 0.646, -31.41, 0.688, -17.46 ] + }, + { + "time": 0.7333, + "x": -1.4, + "y": -8.62, + "curve": [ 0.783, -1.85, 0.833, -2.28, 0.77, -1.61, 0.831, 3.51 ] + }, + { + "time": 0.8667, + "x": -2.46, + "y": 3.48, + "curve": [ 0.901, -2.63, 0.967, -2.87, 0.913, 3.45, 0.967, -7.64 ] + }, + { "time": 1, "x": -2.86, "y": -13.86 } + ] + }, + "torso": { + "rotate": [ + { + "value": -20.72, + "curve": [ 0.013, -20.49, 0.071, -19.12 ] + }, + { + "time": 0.1333, + "value": -19.12, + "curve": [ 0.187, -19.12, 0.285, -22.22 ] + }, + { + "time": 0.3667, + "value": -22.22, + "curve": [ 0.405, -22.22, 0.491, -20.92 ] + }, + { + "time": 0.5, + "value": -20.71, + "curve": [ 0.51, -20.48, 0.582, -19.06 ] + }, + { + "time": 0.6333, + "value": -19.06, + "curve": [ 0.709, -19.07, 0.815, -22.22 ] + }, + { + "time": 0.8667, + "value": -22.22, + "curve": [ 0.908, -22.22, 0.981, -21.1 ] + }, + { "time": 1, "value": -20.72 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.78, + "curve": [ 0.025, 17.93, 0.071, 18.46 ] + }, + { + "time": 0.1333, + "value": 18.46, + "curve": [ 0.187, 18.46, 0.285, 17.34 ] + }, + { + "time": 0.3667, + "value": 17.34, + "curve": [ 0.405, 17.34, 0.47, 17.6 ] + }, + { + "time": 0.5, + "value": 17.79, + "curve": [ 0.518, 17.9, 0.582, 18.47 ] + }, + { + "time": 0.6333, + "value": 18.46, + "curve": [ 0.709, 18.45, 0.815, 17.32 ] + }, + { + "time": 0.8667, + "value": 17.32, + "curve": [ 0.908, 17.32, 0.971, 17.57 ] + }, + { "time": 1, "value": 17.78 } + ] + }, + "head": { + "rotate": [ + { + "value": -12.23, + "curve": [ 0.061, -12.23, 0.191, -7.45 ] + }, + { + "time": 0.2667, + "value": -7.43, + "curve": [ 0.341, -7.42, 0.421, -12.23 ] + }, + { + "time": 0.5, + "value": -12.23, + "curve": [ 0.567, -12.26, 0.694, -7.46 ] + }, + { + "time": 0.7667, + "value": -7.47, + "curve": [ 0.853, -7.49, 0.943, -12.23 ] + }, + { "time": 1, "value": -12.23 } + ], + "scale": [ + { + "curve": [ 0.039, 1, 0.084, 0.991, 0.039, 1, 0.084, 1.019 ] + }, + { + "time": 0.1333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.205, 0.991, 0.318, 1.019, 0.205, 1.019, 0.337, 0.992 ] + }, + { + "time": 0.4, + "x": 1.019, + "y": 0.992, + "curve": [ 0.456, 1.019, 0.494, 1.001, 0.483, 0.991, 0.493, 0.999 ] + }, + { + "time": 0.5, + "curve": [ 0.508, 0.998, 0.584, 0.991, 0.51, 1.002, 0.584, 1.019 ] + }, + { + "time": 0.6333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.705, 0.991, 0.818, 1.019, 0.705, 1.019, 0.837, 0.992 ] + }, + { + "time": 0.9, + "x": 1.019, + "y": 0.992, + "curve": [ 0.956, 1.019, 0.955, 1, 0.983, 0.991, 0.955, 1 ] + }, + { "time": 1 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 41.41, + "curve": [ 0.033, 41.52, 0.075, 57.36 ] + }, + { + "time": 0.1, + "value": 57.36, + "curve": [ 0.142, 57.36, 0.249, 30.8 ] + }, + { + "time": 0.2667, + "value": 26.81, + "curve": [ 0.314, 16.08, 0.378, 5.4 ] + }, + { + "time": 0.4, + "value": 2.75, + "curve": [ 0.455, -3.75, 0.54, -12.39 ] + }, + { + "time": 0.6, + "value": -12.39, + "curve": [ 0.633, -12.39, 0.722, 21.07 ] + }, + { + "time": 0.7333, + "value": 25.71, + "curve": [ 0.751, 32.81, 0.824, 63.52 ] + }, + { + "time": 0.8667, + "value": 63.79, + "curve": [ 0.913, 64.09, 0.948, 41.49 ] + }, + { "time": 1, "value": 41.41 } + ], + "translate": [ + { + "x": 17.15, + "y": -0.09, + "curve": [ 0.178, 17.14, 0.295, -4.26, 0.009, -0.09, 0.475, 0.02 ] + }, + { + "time": 0.5, + "x": -4.26, + "y": 0.02, + "curve": [ 0.705, -4.27, 0.875, 17.16, 0.525, 0.02, 0.875, -0.09 ] + }, + { "time": 1, "x": 17.15, "y": -0.09 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": -40.72, + "curve": [ 0.026, -42.96, 0.075, -43 ] + }, + { + "time": 0.1, + "value": -43, + "curve": [ 0.142, -43, 0.239, 8.23 ] + }, + { + "time": 0.2667, + "value": 18.99, + "curve": [ 0.284, 25.64, 0.367, 38.72 ] + }, + { + "time": 0.4, + "value": 38.72, + "curve": [ 0.425, 38.72, 0.475, 18.7 ] + }, + { + "time": 0.5, + "value": 18.7, + "curve": [ 0.525, 18.7, 0.575, 31.73 ] + }, + { + "time": 0.6, + "value": 31.73, + "curve": [ 0.633, 31.73, 0.719, 15.2 ] + }, + { + "time": 0.7333, + "value": 11.21, + "curve": [ 0.767, 2.12, 0.851, -15.29 ] + }, + { + "time": 0.8667, + "value": -18.46, + "curve": [ 0.905, -26.32, 0.951, -35.33 ] + }, + { "time": 1, "value": -40.72 } + ], + "translate": [ + { + "x": -17.71, + "y": -4.63, + "curve": [ 0.028, -19.31, 0.04, -20.22, 0.027, -4.63, 0.036, 1.71 ] + }, + { + "time": 0.0667, + "x": -20.72, + "y": 1.6, + "curve": [ 0.082, -21, 0.087, -20.93, 0.082, 1.54, 0.091, 0.29 ] + }, + { + "time": 0.1, + "x": -20.95, + "y": 0.06, + "curve": [ 0.162, -21.05, 0.4, 7.79, 0.194, -2.43, 0.4, -1.9 ] + }, + { + "time": 0.5, + "x": 7.79, + "y": -1.94, + "curve": [ 0.519, 7.78, 0.542, 7.33, 0.517, -1.94, 0.54, 5.55 ] + }, + { + "time": 0.5667, + "x": 6.45, + "y": 5.4, + "curve": [ 0.587, 5.74, 0.721, -0.95, 0.587, 5.28, 0.732, -3.74 ] + }, + { + "time": 0.7667, + "x": -3.61, + "y": -4.14, + "curve": [ 0.855, -8.76, 0.942, -14.37, 0.814, -4.69, 0.944, -4.63 ] + }, + { "time": 1, "x": -17.71, "y": -4.63 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -14.27, + "curve": [ 0.021, -18.08, 0.058, -19.4 ] + }, + { + "time": 0.1, + "value": -19.4, + "curve": [ 0.238, -19.69, 0.337, 7.78 ] + }, + { + "time": 0.3667, + "value": 16.2, + "curve": [ 0.399, 25.42, 0.497, 60.19 ] + }, + { + "time": 0.6, + "value": 60.26, + "curve": [ 0.719, 60.13, 0.845, 27.61 ] + }, + { + "time": 0.8667, + "value": 22.45, + "curve": [ 0.892, 16.38, 0.967, -8.36 ] + }, + { "time": 1, "value": -14.27 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 13.57, + "curve": [ 0.022, 9.71, 0.147, -15.4 ] + }, + { + "time": 0.3667, + "value": -15.3, + "curve": [ 0.457, -15.28, 0.635, 30.8 ] + }, + { + "time": 0.8, + "value": 30.92, + "curve": [ 0.894, 30.82, 0.98, 18.35 ] + }, + { "time": 1, "value": 13.57 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -28.72, + "curve": [ 0.024, -31.74, 0.176, -43.4 ] + }, + { + "time": 0.3667, + "value": -43.6, + "curve": [ 0.403, -43.65, 0.47, -40.15 ] + }, + { + "time": 0.5, + "value": -35.63, + "curve": [ 0.547, -28.59, 0.624, -4.57 ] + }, + { + "time": 0.7333, + "value": -4.59, + "curve": [ 0.891, -4.62, 0.954, -24.28 ] + }, + { "time": 1, "value": -28.48 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.034, 30.94, 0.068, 32.05 ] + }, + { + "time": 0.1, + "value": 31.88, + "curve": [ 0.194, 31.01, 0.336, -0.11 ] + }, + { + "time": 0.3667, + "value": -7.11, + "curve": [ 0.421, -19.73, 0.53, -46.21 ] + }, + { + "time": 0.6, + "value": -45.75, + "curve": [ 0.708, -45.03, 0.844, -13.56 ] + }, + { + "time": 0.8667, + "value": -6.48, + "curve": [ 0.909, 6.59, 0.958, 24.21 ] + }, + { "time": 1, "value": 28.28 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.06, + "curve": [ 0.044, 11.16, 0.063, 11.49 ] + }, + { + "time": 0.1, + "value": 11.49, + "curve": [ 0.215, 11.49, 0.336, 2.92 ] + }, + { + "time": 0.3667, + "value": 0.84, + "curve": [ 0.416, -2.52, 0.498, -10.84 ] + }, + { + "time": 0.6, + "value": -10.83, + "curve": [ 0.762, -10.71, 0.845, -3.05 ] + }, + { + "time": 0.8667, + "value": -1.34, + "curve": [ 0.917, 2.54, 0.977, 8.81 ] + }, + { "time": 1, "value": 10.06 } + ] + }, + "gun": { + "rotate": [ + { + "value": -14.67, + "curve": [ 0.086, -14.67, 0.202, 8.31 ] + }, + { + "time": 0.2333, + "value": 12.14, + "curve": [ 0.279, 17.71, 0.391, 25.79 ] + }, + { + "time": 0.5, + "value": 25.77, + "curve": [ 0.631, 25.74, 0.694, 4.53 ] + }, + { + "time": 0.7333, + "value": -0.65, + "curve": [ 0.768, -5.21, 0.902, -14.4 ] + }, + { "time": 1, "value": -14.67 } + ] + }, + "gun-tip": { + "rotate": [ + { "time": 0.2333, "value": 0.11 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": 26.22 }, + { + "time": 0.0333, + "value": 28.94, + "curve": [ 0.05, 28.94, 0.081, 17.62 ] + }, + { + "time": 0.1, + "value": 12.68, + "curve": [ 0.121, 7.25, 0.239, -22.96 ] + }, + { + "time": 0.2667, + "value": -26.31, + "curve": [ 0.299, -30.12, 0.364, -35.52 ] + }, + { + "time": 0.4, + "value": -35.38, + "curve": [ 0.418, -35.31, 0.485, 1.14 ] + }, + { + "time": 0.5, + "value": 6.17, + "curve": [ 0.503, 7.08, 0.519, 11.27 ] + }, + { + "time": 0.5333, + "value": 11.15, + "curve": [ 0.545, 11.06, 0.552, 11.27 ] + }, + { "time": 0.5667, "value": 3.69 }, + { "time": 0.6, "value": 3.55 }, + { "time": 0.7, "value": 10.77 }, + { "time": 1, "value": 26.22 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -6.79, + "curve": [ 0.028, -6.79, 0.087, -49.32 ] + }, + { + "time": 0.1, + "value": -51.42, + "curve": [ 0.109, -52.92, 0.137, -55.37 ] + }, + { + "time": 0.1667, + "value": -55.35, + "curve": [ 0.188, -55.34, 0.238, -44.96 ] + }, + { + "time": 0.2667, + "value": -40.55, + "curve": [ 0.284, -37.93, 0.365, -23.14 ] + }, + { + "time": 0.4333, + "value": -22.85, + "curve": [ 0.524, -22.46, 0.585, -48.24 ] + }, + { + "time": 0.6, + "value": -54.5, + "curve": [ 0.618, -61.64, 0.714, -97.51 ] + }, + { + "time": 0.7333, + "value": -102.65, + "curve": [ 0.749, -106.84, 0.768, -109.78 ] + }, + { + "time": 0.8, + "value": -109.78, + "curve": [ 0.818, -109.78, 0.859, -94.44 ] + }, + { + "time": 0.8667, + "value": -87.74, + "curve": [ 0.874, -81.52, 0.969, -6.79 ] + }, + { "time": 1, "value": -6.79 } + ], + "scale": [ + {}, + { "time": 0.0333, "x": 0.983 }, + { "time": 0.1, "x": 0.967, "y": 0.981 }, + { "time": 0.4333 }, + { "time": 0.5333, "x": 0.958, "y": 0.951 }, + { "time": 0.6333 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": 6.84, + "curve": [ 0.025, 6.84, 0.093, -24.57 ] + }, + { + "time": 0.1, + "value": -28.08, + "curve": [ 0.121, -38.52, 0.204, -92.35 ] + }, + { + "time": 0.2667, + "value": -91.68, + "curve": [ 0.309, -91.22, 0.379, -77.62 ] + }, + { + "time": 0.4, + "value": -68.91, + "curve": [ 0.43, -56.58, 0.474, 2.28 ] + }, + { + "time": 0.5, + "value": 2.63, + "curve": [ 0.538, 3.15, 0.567, -35.43 ] + }, + { + "time": 0.6, + "value": -35.18, + "curve": [ 0.634, -34.93, 0.665, -34.17 ] + }, + { + "time": 0.7, + "value": -30.64, + "curve": [ 0.718, -28.79, 0.857, -8.34 ] + }, + { + "time": 0.8667, + "value": -6.83, + "curve": [ 0.915, 0.75, 0.967, 6.84 ] + }, + { "time": 1, "value": 6.84 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 2.73, + "curve": [ 0.013, 4.28, 0.019, 5.27 ] + }, + { + "time": 0.0333, + "value": 5.15, + "curve": [ 0.045, 5.05, 0.063, -4.11 ] + }, + { + "time": 0.0667, + "value": -6.67, + "curve": [ 0.111, -6.72, 0.148, 3.78 ] + }, + { "time": 0.1667, "value": 4.67 }, + { "time": 0.2667, "value": 7.06 }, + { "time": 0.3333, "value": 8.97 }, + { "time": 0.4, "value": 11.15 }, + { + "time": 0.5333, + "value": 21.62, + "curve": [ 0.572, 21.62, 0.587, 17.19 ] + }, + { + "time": 0.6, + "value": 13.77, + "curve": [ 0.639, 3.33, 0.713, -20.85 ] + }, + { + "time": 0.7333, + "value": -27.3, + "curve": [ 0.757, -34.54, 0.766, -37.13 ] + }, + { + "time": 0.8, + "value": -38.01, + "curve": [ 0.828, -38.72, 0.976, -2.16 ] + }, + { "time": 1, "value": 2.73 } + ] + } + }, + "events": [ + { "name": "footstep" }, + { "time": 0.5333, "name": "footstep" } + ] + } +} +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-ess.skel b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-ess.skel new file mode 100644 index 0000000..a7df1b2 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-ess.skel differ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-pma.atlas b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-pma.atlas new file mode 100644 index 0000000..9c8bd8e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-pma.atlas @@ -0,0 +1,102 @@ +spineboy-pma.png + size: 1024, 256 + filter: Linear, Linear + pma: true + scale: 0.5 +crosshair + bounds: 813, 160, 45, 45 +eye-indifferent + bounds: 569, 2, 47, 45 +eye-surprised + bounds: 643, 7, 47, 45 + rotate: 90 +front-bracer + bounds: 811, 51, 29, 40 +front-fist-closed + bounds: 807, 93, 38, 41 +front-fist-open + bounds: 815, 210, 43, 44 +front-foot + bounds: 706, 64, 63, 35 + rotate: 90 +front-shin + bounds: 80, 11, 41, 92 +front-thigh + bounds: 754, 12, 23, 56 +front-upper-arm + bounds: 618, 5, 23, 49 +goggles + bounds: 214, 20, 131, 83 +gun + bounds: 347, 14, 105, 102 + rotate: 90 +head + bounds: 80, 105, 136, 149 +hoverboard-board + bounds: 2, 8, 246, 76 + rotate: 90 +hoverboard-thruster + bounds: 478, 2, 30, 32 +hoverglow-small + bounds: 218, 117, 137, 38 + rotate: 90 +mouth-grind + bounds: 775, 80, 47, 30 + rotate: 90 +mouth-oooo + bounds: 779, 31, 47, 30 + rotate: 90 +mouth-smile + bounds: 783, 207, 47, 30 + rotate: 90 +muzzle-glow + bounds: 779, 4, 25, 25 +muzzle-ring + bounds: 451, 14, 25, 105 +muzzle01 + bounds: 664, 60, 67, 40 + rotate: 90 +muzzle02 + bounds: 580, 56, 68, 42 + rotate: 90 +muzzle03 + bounds: 478, 36, 83, 53 + rotate: 90 +muzzle04 + bounds: 533, 49, 75, 45 + rotate: 90 +muzzle05 + bounds: 624, 56, 68, 38 + rotate: 90 +neck + bounds: 806, 8, 18, 21 +portal-bg + bounds: 258, 121, 133, 133 +portal-flare1 + bounds: 690, 2, 56, 30 + rotate: 90 +portal-flare2 + bounds: 510, 3, 57, 31 +portal-flare3 + bounds: 722, 4, 58, 30 + rotate: 90 +portal-shade + bounds: 393, 121, 133, 133 +portal-streaks1 + bounds: 528, 126, 126, 128 +portal-streaks2 + bounds: 656, 129, 125, 125 +rear-bracer + bounds: 826, 13, 28, 36 +rear-foot + bounds: 743, 70, 57, 30 + rotate: 90 +rear-shin + bounds: 174, 14, 38, 89 +rear-thigh + bounds: 783, 158, 28, 47 +rear-upper-arm + bounds: 783, 136, 20, 44 + rotate: 90 +torso + bounds: 123, 13, 49, 90 diff --git a/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-pma.png b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-pma.png new file mode 100644 index 0000000..88efd98 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-pma.png differ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-pro.json b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-pro.json new file mode 100644 index 0000000..4d8c7c2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-pro.json @@ -0,0 +1,8699 @@ +{ +"skeleton": { + "hash": "IQgkYFQG8ng", + "spine": "4.0.31", + "x": -188.63, + "y": -7.94, + "width": 418.45, + "height": 686.2, + "images": "./images/", + "audio": "" +}, +"bones": [ + { "name": "root", "rotation": 0.05 }, + { "name": "hip", "parent": "root", "y": 247.27 }, + { "name": "crosshair", "parent": "root", "x": 302.83, "y": 569.45, "color": "ff3f00ff" }, + { + "name": "aim-constraint-target", + "parent": "hip", + "length": 26.24, + "rotation": 19.61, + "x": 1.02, + "y": 5.62, + "color": "abe323ff" + }, + { "name": "rear-foot-target", "parent": "root", "x": 61.91, "y": 0.42, "color": "ff3f00ff" }, + { "name": "rear-leg-target", "parent": "rear-foot-target", "x": -33.91, "y": 37.34, "color": "ff3f00ff" }, + { + "name": "rear-thigh", + "parent": "hip", + "length": 85.72, + "rotation": -72.54, + "x": 8.91, + "y": -5.63, + "color": "ff000dff" + }, + { + "name": "rear-shin", + "parent": "rear-thigh", + "length": 121.88, + "rotation": -19.83, + "x": 86.1, + "y": -1.33, + "color": "ff000dff" + }, + { + "name": "rear-foot", + "parent": "rear-shin", + "length": 51.58, + "rotation": 45.78, + "x": 121.46, + "y": -0.76, + "color": "ff000dff" + }, + { + "name": "back-foot-tip", + "parent": "rear-foot", + "length": 50.3, + "rotation": -0.85, + "x": 51.17, + "y": 0.24, + "transform": "noRotationOrReflection", + "color": "ff000dff" + }, + { "name": "board-ik", "parent": "root", "x": -131.78, "y": 69.09, "color": "4c56ffff" }, + { "name": "clipping", "parent": "root" }, + { "name": "hoverboard-controller", "parent": "root", "rotation": -0.28, "x": -329.69, "y": 69.82, "color": "ff0004ff" }, + { "name": "exhaust1", "parent": "hoverboard-controller", "rotation": 3.02, "x": -249.68, "y": 53.39 }, + { "name": "exhaust2", "parent": "hoverboard-controller", "rotation": 26.34, "x": -191.6, "y": -22.92 }, + { + "name": "exhaust3", + "parent": "hoverboard-controller", + "rotation": -12.34, + "x": -236.03, + "y": 80.54, + "scaleX": 0.7847, + "scaleY": 0.7847 + }, + { "name": "portal-root", "parent": "root", "x": 12.9, "y": 328.54, "scaleX": 2.0334, "scaleY": 2.0334 }, + { "name": "flare1", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare10", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare2", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare3", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare4", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare5", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare6", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare7", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare8", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare9", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { + "name": "torso", + "parent": "hip", + "length": 42.52, + "rotation": 103.82, + "x": -1.62, + "y": 4.9, + "color": "e0da19ff" + }, + { "name": "torso2", "parent": "torso", "length": 42.52, "x": 42.52, "color": "e0da19ff" }, + { "name": "torso3", "parent": "torso2", "length": 42.52, "x": 42.52, "color": "e0da19ff" }, + { "name": "front-shoulder", "parent": "torso3", "rotation": 255.89, "x": 18.72, "y": 19.33, "color": "00ff04ff" }, + { "name": "front-upper-arm", "parent": "front-shoulder", "length": 69.45, "rotation": -87.51, "color": "00ff04ff" }, + { + "name": "front-bracer", + "parent": "front-upper-arm", + "length": 40.57, + "rotation": 18.3, + "x": 68.8, + "y": -0.68, + "color": "00ff04ff" + }, + { + "name": "front-fist", + "parent": "front-bracer", + "length": 65.39, + "rotation": 12.43, + "x": 40.57, + "y": 0.2, + "color": "00ff04ff" + }, + { "name": "front-foot-target", "parent": "root", "x": -13.53, "y": 0.04, "color": "ff3f00ff" }, + { "name": "front-leg-target", "parent": "front-foot-target", "x": -28.4, "y": 29.06, "color": "ff3f00ff" }, + { + "name": "front-thigh", + "parent": "hip", + "length": 74.81, + "rotation": -95.51, + "x": -17.46, + "y": -11.64, + "color": "00ff04ff" + }, + { + "name": "front-shin", + "parent": "front-thigh", + "length": 128.77, + "rotation": -2.21, + "x": 78.69, + "y": 1.6, + "color": "00ff04ff" + }, + { + "name": "front-foot", + "parent": "front-shin", + "length": 41.01, + "rotation": 51.27, + "x": 128.76, + "y": -0.34, + "color": "00ff04ff" + }, + { + "name": "front-foot-tip", + "parent": "front-foot", + "length": 56.03, + "rotation": -1.68, + "x": 41.42, + "y": -0.09, + "transform": "noRotationOrReflection", + "color": "00ff04ff" + }, + { "name": "back-shoulder", "parent": "torso3", "rotation": -104.11, "x": 7.32, "y": -19.22, "color": "ff000dff" }, + { "name": "rear-upper-arm", "parent": "back-shoulder", "length": 51.94, "rotation": -65.45, "color": "ff000dff" }, + { "name": "rear-bracer", "parent": "rear-upper-arm", "length": 34.56, "rotation": 23.15, "x": 51.36, "color": "ff000dff" }, + { + "name": "gun", + "parent": "rear-bracer", + "length": 43.11, + "rotation": -5.43, + "x": 34.42, + "y": -0.45, + "color": "ff000dff" + }, + { "name": "gun-tip", "parent": "gun", "rotation": 7.1, "x": 200.78, "y": 52.5, "color": "ff0000ff" }, + { + "name": "neck", + "parent": "torso3", + "length": 25.45, + "rotation": -31.54, + "x": 42.46, + "y": -0.31, + "color": "e0da19ff" + }, + { + "name": "head", + "parent": "neck", + "length": 131.79, + "rotation": 26.1, + "x": 27.66, + "y": -0.26, + "color": "e0da19ff" + }, + { + "name": "hair1", + "parent": "head", + "length": 47.23, + "rotation": -49.1, + "x": 149.83, + "y": -59.77, + "color": "e0da19ff" + }, + { + "name": "hair2", + "parent": "hair1", + "length": 55.57, + "rotation": 50.42, + "x": 47.23, + "y": 0.19, + "color": "e0da19ff" + }, + { + "name": "hair3", + "parent": "head", + "length": 62.22, + "rotation": -32.17, + "x": 164.14, + "y": 3.68, + "color": "e0da19ff" + }, + { + "name": "hair4", + "parent": "hair3", + "length": 80.28, + "rotation": 83.71, + "x": 62.22, + "y": -0.04, + "color": "e0da19ff" + }, + { "name": "hoverboard-thruster-front", "parent": "hoverboard-controller", "rotation": -29.2, "x": 95.77, "y": -2.99, "transform": "noRotationOrReflection" }, + { "name": "hoverboard-thruster-rear", "parent": "hoverboard-controller", "rotation": -29.2, "x": -76.47, "y": -4.88, "transform": "noRotationOrReflection" }, + { "name": "hoverglow-front", "parent": "hoverboard-thruster-front", "rotation": 0.17, "x": -1.78, "y": -37.79 }, + { "name": "hoverglow-rear", "parent": "hoverboard-thruster-rear", "rotation": 0.17, "x": 1.06, "y": -35.66 }, + { "name": "muzzle", "parent": "rear-bracer", "rotation": 3.06, "x": 242.34, "y": 34.26, "color": "ffb900ff" }, + { "name": "muzzle-ring", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring2", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring3", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring4", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "portal", "parent": "portal-root" }, + { "name": "portal-shade", "parent": "portal-root" }, + { "name": "portal-streaks1", "parent": "portal-root" }, + { "name": "portal-streaks2", "parent": "portal-root" }, + { "name": "side-glow1", "parent": "hoverboard-controller", "x": -110.56, "y": 2.62, "color": "000effff" }, + { + "name": "side-glow2", + "parent": "hoverboard-controller", + "x": -110.56, + "y": 2.62, + "scaleX": 0.738, + "scaleY": 0.738, + "color": "000effff" + }, + { "name": "head-control", "parent": "head", "x": 110.21, "color": "00a220ff" } +], +"slots": [ + { "name": "portal-bg", "bone": "portal" }, + { "name": "portal-shade", "bone": "portal-shade" }, + { "name": "portal-streaks2", "bone": "portal-streaks2", "blend": "additive" }, + { "name": "portal-streaks1", "bone": "portal-streaks1", "blend": "additive" }, + { "name": "portal-flare8", "bone": "flare8", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare9", "bone": "flare9", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare10", "bone": "flare10", "color": "c3cbffff", "blend": "additive" }, + { "name": "clipping", "bone": "clipping" }, + { "name": "exhaust3", "bone": "exhaust3", "color": "5eb4ffff", "blend": "additive" }, + { "name": "hoverboard-thruster-rear", "bone": "hoverboard-thruster-rear" }, + { "name": "hoverboard-thruster-front", "bone": "hoverboard-thruster-front" }, + { "name": "hoverboard-board", "bone": "hoverboard-controller" }, + { "name": "side-glow1", "bone": "side-glow1", "color": "ff8686ff", "blend": "additive" }, + { "name": "side-glow3", "bone": "side-glow1", "color": "ff8686ff", "blend": "additive" }, + { "name": "side-glow2", "bone": "side-glow2", "color": "ff8686ff", "blend": "additive" }, + { "name": "hoverglow-front", "bone": "hoverglow-front", "color": "5eb4ffff", "blend": "additive" }, + { "name": "hoverglow-rear", "bone": "hoverglow-rear", "color": "5eb4ffff", "blend": "additive" }, + { "name": "exhaust1", "bone": "exhaust2", "color": "5eb4ffff", "blend": "additive" }, + { "name": "exhaust2", "bone": "exhaust1", "color": "5eb4ffff", "blend": "additive" }, + { "name": "rear-upper-arm", "bone": "rear-upper-arm", "attachment": "rear-upper-arm" }, + { "name": "rear-bracer", "bone": "rear-bracer", "attachment": "rear-bracer" }, + { "name": "gun", "bone": "gun", "attachment": "gun" }, + { "name": "rear-foot", "bone": "rear-foot", "attachment": "rear-foot" }, + { "name": "rear-thigh", "bone": "rear-thigh", "attachment": "rear-thigh" }, + { "name": "rear-shin", "bone": "rear-shin", "attachment": "rear-shin" }, + { "name": "neck", "bone": "neck", "attachment": "neck" }, + { "name": "torso", "bone": "torso", "attachment": "torso" }, + { "name": "front-upper-arm", "bone": "front-upper-arm", "attachment": "front-upper-arm" }, + { "name": "head", "bone": "head", "attachment": "head" }, + { "name": "eye", "bone": "head", "attachment": "eye-indifferent" }, + { "name": "front-thigh", "bone": "front-thigh", "attachment": "front-thigh" }, + { "name": "front-foot", "bone": "front-foot", "attachment": "front-foot" }, + { "name": "front-shin", "bone": "front-shin", "attachment": "front-shin" }, + { "name": "mouth", "bone": "head", "attachment": "mouth-smile" }, + { "name": "goggles", "bone": "head", "attachment": "goggles" }, + { "name": "front-bracer", "bone": "front-bracer", "attachment": "front-bracer" }, + { "name": "front-fist", "bone": "front-fist", "attachment": "front-fist-closed" }, + { "name": "muzzle", "bone": "muzzle" }, + { "name": "head-bb", "bone": "head" }, + { "name": "portal-flare1", "bone": "flare1", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare2", "bone": "flare2", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare3", "bone": "flare3", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare4", "bone": "flare4", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare5", "bone": "flare5", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare6", "bone": "flare6", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare7", "bone": "flare7", "color": "c3cbffff", "blend": "additive" }, + { "name": "crosshair", "bone": "crosshair" }, + { "name": "muzzle-glow", "bone": "gun-tip", "color": "ffffff00", "blend": "additive" }, + { "name": "muzzle-ring", "bone": "muzzle-ring", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring2", "bone": "muzzle-ring2", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring3", "bone": "muzzle-ring3", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring4", "bone": "muzzle-ring4", "color": "d8baffff", "blend": "additive" } +], +"ik": [ + { + "name": "aim-ik", + "order": 13, + "bones": [ "rear-upper-arm" ], + "target": "crosshair", + "mix": 0 + }, + { + "name": "aim-torso-ik", + "order": 8, + "bones": [ "aim-constraint-target" ], + "target": "crosshair" + }, + { + "name": "board-ik", + "order": 1, + "bones": [ "hoverboard-controller" ], + "target": "board-ik" + }, + { + "name": "front-foot-ik", + "order": 6, + "bones": [ "front-foot" ], + "target": "front-foot-target" + }, + { + "name": "front-leg-ik", + "order": 4, + "bones": [ "front-thigh", "front-shin" ], + "target": "front-leg-target", + "bendPositive": false + }, + { + "name": "rear-foot-ik", + "order": 7, + "bones": [ "rear-foot" ], + "target": "rear-foot-target" + }, + { + "name": "rear-leg-ik", + "order": 5, + "bones": [ "rear-thigh", "rear-shin" ], + "target": "rear-leg-target", + "bendPositive": false + } +], +"transform": [ + { + "name": "aim-front-arm-transform", + "order": 11, + "bones": [ "front-upper-arm" ], + "target": "aim-constraint-target", + "rotation": -180, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "aim-head-transform", + "order": 10, + "bones": [ "head" ], + "target": "aim-constraint-target", + "rotation": 84.3, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "aim-rear-arm-transform", + "order": 12, + "bones": [ "rear-upper-arm" ], + "target": "aim-constraint-target", + "x": 57.7, + "y": 56.4, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "aim-torso-transform", + "order": 9, + "bones": [ "torso" ], + "target": "aim-constraint-target", + "rotation": 69.5, + "shearY": -36, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "front-foot-board-transform", + "order": 2, + "bones": [ "front-foot-target" ], + "target": "hoverboard-controller", + "x": -69.8, + "y": 20.7, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "rear-foot-board-transform", + "order": 3, + "bones": [ "rear-foot-target" ], + "target": "hoverboard-controller", + "x": 86.6, + "y": 21.3, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "shoulder", + "bones": [ "back-shoulder" ], + "target": "front-shoulder", + "x": 40.17, + "y": -1.66, + "mixRotate": 0, + "mixX": -1, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "toes-board", + "order": 14, + "bones": [ "front-foot-tip", "back-foot-tip" ], + "target": "hoverboard-controller", + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + } +], +"skins": [ + { + "name": "default", + "attachments": { + "clipping": { + "clipping": { + "type": "clipping", + "end": "head-bb", + "vertexCount": 9, + "vertices": [ 66.76, 509.48, 19.98, 434.54, 5.34, 336.28, 22.19, 247.93, 77.98, 159.54, 182.21, -97.56, 1452.26, -99.8, 1454.33, 843.61, 166.57, 841.02 ], + "color": "ce3a3aff" + } + }, + "crosshair": { + "crosshair": { "width": 89, "height": 89 } + }, + "exhaust1": { + "hoverglow-small": { "scaleX": 0.4629, "scaleY": 0.8129, "rotation": -83.07, "width": 274, "height": 75 } + }, + "exhaust2": { + "hoverglow-small": { + "x": 0.01, + "y": -0.76, + "scaleX": 0.4208, + "scaleY": 0.8403, + "rotation": -89.25, + "width": 274, + "height": 75 + } + }, + "exhaust3": { + "hoverglow-small": { "scaleX": 0.4629, "scaleY": 0.8129, "rotation": -83.07, "width": 274, "height": 75 } + }, + "eye": { + "eye-indifferent": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 66, -36.8, -91.35, 0.3, 46, 73.41, -91.35, 0.7, 2, 66, -87.05, -13.11, 0.70968, 46, 23.16, -13.11, 0.29032, 2, 66, -12.18, 34.99, 0.82818, 46, 98.03, 34.99, 0.17182, 2, 66, 38.07, -43.25, 0.59781, 46, 148.28, -43.25, 0.40219 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 89 + }, + "eye-surprised": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 2, 66, -46.74, -89.7, 0.3, 46, 63.47, -89.7, 0.7, 2, 66, -77.58, -1.97, 0.71, 46, 32.63, -1.97, 0.29, 2, 66, 6.38, 27.55, 0.83, 46, 116.59, 27.55, 0.17, 2, 66, 37.22, -60.19, 0.6, 46, 147.44, -60.19, 0.4 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 89 + } + }, + "front-bracer": { + "front-bracer": { "x": 12.03, "y": -1.68, "rotation": 79.6, "width": 58, "height": 80 } + }, + "front-fist": { + "front-fist-closed": { "x": 35.5, "y": 6, "rotation": 67.16, "width": 75, "height": 82 }, + "front-fist-open": { "x": 39.57, "y": 7.76, "rotation": 67.16, "width": 86, "height": 87 } + }, + "front-foot": { + "front-foot": { + "type": "mesh", + "uvs": [ 0.59417, 0.23422, 0.62257, 0.30336, 0.6501, 0.37036, 0.67637, 0.38404, 0.72068, 0.4071, 0.76264, 0.42894, 1, 0.70375, 1, 1, 0.65517, 1, 0.46923, 0.99999, 0, 1, 0, 0.39197, 0.17846, 0, 0.49796, 0 ], + "triangles": [ 8, 9, 3, 4, 8, 3, 5, 8, 4, 6, 8, 5, 8, 6, 7, 11, 1, 10, 0, 12, 13, 0, 11, 12, 0, 1, 11, 9, 2, 3, 1, 2, 10, 9, 10, 2 ], + "vertices": [ 2, 38, 18.17, 41.57, 0.7896, 39, 12.46, 46.05, 0.2104, 2, 38, 24.08, 40.76, 0.71228, 39, 16.12, 41.34, 0.28772, 2, 38, 29.81, 39.98, 0.55344, 39, 19.67, 36.78, 0.44656, 2, 38, 32.81, 41.67, 0.38554, 39, 23, 35.89, 0.61446, 2, 38, 37.86, 44.52, 0.25567, 39, 28.61, 34.4, 0.74433, 2, 38, 42.65, 47.22, 0.17384, 39, 33.92, 32.99, 0.82616, 1, 39, 64.15, 14.56, 1, 1, 39, 64.51, -5.87, 1, 1, 39, 21.08, -6.64, 1, 2, 38, 44.67, -6.77, 0.5684, 39, -2.34, -6.97, 0.4316, 1, 38, 3.1, -48.81, 1, 1, 38, -26.73, -19.31, 1, 1, 38, -30.15, 15.69, 1, 1, 38, -1.84, 44.32, 1 ], + "hull": 14, + "edges": [ 14, 16, 16, 18, 18, 20, 4, 18, 20, 22, 24, 26, 22, 24, 12, 14, 10, 12, 2, 4, 2, 20, 4, 6, 6, 16, 2, 0, 0, 26, 6, 8, 8, 10 ], + "width": 126, + "height": 69 + } + }, + "front-shin": { + "front-shin": { + "type": "mesh", + "uvs": [ 0.90031, 0.05785, 1, 0.12828, 1, 0.21619, 0.9025, 0.31002, 0.78736, 0.35684, 0.78081, 0.39874, 0.77215, 0.45415, 0.77098, 0.51572, 0.84094, 0.63751, 0.93095, 0.7491, 0.95531, 0.7793, 0.78126, 0.87679, 0.5613, 1, 0.2687, 1, 0, 1, 0.00279, 0.96112, 0.01358, 0.81038, 0.02822, 0.60605, 0.08324, 0.45142, 0.18908, 0.31882, 0.29577, 0.2398, 0.30236, 0.14941, 0.37875, 0.05902, 0.53284, 0, 0.70538, 0, 0.41094, 0.71968, 0.40743, 0.54751, 0.41094, 0.4536, 0.4724, 0.35186, 0.33367, 0.27829, 0.50226, 0.31664, 0.65328, 0.67507, 0.60762, 0.52716, 0.6006, 0.45125, 0.62747, 0.37543, 0.6573, 0.3385, 0.27843, 0.32924, 0.18967, 0.45203, 0.16509, 0.58586, 0.18265, 0.7682, 0.50532, 0.24634, 0.59473, 0.17967, 0.60161, 0.10611, 0.51392, 0.04327, 0.72198, 0.28849, 0.82343, 0.20266, 0.86814, 0.11377, 0.79592, 0.04634, 0.44858, 0.15515, 0.25466, 0.96219, 0.53169, 0.9448, 0.7531, 0.8324 ], + "triangles": [ 24, 0, 47, 43, 23, 24, 47, 43, 24, 43, 22, 23, 42, 43, 47, 46, 47, 0, 42, 47, 46, 46, 0, 1, 48, 22, 43, 48, 43, 42, 21, 22, 48, 41, 48, 42, 45, 42, 46, 41, 42, 45, 46, 1, 2, 45, 46, 2, 40, 48, 41, 48, 20, 21, 29, 48, 40, 29, 20, 48, 44, 41, 45, 40, 41, 44, 3, 45, 2, 44, 45, 3, 30, 29, 40, 35, 30, 40, 36, 19, 20, 36, 20, 29, 44, 35, 40, 28, 29, 30, 4, 44, 3, 35, 44, 4, 34, 30, 35, 5, 35, 4, 34, 28, 30, 33, 28, 34, 37, 19, 36, 18, 19, 37, 27, 29, 28, 27, 28, 33, 36, 29, 27, 37, 36, 27, 5, 34, 35, 6, 34, 5, 33, 34, 6, 6, 32, 33, 7, 32, 6, 26, 37, 27, 38, 18, 37, 38, 37, 26, 17, 18, 38, 31, 32, 7, 31, 7, 8, 32, 25, 26, 38, 26, 25, 27, 33, 32, 32, 26, 27, 39, 38, 25, 17, 38, 39, 16, 17, 39, 51, 31, 8, 51, 8, 9, 11, 51, 9, 11, 9, 10, 31, 50, 25, 31, 25, 32, 50, 31, 51, 49, 39, 25, 49, 25, 50, 15, 16, 39, 49, 15, 39, 13, 49, 50, 14, 15, 49, 13, 14, 49, 12, 50, 51, 12, 51, 11, 13, 50, 12 ], + "vertices": [ -23.66, 19.37, -11.73, 28.98, 4.34, 30.83, 22.41, 24.87, 32.05, 16.48, 39.77, 16.83, 49.98, 17.3, 61.25, 18.5, 82.85, 26.78, 102.4, 36.46, 107.69, 39.09, 127.15, 26.97, 151.74, 11.65, 154.49, -12.18, 157.02, -34.07, 149.89, -34.66, 122.23, -36.97, 84.75, -40.09, 55.97, -38.88, 30.73, -33.05, 15.29, -26.03, -1.3, -27.41, -18.54, -23.09, -30.78, -11.79, -32.4, 2.27, 101.92, -6.52, 70.48, -10.44, 53.28, -12.14, 34.11, -9.28, 21.96, -22.13, 27.39, -7.59, 91.48, 12.28, 64.88, 5.44, 51.07, 3.26, 36.95, 3.85, 29.92, 5.5, 31.8, -25.56, 55.08, -30.19, 79.77, -29.37, 112.93, -24.09, 14.51, -8.83, 1.48, -2.95, -12.03, -3.94, -22.69, -12.41, 20.17, 9.71, 3.53, 16.16, -13.14, 17.93, -24.78, 10.62, -1.62, -15.37, 147.71, -14.13, 141.93, 8.07, 119.3, 23.74 ], + "hull": 25, + "edges": [ 8, 6, 6, 4, 4, 2, 2, 0, 0, 48, 46, 48, 46, 44, 44, 42, 42, 40, 40, 38, 38, 36, 36, 34, 32, 34, 50, 52, 52, 54, 54, 56, 40, 58, 58, 60, 8, 10, 20, 22, 22, 24, 62, 64, 64, 66, 66, 68, 8, 70, 70, 60, 68, 70, 58, 72, 72, 74, 74, 76, 76, 78, 24, 26, 26, 28, 58, 80, 80, 82, 82, 84, 84, 86, 86, 44, 70, 88, 88, 90, 90, 92, 92, 94, 94, 48, 80, 88, 88, 6, 82, 90, 90, 4, 84, 92, 92, 2, 86, 94, 94, 0, 56, 60, 10, 12, 12, 14, 14, 16, 28, 30, 30, 32, 26, 98, 98, 78, 30, 98, 24, 100, 100, 50, 98, 100, 22, 102, 102, 62, 100, 102, 16, 18, 18, 20, 102, 18 ], + "width": 82, + "height": 184 + } + }, + "front-thigh": { + "front-thigh": { "x": 42.48, "y": 4.45, "rotation": 84.87, "width": 45, "height": 112 } + }, + "front-upper-arm": { + "front-upper-arm": { "x": 28.31, "y": 7.37, "rotation": 97.9, "width": 46, "height": 97 } + }, + "goggles": { + "goggles": { + "type": "mesh", + "uvs": [ 0.53653, 0.04114, 0.72922, 0.16036, 0.91667, 0.33223, 0.97046, 0.31329, 1, 0.48053, 0.95756, 0.5733, 0.88825, 0.6328, 0.86878, 0.78962, 0.77404, 0.8675, 0.72628, 1, 0.60714, 0.93863, 0.49601, 0.88138, 0.41558, 0.75027, 0.32547, 0.70084, 0.2782, 0.58257, 0.1721, 0.63281, 0.17229, 0.75071, 0.10781, 0.79898, 0, 0.32304, 0, 0.12476, 0.07373, 0.07344, 0.15423, 0.10734, 0.23165, 0.13994, 0.30313, 0.02256, 0.34802, 0, 0.42979, 0.69183, 0.39476, 0.51042, 0.39488, 0.31512, 0.45878, 0.23198, 0.56501, 0.28109, 0.69961, 0.39216, 0.82039, 0.54204, 0.85738, 0.62343, 0.91107, 0.51407, 0.72639, 0.32147, 0.58764, 0.19609, 0.48075, 0.11269, 0.37823, 0.05501, 0.3287, 0.17866, 0.319, 0.305, 0.36036, 0.53799, 0.40327, 0.70072, 0.30059, 0.55838, 0.21957, 0.2815, 0.09963, 0.28943, 0.56863, 0.4368, 0.4911, 0.37156, 0.51185, 0.52093, 0.67018, 0.59304, 0.7619, 0.68575, 0.73296, 0.43355 ], + "triangles": [ 18, 44, 15, 21, 19, 20, 17, 18, 15, 44, 19, 21, 2, 3, 4, 18, 19, 44, 2, 33, 34, 33, 2, 4, 5, 33, 4, 5, 6, 33, 7, 32, 6, 31, 50, 33, 32, 31, 33, 6, 32, 33, 31, 49, 50, 49, 31, 32, 49, 32, 7, 8, 49, 7, 33, 50, 34, 17, 15, 16, 9, 48, 8, 49, 48, 50, 50, 48, 45, 47, 45, 48, 50, 45, 30, 45, 47, 46, 45, 46, 29, 30, 45, 29, 30, 29, 34, 30, 34, 50, 47, 26, 46, 25, 10, 11, 12, 25, 11, 41, 12, 42, 42, 44, 43, 43, 21, 22, 41, 40, 25, 41, 42, 40, 29, 35, 34, 40, 26, 25, 25, 26, 47, 37, 24, 0, 36, 37, 0, 42, 43, 39, 42, 39, 40, 28, 38, 36, 40, 39, 26, 28, 27, 38, 26, 39, 27, 37, 38, 23, 39, 43, 38, 38, 37, 36, 27, 39, 38, 43, 22, 38, 37, 23, 24, 22, 23, 38, 36, 0, 35, 28, 36, 35, 29, 28, 35, 27, 28, 46, 26, 27, 46, 35, 0, 1, 34, 35, 1, 12, 41, 25, 47, 10, 25, 44, 21, 43, 42, 14, 44, 14, 15, 44, 13, 14, 42, 12, 13, 42, 46, 28, 29, 47, 48, 10, 48, 9, 10, 49, 8, 48, 2, 34, 1 ], + "vertices": [ 2, 66, 61.88, 22.81, 0.832, 46, 172.09, 22.81, 0.168, 2, 66, 59.89, -31.19, 0.6855, 46, 170.1, -31.19, 0.3145, 2, 66, 49.2, -86.8, 0.32635, 46, 159.41, -86.8, 0.67365, 2, 66, 56.82, -99.01, 0.01217, 46, 167.03, -99.01, 0.98783, 1, 46, 143.4, -115.48, 1, 2, 66, 15, -110.14, 0.0041, 46, 125.21, -110.14, 0.9959, 2, 66, -0.32, -96.36, 0.07948, 46, 109.89, -96.36, 0.92052, 2, 66, -26.56, -100.19, 0.01905, 46, 83.65, -100.19, 0.98095, 2, 66, -46.96, -81.16, 0.4921, 46, 63.26, -81.16, 0.50791, 2, 66, -71.84, -76.69, 0.56923, 46, 38.37, -76.69, 0.43077, 2, 66, -72.54, -43.98, 0.74145, 46, 37.67, -43.98, 0.25855, 2, 66, -73.2, -13.47, 0.87929, 46, 37.01, -13.47, 0.12071, 2, 66, -59.63, 13.55, 0.864, 46, 50.58, 13.55, 0.136, 2, 66, -59.69, 38.45, 0.85289, 46, 50.52, 38.45, 0.14711, 2, 66, -45.26, 56.6, 0.74392, 46, 64.95, 56.6, 0.25608, 2, 66, -62.31, 79.96, 0.624, 46, 47.9, 79.96, 0.376, 2, 66, -80.76, 73.42, 0.616, 46, 29.45, 73.42, 0.384, 2, 66, -93.9, 86.64, 0.288, 46, 16.31, 86.64, 0.712, 1, 46, 81.51, 139.38, 1, 1, 46, 112.56, 150.3, 1, 2, 66, 16.76, 134.97, 0.02942, 46, 126.97, 134.97, 0.97058, 2, 66, 18.42, 113.28, 0.36147, 46, 128.63, 113.28, 0.63853, 2, 66, 20.02, 92.43, 0.7135, 46, 130.23, 92.43, 0.2865, 2, 66, 44.58, 81.29, 0.69603, 46, 154.79, 81.29, 0.30397, 2, 66, 52, 71.48, 0.848, 46, 162.21, 71.48, 0.152, 2, 66, -49.25, 13.27, 0.8, 46, 60.96, 13.27, 0.2, 2, 66, -23.88, 31.88, 0.896, 46, 86.33, 31.88, 0.104, 2, 66, 6.72, 42.6, 0.928, 46, 116.93, 42.6, 0.072, 2, 66, 25.26, 31.44, 0.8, 46, 135.47, 31.44, 0.2, 2, 66, 26.77, 2.59, 0.75, 46, 136.98, 2.59, 0.25, 2, 66, 21.02, -36.66, 0.54887, 46, 131.23, -36.66, 0.45113, 2, 66, 8.01, -74.65, 0.36029, 46, 118.22, -74.65, 0.63971, 2, 66, -1.52, -88.24, 0.1253, 46, 108.69, -88.24, 0.8747, 2, 66, 20.25, -95.44, 0.08687, 46, 130.46, -95.44, 0.91313, 2, 66, 34.42, -39.36, 0.72613, 46, 144.63, -39.36, 0.27387, 2, 66, 42.03, 1.7, 0.824, 46, 152.25, 1.7, 0.176, 2, 66, 45.85, 32.6, 0.856, 46, 156.06, 32.6, 0.144, 1, 66, 46.01, 61.02, 1, 1, 66, 22.35, 66.41, 1, 1, 66, 1.73, 61.84, 1, 2, 66, -31.17, 38.83, 0.928, 46, 79.04, 38.83, 0.072, 2, 66, -52.94, 19.31, 0.79073, 46, 57.27, 19.31, 0.20927, 2, 66, -39.54, 52.42, 0.912, 46, 70.67, 52.42, 0.088, 2, 66, -3.2, 87.61, 0.744, 46, 107.02, 87.61, 0.256, 2, 66, -14.82, 116.7, 0.6368, 46, 95.4, 116.7, 0.3632, 2, 66, 2.7, -6.87, 0.856, 46, 112.91, -6.87, 0.144, 2, 66, 6.21, 15.8, 0.744, 46, 116.42, 15.8, 0.256, 2, 66, -15.39, 2.47, 0.856, 46, 94.82, 2.47, 0.144, 2, 66, -12.98, -40.48, 0.72102, 46, 97.24, -40.48, 0.27898, 2, 66, -19.55, -68.16, 0.59162, 46, 90.66, -68.16, 0.40838, 2, 66, 17.44, -47.15, 0.53452, 46, 127.65, -47.15, 0.46548 ], + "hull": 25, + "edges": [ 36, 34, 34, 32, 32, 30, 30, 28, 28, 26, 26, 24, 24, 22, 18, 16, 16, 14, 14, 12, 12, 10, 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 48, 48, 46, 46, 44, 36, 38, 40, 38, 24, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 62, 64, 64, 12, 8, 66, 66, 68, 68, 70, 70, 72, 72, 74, 74, 76, 76, 78, 78, 80, 80, 82, 82, 24, 24, 84, 84, 86, 86, 44, 40, 42, 42, 44, 42, 88, 88, 30, 58, 90, 90, 92, 92, 94, 18, 20, 20, 22, 94, 20, 18, 96, 96, 98, 60, 100, 100, 62, 98, 100 ], + "width": 261, + "height": 166 + } + }, + "gun": { + "gun": { "x": 77.3, "y": 16.4, "rotation": 60.83, "width": 210, "height": 203 } + }, + "head": { + "head": { + "type": "mesh", + "uvs": [ 0.75919, 0.06107, 0.88392, 0.17893, 0.90174, 0.30856, 0.94224, 0.1966, 1, 0.26584, 1, 0.422, 0.95864, 0.46993, 0.92118, 0.51333, 0.85957, 0.5347, 0.78388, 0.65605, 0.74384, 0.74838, 0.85116, 0.75151, 0.84828, 0.82564, 0.81781, 0.85367, 0.75599, 0.85906, 0.76237, 0.90468, 0.65875, 1, 0.38337, 1, 0.1858, 0.85404, 0.12742, 0.81091, 0.06025, 0.69209, 0, 0.58552, 0, 0.41021, 0.0853, 0.20692, 0.24243, 0.14504, 0.5, 0.1421, 0.50324, 0.07433, 0.41738, 0, 0.57614, 0, 0.85059, 0.36087, 0.73431, 0.43206, 0.68481, 0.31271, 0.72165, 0.16718, 0.55931, 0.04154, 0.44764, 0.22895, 0.23926, 0.26559, 0.71272, 0.44036, 0.56993, 0.383, 0.41678, 0.33511, 0.293, 0.31497, 0.70802, 0.44502, 0.56676, 0.38976, 0.41521, 0.34416, 0.28754, 0.33017, 0.88988, 0.50177, 0.30389, 0.73463, 0.2646, 0.65675, 0.21414, 0.61584, 0.14613, 0.62194, 0.10316, 0.66636, 0.10358, 0.72557, 0.14505, 0.79164, 0.20263, 0.81355, 0.27873, 0.80159, 0.34947, 0.7376, 0.23073, 0.57073, 0.08878, 0.60707, 0.29461, 0.8129, 0.73006, 0.87883, 0.69805, 0.87348, 0.66166, 0.79681, 0.22468, 0.69824, 0.14552, 0.67405 ], + "triangles": [ 50, 49, 62, 34, 25, 31, 39, 35, 34, 38, 39, 34, 37, 38, 34, 42, 39, 38, 43, 39, 42, 32, 2, 31, 31, 37, 34, 42, 38, 37, 41, 42, 37, 43, 22, 39, 30, 31, 29, 36, 37, 31, 30, 36, 31, 40, 41, 37, 36, 40, 37, 36, 30, 44, 55, 22, 43, 55, 48, 56, 47, 48, 55, 46, 55, 54, 42, 55, 43, 47, 55, 46, 62, 49, 48, 61, 47, 46, 62, 48, 47, 61, 62, 47, 46, 54, 45, 42, 41, 55, 61, 46, 45, 55, 41, 54, 61, 51, 50, 61, 50, 62, 60, 41, 40, 54, 41, 60, 53, 61, 45, 52, 51, 61, 57, 53, 45, 57, 45, 54, 53, 52, 61, 52, 19, 51, 57, 18, 52, 57, 52, 53, 17, 54, 60, 57, 54, 17, 18, 57, 17, 19, 50, 51, 33, 27, 28, 26, 27, 33, 0, 33, 28, 32, 33, 0, 32, 0, 1, 33, 25, 26, 33, 32, 25, 31, 25, 32, 2, 32, 1, 2, 3, 4, 29, 31, 2, 2, 4, 5, 29, 2, 5, 6, 29, 5, 30, 29, 6, 44, 30, 6, 18, 19, 52, 49, 56, 48, 34, 24, 25, 35, 23, 24, 35, 24, 34, 39, 22, 35, 22, 23, 35, 7, 44, 6, 8, 36, 44, 40, 36, 8, 8, 44, 7, 56, 21, 22, 55, 56, 22, 9, 40, 8, 20, 21, 56, 20, 56, 49, 9, 60, 40, 10, 60, 9, 20, 50, 19, 12, 10, 11, 13, 10, 12, 14, 60, 10, 13, 14, 10, 59, 60, 14, 58, 59, 14, 58, 14, 15, 16, 17, 60, 59, 16, 60, 15, 16, 59, 15, 59, 58, 20, 49, 50 ], + "vertices": [ 2, 50, 41.97, -41.8, 0.94074, 66, 165.41, -22.6, 0.05926, 4, 48, 73.47, 27.54, 0.26795, 50, -5.75, -51.71, 0.4738, 49, 112.99, -11.41, 0.12255, 66, 143.5, -66.13, 0.1357, 4, 48, 38.23, 10.99, 0.6831, 50, -41.01, -35.22, 0.07866, 49, 92.73, -44.66, 0.04872, 66, 108.65, -83.49, 0.18952, 2, 48, 73.35, 10.89, 0.8455, 66, 143.77, -82.78, 0.1545, 2, 48, 58.59, -10.38, 0.91607, 66, 129.5, -104.39, 0.08393, 3, 46, 195.82, -119.82, 0.104, 47, 75.49, -4.55, 0.09191, 48, 14.36, -24.8, 0.80409, 4, 46, 178.62, -113.98, 0.19022, 47, 59.82, -13.72, 0.33409, 48, -2.7, -18.57, 0.46643, 66, 68.41, -113.98, 0.00926, 4, 46, 163.06, -108.69, 0.18724, 47, 45.64, -22.03, 0.3133, 48, -18.14, -12.93, 0.47469, 66, 52.84, -108.69, 0.02477, 2, 46, 151.52, -95.05, 0.91122, 66, 41.31, -95.05, 0.08878, 2, 46, 110.61, -87.69, 0.70564, 66, 0.4, -87.69, 0.29436, 2, 46, 81.05, -86.58, 0.63951, 66, -29.16, -86.58, 0.36049, 2, 46, 89.82, -114.32, 0.57, 66, -20.39, -114.32, 0.43, 2, 46, 68.72, -120.91, 0.57, 66, -41.49, -120.91, 0.43, 2, 46, 58.1, -115.9, 0.57, 66, -52.11, -115.9, 0.43, 2, 46, 51.03, -100.63, 0.64242, 66, -59.18, -100.63, 0.35758, 2, 46, 38.79, -106.76, 0.81659, 66, -71.43, -106.76, 0.18341, 2, 46, 2.68, -89.7, 0.77801, 66, -107.53, -89.7, 0.22199, 2, 46, -22.07, -19.3, 0.823, 66, -132.28, -19.3, 0.177, 2, 46, 1.2, 45.63, 0.51204, 66, -109.01, 45.63, 0.48796, 2, 46, 8.07, 64.81, 0.60869, 66, -102.14, 64.81, 0.39131, 2, 46, 35.44, 93.73, 0.80009, 66, -74.77, 93.73, 0.19991, 2, 46, 59.98, 119.66, 0.93554, 66, -50.23, 119.66, 0.06446, 2, 46, 109.26, 136.99, 0.99895, 66, -0.95, 136.99, 0.00105, 1, 46, 174.07, 135.27, 1, 3, 46, 205.59, 101.22, 0.80778, 49, -16.84, 104.63, 0.15658, 66, 95.38, 101.22, 0.03564, 3, 50, 58.94, 30.5, 0.43491, 49, 38.36, 61.89, 0.28116, 66, 119.35, 35.65, 0.28393, 2, 50, 75.56, 19.01, 0.92164, 66, 138.68, 41.52, 0.07836, 1, 50, 106.7, 26.9, 1, 1, 50, 83.79, -9.51, 1, 5, 47, 44.51, 27.24, 0.15139, 48, 19.12, 19.33, 0.44847, 50, -46.82, -15.19, 0.05757, 49, 72.19, -48.24, 0.1149, 66, 89.35, -75.58, 0.22767, 3, 47, 7.42, 19.08, 0.37772, 49, 34.32, -45.24, 0.09918, 66, 58.9, -52.89, 0.52311, 2, 49, 45.94, -9.07, 0.4826, 66, 87.99, -28.45, 0.5174, 2, 50, 20.62, -16.35, 0.7435, 66, 132.21, -23.49, 0.2565, 2, 50, 75.74, 0.94, 0.97172, 66, 152.95, 30.42, 0.02828, 4, 46, 200.45, 40.46, 0.18809, 50, 44.6, 56.29, 0.05831, 49, 11.15, 50.46, 0.14366, 66, 90.24, 40.46, 0.60994, 2, 46, 171.41, 90.12, 0.48644, 66, 61.2, 90.12, 0.51356, 2, 46, 164.84, -48.18, 0.43217, 66, 54.62, -48.18, 0.56783, 4, 46, 168.13, -6.02, 0.01949, 47, -28.65, 49.02, 0.02229, 49, 8.54, -6.09, 0.12791, 66, 57.92, -6.02, 0.83031, 2, 46, 167.84, 37.87, 0.15, 66, 57.63, 37.87, 0.85, 2, 46, 162.36, 71.5, 0.24107, 66, 52.15, 71.5, 0.75893, 2, 46, 163.11, -47.44, 0.41951, 66, 52.9, -47.44, 0.58049, 2, 46, 165.94, -5.87, 0.16355, 66, 55.73, -5.87, 0.83645, 2, 46, 165.14, 37.38, 0.15, 66, 54.93, 37.38, 0.85, 2, 46, 157.6, 71.4, 0.21735, 66, 47.39, 71.4, 0.78265, 3, 46, 163.5, -99.54, 0.61812, 47, 39.01, -15.71, 0.30445, 66, 53.29, -99.54, 0.07744, 2, 46, 45.38, 27.24, 0.16741, 66, -64.83, 27.24, 0.83259, 2, 46, 63.74, 44.98, 0.15, 66, -46.47, 44.98, 0.85, 2, 46, 70.7, 61.92, 0.22175, 66, -39.51, 61.92, 0.77825, 2, 46, 62.88, 78.71, 0.38, 66, -47.34, 78.71, 0.62, 2, 46, 46.53, 85.3, 0.51, 66, -63.68, 85.3, 0.49, 2, 46, 29.92, 79.34, 0.388, 66, -80.29, 79.34, 0.612, 2, 46, 15.08, 62.21, 0.38, 66, -95.13, 62.21, 0.62, 2, 46, 14.09, 45.32, 0.41, 66, -96.12, 45.32, 0.59, 2, 46, 24.3, 27.06, 0.192, 66, -85.91, 27.06, 0.808, 1, 66, -61.57, 15.3, 1, 2, 46, 84.87, 62.14, 0.16757, 66, -25.34, 62.14, 0.83243, 2, 46, 61.9, 94.84, 0.68145, 66, -48.31, 94.84, 0.31855, 2, 46, 22.54, 21.88, 0.16, 66, -87.67, 21.88, 0.84, 2, 46, 43.15, -95.95, 0.73445, 66, -67.06, -95.95, 0.26555, 2, 46, 41.77, -87.24, 0.67858, 66, -68.44, -87.24, 0.32142, 2, 46, 60.05, -70.36, 0.50195, 66, -50.16, -70.36, 0.49805, 2, 46, 48.49, 51.09, 0.25, 66, -61.72, 51.09, 0.75, 2, 46, 48.17, 73.71, 0.15634, 66, -62.04, 73.71, 0.84366 ], + "hull": 29, + "edges": [ 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 56, 54, 56, 54, 52, 52, 50, 50, 48, 48, 46, 46, 44, 42, 44, 32, 34, 4, 58, 58, 60, 62, 64, 64, 66, 66, 54, 50, 68, 68, 70, 70, 44, 60, 72, 62, 74, 72, 74, 74, 76, 76, 78, 78, 44, 16, 80, 80, 82, 82, 84, 84, 86, 86, 44, 14, 88, 88, 72, 14, 16, 10, 12, 12, 14, 12, 60, 90, 92, 92, 94, 94, 96, 96, 98, 98, 100, 100, 102, 102, 104, 104, 106, 106, 90, 108, 110, 110, 112, 38, 40, 40, 42, 112, 40, 34, 36, 36, 38, 36, 114, 114, 108, 30, 32, 30, 28, 24, 26, 28, 26, 22, 24, 22, 20, 20, 18, 18, 16, 28, 116, 116, 118, 118, 120, 120, 20 ], + "width": 271, + "height": 298 + } + }, + "head-bb": { + "head": { + "type": "boundingbox", + "vertexCount": 6, + "vertices": [ -19.14, -70.3, 40.8, -118.08, 257.78, -115.62, 285.17, 57.18, 120.77, 164.95, -5.07, 76.95 ] + } + }, + "hoverboard-board": { + "hoverboard-board": { + "type": "mesh", + "uvs": [ 0.13865, 0.56624, 0.11428, 0.51461, 0.07619, 0.52107, 0.02364, 0.52998, 0.01281, 0.53182, 0, 0.37979, 0, 0.2206, 0.00519, 0.10825, 0.01038, 0.10726, 0.03834, 0.10194, 0.05091, 0, 0.08326, 0, 0.10933, 0.04206, 0.1382, 0.08865, 0.18916, 0.24067, 0.22234, 0.4063, 0.23886, 0.44063, 0.83412, 0.44034, 0.88444, 0.38296, 0.92591, 0.32639, 0.95996, 0.28841, 0.98612, 0.28542, 1, 0.38675, 0.99494, 0.47104, 0.97883, 0.53251, 0.94409, 0.62135, 0.90206, 0.69492, 0.86569, 0.71094, 0.82822, 0.70791, 0.81286, 0.77127, 0.62931, 0.77266, 0.61364, 0.70645, 0.47166, 0.70664, 0.45901, 0.77827, 0.27747, 0.76986, 0.2658, 0.70372, 0.24976, 0.71381, 0.24601, 0.77827, 0.23042, 0.84931, 0.20926, 0.90956, 0.17299, 1, 0.15077, 0.99967, 0.12906, 0.90192, 0.10369, 0.73693, 0.10198, 0.62482, 0.09131, 0.47272, 0.09133, 0.41325, 0.15082, 0.41868, 0.21991, 0.51856, 0.06331, 0.10816, 0.08383, 0.21696, 0.08905, 0.37532, 0.15903, 0.58726, 0.17538, 0.65706, 0.20118, 0.8029, 0.17918, 0.55644, 0.22166, 0.5802, 0.86259, 0.57962, 0.92346, 0.48534, 0.96691, 0.36881, 0.0945, 0.13259, 0.12688, 0.17831, 0.15986, 0.24682, 0.18036, 0.31268, 0.20607, 0.4235, 0.16074, 0.85403, 0.13624, 0.70122, 0.12096, 0.64049, 0.02396, 0.21811, 0.02732, 0.37839, 0.02557, 0.4972, 0.14476, 0.45736, 0.18019, 0.51689, 0.19692, 0.56636 ], + "triangles": [ 10, 11, 12, 9, 10, 12, 49, 9, 12, 60, 49, 12, 13, 60, 12, 61, 60, 13, 50, 49, 60, 50, 60, 61, 68, 8, 9, 68, 9, 49, 68, 49, 50, 7, 8, 68, 6, 7, 68, 61, 13, 14, 62, 61, 14, 50, 61, 62, 63, 62, 14, 59, 20, 21, 19, 20, 59, 51, 50, 62, 51, 62, 63, 51, 69, 68, 51, 68, 50, 6, 68, 69, 5, 6, 69, 18, 19, 59, 15, 63, 14, 59, 21, 22, 47, 51, 63, 47, 46, 51, 47, 63, 64, 15, 64, 63, 64, 15, 16, 71, 46, 47, 23, 59, 22, 69, 51, 70, 45, 46, 71, 70, 51, 2, 58, 18, 59, 58, 59, 23, 17, 18, 58, 70, 5, 69, 2, 51, 46, 1, 45, 71, 47, 48, 71, 47, 64, 48, 48, 72, 71, 1, 71, 72, 16, 48, 64, 45, 2, 46, 2, 45, 1, 70, 4, 5, 3, 70, 2, 3, 4, 70, 24, 58, 23, 72, 0, 1, 73, 55, 72, 55, 0, 72, 48, 73, 72, 57, 17, 58, 25, 57, 58, 56, 48, 16, 73, 48, 56, 56, 16, 17, 56, 17, 57, 52, 0, 55, 24, 25, 58, 44, 0, 52, 67, 44, 52, 52, 56, 53, 73, 52, 55, 56, 52, 73, 67, 52, 53, 26, 57, 25, 66, 67, 53, 56, 32, 35, 53, 56, 35, 56, 57, 32, 28, 31, 57, 57, 31, 32, 57, 27, 28, 26, 27, 57, 36, 53, 35, 43, 44, 67, 43, 67, 66, 34, 35, 32, 29, 31, 28, 30, 31, 29, 53, 54, 66, 53, 36, 54, 33, 34, 32, 37, 54, 36, 65, 43, 66, 38, 54, 37, 54, 65, 66, 39, 65, 54, 42, 43, 65, 38, 39, 54, 40, 42, 65, 40, 41, 42, 65, 39, 40 ], + "vertices": [ -189.36, 15.62, -201.35, 23.47, -220.09, 22.49, -245.95, 21.13, -251.28, 20.86, -257.58, 43.96, -257.57, 68.16, -255.02, 85.24, -252.47, 85.39, -238.71, 86.2, -232.52, 101.69, -216.61, 101.69, -203.78, 95.3, -189.58, 88.21, -164.51, 65.1, -148.19, 39.93, -140.06, 34.71, 152.82, 34.73, 177.57, 43.45, 197.97, 52.05, 214.72, 57.82, 227.6, 58.27, 234.42, 42.87, 231.94, 30.06, 224.01, 20.72, 206.91, 7.21, 186.23, -3.97, 168.34, -6.4, 149.9, -5.94, 142.35, -15.57, 52.04, -15.77, 44.33, -5.71, -25.52, -5.73, -31.75, -16.62, -121.07, -15.34, -126.81, -5.28, -134.7, -6.81, -136.54, -16.61, -144.22, -27.41, -154.63, -36.57, -172.47, -50.31, -183.41, -50.26, -194.09, -35.4, -206.56, -10.32, -207.4, 6.72, -212.65, 29.84, -212.64, 38.88, -183.37, 38.05, -149.38, 22.86, -226.43, 85.25, -216.33, 68.71, -213.76, 44.64, -179.34, 12.42, -171.29, 1.81, -158.6, -20.36, -169.42, 17.11, -148.52, 13.49, 166.82, 13.56, 196.76, 27.89, 218.14, 45.6, -211.08, 81.54, -195.15, 74.59, -178.93, 64.17, -168.84, 54.16, -156.19, 37.31, -178.5, -28.13, -190.55, -4.9, -198.07, 4.33, -245.79, 68.54, -244.14, 44.18, -245, 26.12, -186.36, 32.17, -168.92, 23.12, -160.69, 15.6 ], + "hull": 45, + "edges": [ 0, 2, 8, 10, 10, 12, 12, 14, 18, 20, 20, 22, 26, 28, 28, 30, 30, 32, 32, 34, 34, 36, 36, 38, 38, 40, 40, 42, 42, 44, 44, 46, 46, 48, 48, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 60, 62, 62, 64, 64, 66, 66, 68, 68, 70, 70, 72, 72, 74, 80, 82, 82, 84, 84, 86, 86, 88, 0, 88, 2, 90, 90, 92, 92, 94, 94, 96, 96, 32, 18, 98, 98, 100, 100, 102, 2, 4, 102, 4, 92, 102, 0, 104, 104, 106, 106, 108, 78, 80, 108, 78, 74, 76, 76, 78, 62, 56, 64, 70, 0, 110, 112, 114, 114, 116, 116, 118, 118, 42, 50, 116, 114, 34, 98, 120, 120, 122, 22, 24, 24, 26, 120, 24, 122, 124, 124, 126, 126, 128, 128, 96, 80, 130, 130, 132, 132, 134, 134, 88, 14, 16, 16, 18, 136, 16, 136, 138, 138, 140, 4, 6, 6, 8, 140, 6, 96, 112, 92, 142, 142, 144, 110, 146, 146, 112, 144, 146 ], + "width": 492, + "height": 152 + } + }, + "hoverboard-thruster-front": { + "hoverboard-thruster": { "x": 0.02, "y": -7.08, "rotation": 0.17, "width": 60, "height": 64 } + }, + "hoverboard-thruster-rear": { + "hoverboard-thruster": { "x": 1.1, "y": -6.29, "rotation": 0.17, "width": 60, "height": 64 } + }, + "hoverglow-front": { + "hoverglow-small": { + "x": 2.13, + "y": -2, + "scaleX": 0.303, + "scaleY": 0.495, + "rotation": 0.15, + "width": 274, + "height": 75 + } + }, + "hoverglow-rear": { + "hoverglow-small": { + "x": 1.39, + "y": -2.09, + "scaleX": 0.303, + "scaleY": 0.495, + "rotation": 0.61, + "width": 274, + "height": 75 + } + }, + "mouth": { + "mouth-grind": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 66, -98.93, -85.88, 0.22, 46, 11.28, -85.88, 0.78, 2, 66, -129.77, 1.84, 0.6, 46, -19.56, 1.84, 0.4, 2, 66, -74.12, 21.41, 0.6, 46, 36.09, 21.41, 0.4, 2, 66, -43.28, -66.32, 0.4, 46, 66.93, -66.32, 0.6 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + }, + "mouth-oooo": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 46, 11.28, -85.89, 0.22, 66, -98.93, -85.89, 0.78, 2, 46, -19.56, 1.85, 0.6, 66, -129.78, 1.85, 0.4, 2, 46, 36.1, 21.42, 0.6, 66, -74.12, 21.42, 0.4, 2, 46, 66.94, -66.32, 0.4, 66, -43.27, -66.32, 0.6 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + }, + "mouth-smile": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 66, -98.93, -85.89, 0.21075, 46, 11.28, -85.89, 0.78925, 2, 66, -129.77, 1.85, 0.6, 46, -19.56, 1.85, 0.4, 2, 66, -74.11, 21.42, 0.6, 46, 36.1, 21.42, 0.4, 2, 66, -43.27, -66.32, 0.40772, 46, 66.94, -66.32, 0.59228 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + } + }, + "muzzle": { + "muzzle01": { + "x": 151.97, + "y": 5.81, + "scaleX": 3.7361, + "scaleY": 3.7361, + "rotation": 0.15, + "width": 133, + "height": 79 + }, + "muzzle02": { + "x": 187.25, + "y": 5.9, + "scaleX": 4.0623, + "scaleY": 4.0623, + "rotation": 0.15, + "width": 135, + "height": 84 + }, + "muzzle03": { + "x": 231.96, + "y": 6.02, + "scaleX": 4.1325, + "scaleY": 4.1325, + "rotation": 0.15, + "width": 166, + "height": 106 + }, + "muzzle04": { + "x": 231.96, + "y": 6.02, + "scaleX": 4.0046, + "scaleY": 4.0046, + "rotation": 0.15, + "width": 149, + "height": 90 + }, + "muzzle05": { + "x": 293.8, + "y": 6.19, + "scaleX": 4.4673, + "scaleY": 4.4673, + "rotation": 0.15, + "width": 135, + "height": 75 + } + }, + "muzzle-glow": { + "muzzle-glow": { "width": 50, "height": 50 } + }, + "muzzle-ring": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "muzzle-ring2": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "muzzle-ring3": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "muzzle-ring4": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "neck": { + "neck": { "x": 9.77, "y": -3.01, "rotation": -55.22, "width": 36, "height": 41 } + }, + "portal-bg": { + "portal-bg": { "x": -3.1, "y": 7.25, "scaleX": 1.0492, "scaleY": 1.0492, "width": 266, "height": 266 } + }, + "portal-flare1": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare2": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare3": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare4": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare5": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare6": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare7": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare8": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare9": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare10": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-shade": { + "portal-shade": { "width": 266, "height": 266 } + }, + "portal-streaks1": { + "portal-streaks1": { "scaleX": 0.9774, "scaleY": 0.9774, "width": 252, "height": 256 } + }, + "portal-streaks2": { + "portal-streaks2": { "x": -1.64, "y": 2.79, "width": 250, "height": 249 } + }, + "rear-bracer": { + "rear-bracer": { "x": 11.15, "y": -2.2, "rotation": 66.17, "width": 56, "height": 72 } + }, + "rear-foot": { + "rear-foot": { + "type": "mesh", + "uvs": [ 0.48368, 0.1387, 0.51991, 0.21424, 0.551, 0.27907, 0.58838, 0.29816, 0.63489, 0.32191, 0.77342, 0.39267, 1, 0.73347, 1, 1, 0.54831, 0.99883, 0.31161, 1, 0, 1, 0, 0.41397, 0.13631, 0, 0.41717, 0 ], + "triangles": [ 8, 3, 4, 8, 4, 5, 8, 5, 6, 8, 6, 7, 11, 1, 10, 3, 9, 2, 2, 10, 1, 12, 13, 0, 0, 11, 12, 1, 11, 0, 2, 9, 10, 3, 8, 9 ], + "vertices": [ 2, 8, 10.45, 29.41, 0.90802, 9, -6.74, 49.62, 0.09198, 2, 8, 16.56, 29.27, 0.84259, 9, -2.65, 45.09, 0.15741, 2, 8, 21.8, 29.15, 0.69807, 9, 0.85, 41.2, 0.30193, 2, 8, 25.53, 31.43, 0.52955, 9, 5.08, 40.05, 0.47045, 2, 8, 30.18, 34.27, 0.39303, 9, 10.33, 38.62, 0.60697, 2, 8, 44.02, 42.73, 0.27525, 9, 25.98, 34.36, 0.72475, 2, 8, 76.47, 47.28, 0.21597, 9, 51.56, 13.9, 0.78403, 2, 8, 88.09, 36.29, 0.28719, 9, 51.55, -2.09, 0.71281, 2, 8, 52.94, -0.73, 0.47576, 9, 0.52, -1.98, 0.52424, 2, 8, 34.63, -20.23, 0.68757, 9, -26.23, -2.03, 0.31243, 2, 8, 10.44, -45.81, 0.84141, 9, -61.43, -2, 0.15859, 2, 8, -15.11, -21.64, 0.93283, 9, -61.4, 33.15, 0.06717, 1, 8, -22.57, 6.61, 1, 1, 8, -0.76, 29.67, 1 ], + "hull": 14, + "edges": [ 14, 12, 10, 12, 14, 16, 16, 18, 18, 20, 4, 18, 20, 22, 24, 26, 22, 24, 4, 2, 2, 20, 4, 6, 6, 16, 6, 8, 8, 10, 2, 0, 0, 26 ], + "width": 113, + "height": 60 + } + }, + "rear-shin": { + "rear-shin": { "x": 58.29, "y": -2.75, "rotation": 92.37, "width": 75, "height": 178 } + }, + "rear-thigh": { + "rear-thigh": { "x": 33.11, "y": -4.11, "rotation": 72.54, "width": 55, "height": 94 } + }, + "rear-upper-arm": { + "rear-upper-arm": { "x": 21.13, "y": 4.09, "rotation": 89.33, "width": 40, "height": 87 } + }, + "side-glow1": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.2353, "scaleY": 0.4132, "width": 274, "height": 75 } + }, + "side-glow2": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.2353, "scaleY": 0.4132, "width": 274, "height": 75 } + }, + "side-glow3": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.3586, "scaleY": 0.6297, "width": 274, "height": 75 } + }, + "torso": { + "torso": { + "type": "mesh", + "uvs": [ 0.6251, 0.12672, 1, 0.26361, 1, 0.28871, 1, 0.66021, 1, 0.68245, 0.92324, 0.69259, 0.95116, 0.84965, 0.77124, 1, 0.49655, 1, 0.27181, 1, 0.13842, 0.77196, 0.09886, 0.6817, 0.05635, 0.58471, 0, 0.45614, 0, 0.33778, 0, 0.19436, 0.14463, 0, 0.27802, 0, 0.72525, 0.27835, 0.76091, 0.46216, 0.84888, 0.67963, 0.68257, 0.63249, 0.53986, 0.3847, 0.25443, 0.3217, 0.30063, 0.55174, 0.39553, 0.79507, 0.26389, 0.17007, 0.5241, 0.18674, 0.71492, 0.76655, 0.82151, 0.72956, 0.27626, 0.4304, 0.62327, 0.52952, 0.3455, 0.66679, 0.53243, 0.2914 ], + "triangles": [ 18, 1, 2, 19, 2, 3, 18, 0, 1, 23, 15, 26, 27, 26, 16, 14, 15, 23, 15, 16, 26, 17, 27, 16, 13, 14, 23, 0, 27, 17, 13, 23, 30, 11, 12, 24, 21, 31, 19, 12, 13, 30, 24, 22, 31, 31, 22, 19, 12, 30, 24, 32, 24, 31, 24, 30, 22, 3, 20, 19, 32, 31, 21, 11, 24, 32, 4, 5, 3, 8, 28, 7, 7, 29, 6, 7, 28, 29, 9, 25, 8, 8, 25, 28, 9, 10, 25, 29, 5, 6, 10, 32, 25, 25, 21, 28, 25, 32, 21, 10, 11, 32, 28, 21, 29, 29, 20, 5, 29, 21, 20, 5, 20, 3, 20, 21, 19, 33, 26, 27, 22, 18, 19, 19, 18, 2, 33, 27, 18, 30, 23, 22, 22, 33, 18, 23, 33, 22, 33, 23, 26, 27, 0, 18 ], + "vertices": [ 2, 29, 44.59, -10.39, 0.88, 40, -17.65, 33.99, 0.12, 3, 28, 59.65, -45.08, 0.12189, 29, 17.13, -45.08, 0.26811, 40, 22.68, 15.82, 0.61, 3, 28, 55.15, -44.72, 0.1345, 29, 12.63, -44.72, 0.2555, 40, 23.43, 11.37, 0.61, 3, 27, 31.01, -39.45, 0.51133, 28, -11.51, -39.45, 0.30867, 40, 34.58, -54.57, 0.18, 3, 27, 27.01, -39.14, 0.53492, 28, -15.5, -39.14, 0.28508, 40, 35.25, -58.52, 0.18, 2, 27, 25.79, -31.5, 0.75532, 28, -16.73, -31.5, 0.24468, 1, 27, -2.61, -32, 1, 1, 27, -28.2, -12.29, 1, 1, 27, -26.08, 14.55, 1, 1, 27, -24.35, 36.5, 1, 2, 27, 17.6, 46.3, 0.8332, 28, -24.92, 46.3, 0.1668, 2, 27, 34.1, 48.89, 0.59943, 28, -8.42, 48.89, 0.40058, 3, 27, 51.83, 51.67, 0.29262, 28, 9.32, 51.67, 0.63181, 29, -33.2, 51.67, 0.07557, 3, 27, 75.34, 55.35, 0.06656, 28, 32.82, 55.35, 0.62298, 29, -9.7, 55.35, 0.31046, 2, 28, 54.06, 53.67, 0.37296, 29, 11.54, 53.67, 0.62704, 2, 28, 79.79, 51.64, 0.10373, 29, 37.27, 51.64, 0.89627, 1, 29, 71.04, 34.76, 1, 1, 29, 70.01, 21.72, 1, 1, 30, 36.74, 7.06, 1, 3, 30, 45.7, -24.98, 0.67, 28, 25.87, -18.9, 0.3012, 29, -16.65, -18.9, 0.0288, 2, 27, 28.69, -24.42, 0.77602, 28, -13.83, -24.42, 0.22398, 3, 30, 43.24, -56.49, 0.064, 27, 38.43, -8.84, 0.67897, 28, -4.09, -8.84, 0.25703, 3, 30, 22.02, -14.85, 0.29, 28, 41.48, 1.59, 0.53368, 29, -1.04, 1.59, 0.17632, 3, 30, -7.45, -8.33, 0.76, 28, 54.98, 28.59, 0.06693, 29, 12.46, 28.59, 0.17307, 3, 30, 3.91, -48.4, 0.25, 27, 55.87, 27.33, 0.15843, 28, 13.35, 27.33, 0.59157, 1, 27, 11.47, 21.51, 1, 2, 30, -11.09, 18.74, 0.416, 29, 39.6, 25.51, 0.584, 2, 30, 14.56, 20.03, 0.53, 29, 34.6, 0.33, 0.47, 1, 27, 14.12, -10.1, 1, 2, 27, 19.94, -21.03, 0.92029, 28, -22.58, -21.03, 0.07971, 3, 30, -2.08, -27.26, 0.29, 28, 35.31, 27.99, 0.49582, 29, -7.21, 27.99, 0.21418, 2, 30, 34.42, -39.19, 0.25, 28, 14.84, -4.5, 0.75, 2, 27, 34.87, 24.58, 0.67349, 28, -7.64, 24.58, 0.32651, 2, 30, 18.5, 1.59, 0.76, 29, 15.76, 1, 0.24 ], + "hull": 18, + "edges": [ 14, 12, 12, 10, 10, 8, 18, 20, 32, 34, 30, 32, 2, 4, 36, 4, 36, 38, 38, 40, 4, 6, 6, 8, 40, 6, 40, 42, 14, 16, 16, 18, 50, 16, 46, 52, 54, 36, 2, 0, 0, 34, 54, 0, 54, 32, 20, 50, 14, 56, 56, 42, 50, 56, 56, 58, 58, 40, 58, 10, 46, 60, 60, 48, 26, 60, 60, 44, 24, 26, 24, 48, 42, 62, 62, 44, 48, 62, 48, 64, 64, 50, 42, 64, 20, 22, 22, 24, 64, 22, 26, 28, 28, 30, 28, 46, 44, 66, 66, 54, 46, 66, 66, 36, 62, 38 ], + "width": 98, + "height": 180 + } + } + } + } +], +"events": { + "footstep": {} +}, +"animations": { + "aim": { + "slots": { + "crosshair": { + "attachment": [ + { "name": "crosshair" } + ] + } + }, + "bones": { + "front-fist": { + "rotate": [ + { "value": 36.08 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": -26.55 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "value": 62.31 } + ] + }, + "front-bracer": { + "rotate": [ + { "value": 9.11 } + ] + }, + "gun": { + "rotate": [ + { "value": -0.31 } + ] + } + }, + "ik": { + "aim-ik": [ + { "mix": 0.995 } + ] + }, + "transform": { + "aim-front-arm-transform": [ + { "mixRotate": 0.784, "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ], + "aim-head-transform": [ + { "mixRotate": 0.659, "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ], + "aim-torso-transform": [ + { "mixRotate": 0.423, "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ] + } + }, + "death": { + "slots": { + "eye": { + "attachment": [ + { "name": "eye-surprised" }, + { "time": 0.5333, "name": "eye-indifferent" }, + { "time": 2.2, "name": "eye-surprised" }, + { "time": 4.6, "name": "eye-indifferent" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "name": "mouth-oooo" }, + { "time": 0.5333, "name": "mouth-grind" }, + { "time": 1.4, "name": "mouth-oooo" }, + { "time": 2.1667, "name": "mouth-grind" }, + { "time": 4.5333, "name": "mouth-oooo" } + ] + } + }, + "bones": { + "head": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.015, -2.83, 0.036, 12.72 ] + }, + { + "time": 0.0667, + "value": 12.19, + "curve": [ 0.096, 11.68, 0.119, -1.14 ] + }, + { + "time": 0.1333, + "value": -6.86, + "curve": [ 0.149, -13.27, 0.21, -37.28 ] + }, + { + "time": 0.3, + "value": -36.86, + "curve": [ 0.354, -36.61, 0.412, -32.35 ] + }, + { + "time": 0.4667, + "value": -23.49, + "curve": [ 0.49, -19.87, 0.512, -3.29 ] + }, + { + "time": 0.5333, + "value": -3.24, + "curve": [ 0.56, -3.39, 0.614, -67.25 ] + }, + { + "time": 0.6333, + "value": -74.4, + "curve": [ 0.652, -81.58, 0.702, -88.94 ] + }, + { + "time": 0.7333, + "value": -88.93, + "curve": [ 0.805, -88.91, 0.838, -80.87 ] + }, + { + "time": 0.8667, + "value": -81.03, + "curve": [ 0.922, -81.32, 0.976, -85.29 ] + }, + { "time": 1, "value": -85.29, "curve": "stepped" }, + { + "time": 2.2333, + "value": -85.29, + "curve": [ 2.314, -85.29, 2.382, -68.06 ] + }, + { + "time": 2.4667, + "value": -63.48, + "curve": [ 2.57, -57.87, 2.916, -55.24 ] + }, + { + "time": 3.2, + "value": -55.1, + "curve": [ 3.447, -54.98, 4.135, -56.61 ] + }, + { + "time": 4.2667, + "value": -58.23, + "curve": [ 4.672, -63.24, 4.646, -82.69 ] + }, + { "time": 4.9333, "value": -85.29 } + ], + "scale": [ + { + "time": 0.4667, + "curve": [ 0.469, 1.005, 0.492, 1.065, 0.475, 1.018, 0.492, 0.94 ] + }, + { + "time": 0.5, + "x": 1.065, + "y": 0.94, + "curve": [ 0.517, 1.065, 0.541, 0.991, 0.517, 0.94, 0.542, 1.026 ] + }, + { + "time": 0.5667, + "x": 0.99, + "y": 1.025, + "curve": [ 0.593, 0.988, 0.609, 1.002, 0.595, 1.024, 0.607, 1.001 ] + }, + { "time": 0.6333 } + ] + }, + "neck": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.114, 1.33, 0.195, 4.13 ] + }, + { + "time": 0.2667, + "value": 4.13, + "curve": [ 0.351, 4.14, 0.444, -24.5 ] + }, + { + "time": 0.5, + "value": -24.69, + "curve": [ 0.571, -23.89, 0.55, 34.22 ] + }, + { + "time": 0.6667, + "value": 35.13, + "curve": [ 0.713, 34.81, 0.756, 22.76 ] + }, + { + "time": 0.8333, + "value": 22.82, + "curve": [ 0.868, 22.84, 0.916, 47.95 ] + }, + { "time": 0.9667, "value": 47.95, "curve": "stepped" }, + { + "time": 2.2333, + "value": 47.95, + "curve": [ 2.3, 47.95, 2.617, 18.72 ] + }, + { + "time": 2.6667, + "value": 18.51, + "curve": [ 3.172, 16.58, 4.06, 16.79 ] + }, + { + "time": 4.5333, + "value": 18.51, + "curve": [ 4.707, 19.13, 4.776, 41.11 ] + }, + { "time": 4.8, "value": 47.95 } + ] + }, + "torso": { + "rotate": [ + { + "value": -8.62, + "curve": [ 0.01, -16.71, 0.032, -33.6 ] + }, + { + "time": 0.0667, + "value": -33.37, + "curve": [ 0.182, -32.61, 0.298, 123.07 ] + }, + { + "time": 0.4667, + "value": 122.77, + "curve": [ 0.511, 122.69, 0.52, 100.2 ] + }, + { + "time": 0.5667, + "value": 88.96, + "curve": [ 0.588, 83.89, 0.667, 75.34 ] + }, + { + "time": 0.7, + "value": 75.34, + "curve": [ 0.767, 75.34, 0.9, 76.03 ] + }, + { "time": 0.9667, "value": 76.03 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -38.86, + "curve": [ 0.022, -40.38, 0.096, -41.92 ] + }, + { + "time": 0.1333, + "value": -41.92, + "curve": [ 0.176, -41.92, 0.216, -16.92 ] + }, + { + "time": 0.2333, + "value": -4.35, + "curve": [ 0.258, 13.69, 0.308, 60.35 ] + }, + { + "time": 0.4, + "value": 60.17, + "curve": [ 0.496, 59.98, 0.539, 33.63 ] + }, + { + "time": 0.5667, + "value": 23.06, + "curve": [ 0.595, 32.71, 0.675, 53.71 ] + }, + { + "time": 0.7333, + "value": 53.61, + "curve": [ 0.797, 53.51, 0.926, 30.98 ] + }, + { "time": 0.9333, "value": 19.57, "curve": "stepped" }, + { + "time": 1.9667, + "value": 19.57, + "curve": [ 2.245, 19.57, 2.702, 77.03 ] + }, + { + "time": 3.0667, + "value": 77.06, + "curve": [ 3.209, 77.33, 3.291, 67.99 ] + }, + { + "time": 3.4333, + "value": 67.96, + "curve": [ 3.608, 68.34, 3.729, 73.88 ] + }, + { + "time": 3.8333, + "value": 73.42, + "curve": [ 4.152, 73.91, 4.46, 71.98 ] + }, + { + "time": 4.6333, + "value": 64.77, + "curve": [ 4.688, 62.5, 4.847, 26.42 ] + }, + { "time": 4.8667, "value": 10.94 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": -44.7, + "curve": [ 0.033, -44.7, 0.12, 54.89 ] + }, + { + "time": 0.1333, + "value": 64.62, + "curve": [ 0.154, 79.18, 0.214, 79.42 ] + }, + { + "time": 0.2667, + "value": 63.4, + "curve": [ 0.293, 55.19, 0.332, 30.13 ] + }, + { + "time": 0.3667, + "value": 30.13, + "curve": [ 0.4, 30.13, 0.441, 39.87 ] + }, + { + "time": 0.4667, + "value": 55.13, + "curve": [ 0.488, 68.18, 0.52, 100.72 ] + }, + { + "time": 0.5333, + "value": 111.96, + "curve": [ 0.551, 126.88, 0.627, 185.97 ] + }, + { + "time": 0.6667, + "value": 185.97, + "curve": [ 0.692, 185.97, 0.736, 162.43 ] + }, + { + "time": 0.8, + "value": 158.01, + "curve": [ 0.9, 151.12, 1.017, 144.01 ] + }, + { "time": 1.1, "value": 144.01, "curve": "stepped" }, + { + "time": 2.3667, + "value": 144.01, + "curve": [ 2.492, 144.01, 2.742, 138.63 ] + }, + { + "time": 2.8667, + "value": 138.63, + "curve": [ 3.067, 138.63, 3.467, 138.63 ] + }, + { + "time": 3.6667, + "value": 138.63, + "curve": [ 3.883, 138.63, 4.317, 135.18 ] + }, + { + "time": 4.5333, + "value": 135.18, + "curve": [ 4.575, 135.18, 4.692, 131.59 ] + }, + { + "time": 4.7333, + "value": 131.59, + "curve": [ 4.758, 131.59, 4.517, 144.01 ] + }, + { "time": 4.8333, "value": 144.01 } + ], + "translate": [ + { + "time": 0.4667, + "curve": [ 0.517, 0, 0.617, -34.96, 0.517, 0, 0.617, -16.59 ] + }, + { "time": 0.6667, "x": -35.02, "y": -16.62 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 21.88, + "curve": [ 0.033, 21.88, 0.099, 20.44 ] + }, + { + "time": 0.1333, + "value": 9.43, + "curve": [ 0.164, -0.29, 0.162, -38.26 ] + }, + { + "time": 0.2, + "value": -38.05, + "curve": [ 0.24, -37.96, 0.228, -17.82 ] + }, + { + "time": 0.3333, + "value": -9.73, + "curve": [ 0.372, -6.76, 0.431, -0.74 ] + }, + { + "time": 0.4667, + "value": 6.47, + "curve": [ 0.489, 11.05, 0.503, 19.09 ] + }, + { + "time": 0.5333, + "value": 19.09, + "curve": [ 0.571, 19.09, 0.554, -42.67 ] + }, + { + "time": 0.6, + "value": -42.67, + "curve": [ 0.653, -42.67, 0.691, -13.8 ] + }, + { + "time": 0.7, + "value": -3.54, + "curve": [ 0.707, 3.8, 0.719, 24.94 ] + }, + { + "time": 0.8, + "value": 25.31, + "curve": [ 0.902, 24.75, 0.992, -0.34 ] + }, + { "time": 1, "value": -32.16, "curve": "stepped" }, + { + "time": 2.2333, + "value": -32.16, + "curve": [ 2.6, -32.16, 2.638, -5.3 ] + }, + { + "time": 2.7, + "value": -1.96, + "curve": [ 2.707, -1.56, 2.775, 1.67 ] + }, + { + "time": 2.8, + "value": 1.67, + "curve": [ 2.825, 1.67, 2.875, -0.39 ] + }, + { + "time": 2.9, + "value": -0.39, + "curve": [ 2.925, -0.39, 2.975, 0.26 ] + }, + { + "time": 3, + "value": 0.26, + "curve": [ 3.025, 0.26, 3.075, -1.81 ] + }, + { + "time": 3.1, + "value": -1.81, + "curve": [ 3.125, -1.81, 3.175, -0.52 ] + }, + { + "time": 3.2, + "value": -0.52, + "curve": [ 3.225, -0.52, 3.275, -2.41 ] + }, + { + "time": 3.3, + "value": -2.41, + "curve": [ 3.333, -2.41, 3.4, -0.38 ] + }, + { + "time": 3.4333, + "value": -0.38, + "curve": [ 3.467, -0.38, 3.533, -2.25 ] + }, + { + "time": 3.5667, + "value": -2.25, + "curve": [ 3.592, -2.25, 3.642, -0.33 ] + }, + { + "time": 3.6667, + "value": -0.33, + "curve": [ 3.7, -0.33, 3.767, -1.34 ] + }, + { + "time": 3.8, + "value": -1.34, + "curve": [ 3.825, -1.34, 3.862, -0.77 ] + }, + { + "time": 3.9, + "value": -0.77, + "curve": [ 3.942, -0.77, 3.991, -1.48 ] + }, + { + "time": 4, + "value": -1.87, + "curve": [ 4.167, -1.87, 4.5, -1.96 ] + }, + { + "time": 4.6667, + "value": -1.96, + "curve": [ 4.709, 18.05, 4.767, 34.55 ] + }, + { + "time": 4.8, + "value": 34.55, + "curve": [ 4.84, 34.24, 4.902, 12.03 ] + }, + { "time": 4.9333, "value": -18.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -2.33, + "curve": [ 0.019, 4.43, 0.069, 10.82 ] + }, + { + "time": 0.1, + "value": 10.6, + "curve": [ 0.148, 10.6, 0.123, -15.24 ] + }, + { + "time": 0.2, + "value": -15.35, + "curve": [ 0.266, -15.44, 0.316, -6.48 ] + }, + { + "time": 0.3333, + "value": -3.9, + "curve": [ 0.362, 0.43, 0.479, 22.36 ] + }, + { + "time": 0.5667, + "value": 22.01, + "curve": [ 0.61, 21.84, 0.627, 12.85 ] + }, + { + "time": 0.6333, + "value": 9.05, + "curve": [ 0.643, 2.77, 0.622, -39.43 ] + }, + { + "time": 0.7, + "value": -39.5, + "curve": [ 0.773, -39.57, 0.814, 14.77 ] + }, + { + "time": 0.8667, + "value": 14.81, + "curve": [ 0.965, 14.88, 1.1, 5.64 ] + }, + { "time": 1.1, "value": -6.08, "curve": "stepped" }, + { + "time": 2.2333, + "value": -6.08, + "curve": [ 2.307, -6.08, 2.427, -25.89 ] + }, + { + "time": 2.5333, + "value": -22.42, + "curve": [ 2.598, -20.38, 2.657, 5.73 ] + }, + { + "time": 2.7, + "value": 5.73, + "curve": [ 2.77, 5.73, 2.851, -5.38 ] + }, + { + "time": 2.9333, + "value": -5.38, + "curve": [ 3.008, -5.38, 3.087, -4.54 ] + }, + { + "time": 3.1667, + "value": -4.17, + "curve": [ 3.223, -3.91, 4.486, 5.73 ] + }, + { + "time": 4.6667, + "value": 5.73, + "curve": [ 4.733, 5.73, 4.886, -2.47 ] + }, + { "time": 4.9333, "value": -6.52 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.36, + "curve": [ 0.033, 10.36, 0.1, -32.89 ] + }, + { + "time": 0.1333, + "value": -32.89, + "curve": [ 0.183, -32.89, 0.283, -4.45 ] + }, + { + "time": 0.3333, + "value": -4.45, + "curve": [ 0.367, -4.45, 0.438, -6.86 ] + }, + { + "time": 0.4667, + "value": -8.99, + "curve": [ 0.529, -13.62, 0.605, -20.58 ] + }, + { + "time": 0.6333, + "value": -23.2, + "curve": [ 0.708, -30.18, 0.758, -35.56 ] + }, + { + "time": 0.8, + "value": -35.56, + "curve": [ 0.875, -35.56, 1.025, -23.2 ] + }, + { "time": 1.1, "value": -23.2 } + ] + }, + "gun": { + "rotate": [ + { + "value": -2.79, + "curve": [ 0.033, -2.79, 0.12, -7.22 ] + }, + { + "time": 0.1333, + "value": -8.52, + "curve": [ 0.168, -11.87, 0.29, -23.71 ] + }, + { + "time": 0.3333, + "value": -26.24, + "curve": [ 0.369, -28.31, 0.436, -29.75 ] + }, + { + "time": 0.5, + "value": -29.66, + "curve": [ 0.552, -29.58, 0.611, -25.47 ] + }, + { + "time": 0.6333, + "value": -22.68, + "curve": [ 0.656, -19.76, 0.68, -10.02 ] + }, + { + "time": 0.7, + "value": -6.49, + "curve": [ 0.722, -2.6, 0.75, -1.22 ] + }, + { + "time": 0.7667, + "value": -1.35, + "curve": [ 0.792, -1.55, 0.842, -19.74 ] + }, + { "time": 0.8667, "value": -19.8 } + ] + }, + "hip": { + "translate": [ + { + "curve": [ 0.098, -42.62, 0.166, -79.85, 0.029, 84.97, 0.109, 155.93 ] + }, + { + "time": 0.2667, + "x": -133.79, + "y": 152.44, + "curve": [ 0.361, -184.63, 0.392, -203.69, 0.42, 149.12, 0.467, -15.7 ] + }, + { + "time": 0.4667, + "x": -230.02, + "y": -113.87, + "curve": [ 0.523, -249.86, 0.565, -261.7, 0.473, -133.1, 0.583, -203.43 ] + }, + { + "time": 0.6, + "x": -268.57, + "y": -203.43, + "curve": [ 0.663, -280.98, 0.816, -290.05, 0.708, -203.43, 0.892, -203.5 ] + }, + { "time": 1, "x": -290.42, "y": -203.5 } + ] + }, + "front-thigh": { + "rotate": [ + { + "curve": [ 0.06, 1.02, 0.151, 45.23 ] + }, + { + "time": 0.1667, + "value": 54.01, + "curve": [ 0.19, 66.85, 0.358, 169.85 ] + }, + { + "time": 0.5, + "value": 169.51, + "curve": [ 0.628, 169.85, 0.692, 108.85 ] + }, + { + "time": 0.7, + "value": 97.74, + "curve": [ 0.723, 102.6, 0.805, 111.6 ] + }, + { + "time": 0.8667, + "value": 111.69, + "curve": [ 0.899, 111.83, 1.015, 109.15 ] + }, + { "time": 1.0667, "value": 95.8 } + ] + }, + "front-shin": { + "rotate": [ + { + "curve": [ 0.086, -0.02, 0.191, -24.25 ] + }, + { + "time": 0.2, + "value": -26.5, + "curve": [ 0.214, -29.92, 0.249, -40.51 ] + }, + { + "time": 0.3333, + "value": -40.57, + "curve": [ 0.431, -40.7, 0.459, -11.34 ] + }, + { + "time": 0.4667, + "value": -8.71, + "curve": [ 0.477, -5.16, 0.524, 17.13 ] + }, + { + "time": 0.6, + "value": 16.98, + "curve": [ 0.632, 17.09, 0.625, 2.76 ] + }, + { + "time": 0.6333, + "value": 2.76, + "curve": [ 0.648, 2.76, 0.653, 2.75 ] + }, + { + "time": 0.6667, + "value": 2.59, + "curve": [ 0.678, 2.39, 0.733, 2.53 ] + }, + { + "time": 0.7333, + "value": -9.43, + "curve": [ 0.745, -2.48, 0.782, 3.12 ] + }, + { + "time": 0.8, + "value": 4.28, + "curve": [ 0.832, 6.32, 0.895, 8.46 ] + }, + { + "time": 0.9333, + "value": 8.49, + "curve": [ 0.986, 8.53, 1.051, 6.38 ] + }, + { + "time": 1.0667, + "value": 2.28, + "curve": [ 1.078, 4.17, 1.103, 5.86 ] + }, + { + "time": 1.1333, + "value": 5.88, + "curve": [ 1.191, 5.93, 1.209, 4.56 ] + }, + { "time": 1.2333, "value": 2.52 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.12, 50.26 ] + }, + { + "time": 0.1333, + "value": 57.3, + "curve": [ 0.164, 73.34, 0.274, 147.18 ] + }, + { + "time": 0.3333, + "value": 147.1, + "curve": [ 0.475, 146.45, 0.583, 95.72 ] + }, + { + "time": 0.6, + "value": 79.66, + "curve": [ 0.62, 94.74, 0.732, 103.15 ] + }, + { + "time": 0.7667, + "value": 103.02, + "curve": [ 0.812, 102.85, 0.897, 95.75 ] + }, + { "time": 0.9333, "value": 83.01 } + ] + }, + "rear-shin": { + "rotate": [ + { + "curve": [ 0.021, -16.65, 0.091, -54.82 ] + }, + { + "time": 0.1667, + "value": -55.29, + "curve": [ 0.187, -55.42, 0.213, -52.52 ] + }, + { + "time": 0.2333, + "value": -45.98, + "curve": [ 0.242, -43.1, 0.311, -12.73 ] + }, + { + "time": 0.3333, + "value": -6.32, + "curve": [ 0.356, 0.13, 0.467, 24.5 ] + }, + { + "time": 0.5, + "value": 24.5, + "curve": [ 0.543, 24.5, 0.56, 3.78 ] + }, + { + "time": 0.5667, + "value": -3.53, + "curve": [ 0.585, 3.86, 0.659, 16.63 ] + }, + { + "time": 0.7, + "value": 16.56, + "curve": [ 0.782, 16.43, 0.896, 8.44 ] + }, + { + "time": 0.9333, + "value": 4.04, + "curve": [ 0.956, 6.84, 1.008, 8.41 ] + }, + { + "time": 1.0333, + "value": 8.41, + "curve": [ 1.067, 8.41, 1.122, 8.14 ] + }, + { "time": 1.1667, "value": 5.8 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -0.28, + "curve": [ 0.033, -0.28, 0.256, -66.71 ] + }, + { + "time": 0.3667, + "value": -66.84, + "curve": [ 0.418, -66.91, 0.499, -21.79 ] + }, + { + "time": 0.6, + "value": -21.52, + "curve": [ 0.652, -21.38, 0.665, -53.96 ] + }, + { + "time": 0.7, + "value": -54.26, + "curve": [ 0.757, -53.96, 0.843, -2.07 ] + }, + { + "time": 0.9333, + "value": -1.47, + "curve": [ 0.968, -2.07, 0.975, -19.96 ] + }, + { + "time": 1, + "value": -19.96, + "curve": [ 1.025, -19.96, 1.075, -12.42 ] + }, + { + "time": 1.1, + "value": -12.42, + "curve": [ 1.133, -12.42, 1.2, -18.34 ] + }, + { "time": 1.2333, "value": -18.34 } + ] + }, + "front-foot": { + "rotate": [ + { + "curve": [ 0.008, -11.33, 0.108, -57.71 ] + }, + { + "time": 0.1333, + "value": -57.71, + "curve": [ 0.175, -57.71, 0.229, 19.73 ] + }, + { + "time": 0.3, + "value": 19.34, + "curve": [ 0.354, 19.34, 0.4, -57.76 ] + }, + { + "time": 0.4333, + "value": -57.76, + "curve": [ 0.458, -57.76, 0.511, -3.56 ] + }, + { + "time": 0.5333, + "value": 3.7, + "curve": [ 0.563, 13.29, 0.633, 15.79 ] + }, + { + "time": 0.6667, + "value": 15.79, + "curve": [ 0.7, 15.79, 0.767, -48.75 ] + }, + { + "time": 0.8, + "value": -48.75, + "curve": [ 0.842, -48.75, 0.925, 4.7 ] + }, + { + "time": 0.9667, + "value": 4.7, + "curve": [ 1, 4.7, 1.067, -22.9 ] + }, + { + "time": 1.1, + "value": -22.9, + "curve": [ 1.142, -22.9, 1.225, -13.28 ] + }, + { "time": 1.2667, "value": -13.28 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": -0.28 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -0.28, + "curve": [ 0.008, -0.28, 0.003, -66.62 ] + }, + { + "time": 0.0667, + "value": -65.75, + "curve": [ 0.166, -64.42, 0.234, 14.35 ] + }, + { + "time": 0.2667, + "value": 38.25, + "curve": [ 0.294, 57.91, 0.392, 89.79 ] + }, + { + "time": 0.4667, + "value": 90.73, + "curve": [ 0.483, 90.73, 0.55, 177.66 ] + }, + { + "time": 0.5667, + "value": 177.66, + "curve": [ 0.733, 176.24, 0.75, 11.35 ] + }, + { + "time": 0.8, + "value": 11.35, + "curve": [ 0.886, 12.29, 0.911, 47.88 ] + }, + { + "time": 0.9333, + "value": 56.77, + "curve": [ 0.967, 70.59, 1.05, 86.46 ] + }, + { + "time": 1.1, + "value": 86.46, + "curve": [ 1.187, 86.46, 1.214, 66.44 ] + }, + { "time": 1.3333, "value": 64.55 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "value": -0.28, + "curve": [ 0, -7.97, 0.027, -18.69 ] + }, + { + "time": 0.0667, + "value": -19, + "curve": [ 0.166, -19.3, 0.208, 15.58 ] + }, + { + "time": 0.2667, + "value": 45.95, + "curve": [ 0.306, 66.24, 0.378, 99.08 ] + }, + { + "time": 0.4333, + "value": 99.08, + "curve": [ 0.497, 98.62, 0.488, -1.2 ] + }, + { + "time": 0.5667, + "value": -1.32, + "curve": [ 0.637, -0.84, 0.687, 94.41 ] + }, + { + "time": 0.7333, + "value": 94.33, + "curve": [ 0.832, 94.16, 0.895, 29.6 ] + }, + { + "time": 0.9667, + "value": 28.67, + "curve": [ 1.026, 28.67, 1.045, 53.14 ] + }, + { "time": 1.1, "value": 53.38 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.011, 4.5, 0.05, 11.42 ] + }, + { + "time": 0.0667, + "value": 11.42, + "curve": [ 0.1, 11.42, 0.136, -5.92 ] + }, + { + "time": 0.1667, + "value": -10.54, + "curve": [ 0.206, -16.51, 0.327, -22 ] + }, + { + "time": 0.3667, + "value": -24.47, + "curve": [ 0.413, -27.37, 0.467, -43.99 ] + }, + { + "time": 0.5, + "value": -43.99, + "curve": [ 0.533, -43.99, 0.552, 12.12 ] + }, + { + "time": 0.6333, + "value": 11.85, + "curve": [ 0.714, 11.59, 0.758, -34.13 ] + }, + { + "time": 0.8, + "value": -34.13, + "curve": [ 0.858, -34.13, 1.015, -12.47 ] + }, + { + "time": 1.0667, + "value": -8.85, + "curve": [ 1.121, -5.07, 1.219, -0.02 ] + }, + { + "time": 1.3333, + "value": 1.29, + "curve": [ 1.509, 3.3, 1.763, 2.75 ] + }, + { + "time": 1.8667, + "value": 2.78, + "curve": [ 1.974, 2.81, 2.108, 2.81 ] + }, + { + "time": 2.2, + "value": 2.78, + "curve": [ 2.315, 2.74, 2.374, 1.22 ] + }, + { + "time": 2.4667, + "value": 1.18, + "curve": [ 2.525, 1.18, 2.608, 10.79 ] + }, + { + "time": 2.6667, + "value": 10.79, + "curve": [ 2.725, 10.79, 2.893, 4.72 ] + }, + { + "time": 3.0333, + "value": 4.72, + "curve": [ 3.117, 4.72, 3.283, 7.93 ] + }, + { + "time": 3.3667, + "value": 7.93, + "curve": [ 3.492, 7.93, 3.775, 6.93 ] + }, + { + "time": 3.9, + "value": 6.93, + "curve": [ 3.981, 6.93, 4.094, 6.9 ] + }, + { + "time": 4.2, + "value": 8.44, + "curve": [ 4.267, 9.42, 4.401, 16.61 ] + }, + { + "time": 4.5, + "value": 16.33, + "curve": [ 4.582, 16.12, 4.709, 9.94 ] + }, + { + "time": 4.7333, + "value": 6.51, + "curve": [ 4.747, 4.57, 4.779, -1.76 ] + }, + { + "time": 4.8, + "value": -1.75, + "curve": [ 4.823, -1.73, 4.82, 4.47 ] + }, + { + "time": 4.8667, + "value": 6.04, + "curve": [ 4.899, 7.14, 4.913, 6.93 ] + }, + { "time": 4.9333, "value": 6.93 } + ] + }, + "hair2": { + "rotate": [ + { + "value": 10.61, + "curve": [ 0.075, 10.61, 0.05, 12.67 ] + }, + { + "time": 0.0667, + "value": 12.67, + "curve": [ 0.123, 12.67, 0.194, -16.51 ] + }, + { + "time": 0.2, + "value": -19.87, + "curve": [ 0.207, -23.48, 0.236, -31.68 ] + }, + { + "time": 0.3, + "value": -31.8, + "curve": [ 0.356, -31.9, 0.437, -25.61 ] + }, + { + "time": 0.4667, + "value": -19.29, + "curve": [ 0.485, -15.33, 0.529, 6.48 ] + }, + { + "time": 0.5667, + "value": 6.67, + "curve": [ 0.628, 6.97, 0.65, -46.39 ] + }, + { + "time": 0.7333, + "value": -46.3, + "curve": [ 0.843, -46.17, 0.941, -33.37 ] + }, + { + "time": 0.9667, + "value": -23.17, + "curve": [ 0.972, -20.98, 1.047, 15.21 ] + }, + { + "time": 1.1, + "value": 15.21, + "curve": [ 1.142, 15.21, 1.183, 10.73 ] + }, + { + "time": 1.2667, + "value": 10.61, + "curve": [ 1.45, 10.34, 1.817, 10.61 ] + }, + { + "time": 2, + "value": 10.61, + "curve": [ 2.075, 10.61, 2.225, 16.9 ] + }, + { + "time": 2.3, + "value": 16.9, + "curve": [ 2.327, 16.9, 2.347, 6.81 ] + }, + { + "time": 2.4, + "value": 6.83, + "curve": [ 2.492, 6.87, 2.602, 17.39 ] + }, + { + "time": 2.6667, + "value": 17.39, + "curve": [ 2.742, 17.39, 2.892, 10.67 ] + }, + { + "time": 2.9667, + "value": 10.64, + "curve": [ 3.187, 10.57, 3.344, 10.73 ] + }, + { + "time": 3.6, + "value": 11.4, + "curve": [ 3.766, 11.83, 3.874, 14.87 ] + }, + { + "time": 3.9333, + "value": 14.83, + "curve": [ 4.022, 14.76, 4.208, 9.49 ] + }, + { + "time": 4.3, + "value": 9.54, + "curve": [ 4.391, 9.58, 4.441, 14.82 ] + }, + { + "time": 4.5333, + "value": 14.84, + "curve": [ 4.642, 14.88, 4.692, 1.17 ] + }, + { + "time": 4.7667, + "value": 1.24, + "curve": [ 4.823, 1.3, 4.818, 18.35 ] + }, + { + "time": 4.8667, + "value": 18.38, + "curve": [ 4.905, 18.41, 4.901, 10.61 ] + }, + { "time": 4.9333, "value": 10.61 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.048, 0, 0.129, -12.73 ] + }, + { + "time": 0.1667, + "value": -15.95, + "curve": [ 0.221, -20.66, 0.254, -21.62 ] + }, + { + "time": 0.3, + "value": -21.59, + "curve": [ 0.458, -21.46, 0.46, -1.67 ] + }, + { + "time": 0.6333, + "value": -1.71, + "curve": [ 0.71, -1.73, 0.715, -4 ] + }, + { + "time": 0.7667, + "value": -3.97, + "curve": [ 0.866, -3.92, 0.84, 0.02 ] + }, + { "time": 1, "curve": "stepped" }, + { + "time": 2, + "curve": [ 2.275, 0, 2.867, -5.8 ] + }, + { + "time": 3.1, + "value": -6.44, + "curve": [ 3.327, -7.06, 3.71, -6.23 ] + }, + { + "time": 3.9333, + "value": -5.41, + "curve": [ 4.168, -4.53, 4.488, -2.83 ] + }, + { "time": 4.8 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.025, 0, 0.09, -3.66 ] + }, + { + "time": 0.1, + "value": -4.55, + "curve": [ 0.143, -8.4, 0.223, -17.07 ] + }, + { + "time": 0.2333, + "value": -18.31, + "curve": [ 0.282, -24.44, 0.35, -29 ] + }, + { + "time": 0.3667, + "value": -30.07, + "curve": [ 0.405, -32.58, 0.442, -33.03 ] + }, + { + "time": 0.4667, + "value": -32.99, + "curve": [ 0.491, -33.04, 0.505, -23.56 ] + }, + { + "time": 0.5333, + "value": -23.55, + "curve": [ 0.571, -23.67, 0.599, -27.21 ] + }, + { + "time": 0.6333, + "value": -27.21, + "curve": [ 0.669, -27.2, 0.742, -10.43 ] + }, + { + "time": 0.7667, + "value": -7.79, + "curve": [ 0.788, -5.53, 0.796, -4.42 ] + }, + { + "time": 0.8333, + "value": -2.9, + "curve": [ 0.875, -1.21, 0.933, 0 ] + }, + { "time": 0.9667, "curve": "stepped" }, + { + "time": 2.4333, + "curve": [ 2.517, 0, 2.683, 4.63 ] + }, + { + "time": 2.7667, + "value": 4.66, + "curve": [ 3.084, 4.76, 3.248, 4.37 ] + }, + { + "time": 3.4, + "value": 3.74, + "curve": [ 3.596, 2.92, 3.755, 2.18 ] + }, + { + "time": 3.8667, + "value": 1.72, + "curve": [ 4.136, 0.59, 4.471, 0 ] + }, + { "time": 4.8 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0, 0, 0.041, 10.74 ] + }, + { + "time": 0.0667, + "value": 14.16, + "curve": [ 0.075, 15.22, 0.148, 18.04 ] + }, + { + "time": 0.2, + "value": 18.13, + "curve": [ 0.251, 18.23, 0.307, -4.75 ] + }, + { + "time": 0.3667, + "value": -5.06, + "curve": [ 0.412, -5.3, 0.47, -0.96 ] + }, + { + "time": 0.5, + "value": 2.21, + "curve": [ 0.512, 3.48, 0.595, 20.31 ] + }, + { + "time": 0.6333, + "value": 24.87, + "curve": [ 0.647, 26.53, 0.719, 29.33 ] + }, + { + "time": 0.8, + "value": 29.22, + "curve": [ 0.859, 29.14, 0.9, 28.48 ] + }, + { + "time": 0.9333, + "value": 26.11, + "curve": [ 0.981, 22.72, 0.998, 2.06 ] + }, + { "time": 1.1, "value": 2.21 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.047, -0.21, 0.048, 7.86 ] + }, + { + "time": 0.0667, + "value": 13.27, + "curve": [ 0.083, 18.05, 0.135, 24.44 ] + }, + { + "time": 0.2, + "value": 24.02, + "curve": [ 0.225, 24.02, 0.28, 6.32 ] + }, + { + "time": 0.3, + "value": 3.1, + "curve": [ 0.323, -0.58, 0.382, -7.12 ] + }, + { + "time": 0.4667, + "value": -7.45, + "curve": [ 0.512, -7.66, 0.538, 12.13 ] + }, + { + "time": 0.5667, + "value": 16.46, + "curve": [ 0.609, 22.72, 0.672, 27.4 ] + }, + { + "time": 0.7333, + "value": 27.55, + "curve": [ 0.827, 27.4, 0.933, 23.23 ] + }, + { + "time": 0.9667, + "value": 19.11, + "curve": [ 0.998, 15.27, 1.092, -2.53 ] + }, + { + "time": 1.1333, + "value": -2.53, + "curve": [ 1.158, -2.53, 1.208, 0 ] + }, + { "time": 1.2333, "curve": "stepped" }, + { + "time": 2, + "curve": [ 2.075, 0, 2.248, 0.35 ] + }, + { + "time": 2.3333, + "value": 0.78, + "curve": [ 2.585, 2.06, 2.805, 3.46 ] + }, + { + "time": 3.2, + "value": 3.5, + "curve": [ 3.593, 3.54, 3.979, 2.36 ] + }, + { + "time": 4.1667, + "value": 1.55, + "curve": [ 4.391, 0.59, 4.447, 0.04 ] + }, + { + "time": 4.6, + "value": 0.04, + "curve": [ 4.642, 0.04, 4.742, 0 ] + }, + { "time": 4.9333 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.025, 0, 0.09, 1.43, 0.025, 0, 0.075, -34.76 ] + }, + { + "time": 0.1, + "x": 1.59, + "y": -34.76, + "curve": [ 0.214, 3.33, 0.375, 5.34, 0.192, -34.76, 0.441, -21.17 ] + }, + { + "time": 0.4667, + "x": 5.34, + "y": -12.57, + "curve": [ 0.492, 5.34, 0.55, 5.24, 0.482, -7.36, 0.504, 4.03 ] + }, + { + "time": 0.5667, + "x": 5.11, + "y": 4.01, + "curve": [ 0.658, 4.45, 0.679, 3.19, 0.649, 3.98, 0.642, -16.84 ] + }, + { + "time": 0.7, + "x": 2.8, + "y": -16.74, + "curve": [ 0.787, 1.15, 0.881, -1.29, 0.772, -16.62, 0.82, 8.95 ] + }, + { + "time": 0.9, + "x": -1.72, + "y": 8.91, + "curve": [ 0.961, -3.06, 1.025, -3.58, 0.975, 8.87, 0.951, -1.37 ] + }, + { + "time": 1.1, + "x": -3.58, + "y": -1.45, + "curve": [ 1.292, -3.58, 2.002, -2.4, 1.292, -1.56, 1.975, -1.45 ] + }, + { + "time": 2.1667, + "x": -1.39, + "y": -1.45, + "curve": [ 2.25, -0.88, 2.503, 1.38, 2.283, -1.45, 2.603, -12.44 ] + }, + { + "time": 2.6667, + "x": 2.13, + "y": -14.45, + "curve": [ 2.766, 2.59, 2.999, 2.81, 2.835, -19.73, 3.003, -25.2 ] + }, + { + "time": 3.1333, + "x": 2.91, + "y": -26.08, + "curve": [ 3.392, 3.1, 4.199, 4.05, 3.483, -28.44, 4.129, -27.23 ] + }, + { + "time": 4.3667, + "x": 4.81, + "y": -19.59, + "curve": [ 4.429, 5.1, 4.594, 8.54, 4.538, -14.08, 4.583, -7.88 ] + }, + { + "time": 4.6667, + "x": 8.65, + "y": -4.56, + "curve": [ 4.794, 8.86, 4.806, 5.93, 4.691, -3.59, 4.8, -1.61 ] + }, + { "time": 4.9333, "x": 5.8, "y": -1.99 } + ] + } + }, + "ik": { + "front-foot-ik": [ + { "mix": 0 } + ], + "front-leg-ik": [ + { "mix": 0, "bendPositive": false } + ], + "rear-foot-ik": [ + { "mix": 0.005 } + ], + "rear-leg-ik": [ + { "mix": 0.005, "bendPositive": false } + ] + } + }, + "hoverboard": { + "slots": { + "exhaust1": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "exhaust2": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "exhaust3": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "hoverboard-board": { + "attachment": [ + { "name": "hoverboard-board" } + ] + }, + "hoverboard-thruster-front": { + "attachment": [ + { "name": "hoverboard-thruster" } + ] + }, + "hoverboard-thruster-rear": { + "attachment": [ + { "name": "hoverboard-thruster" } + ] + }, + "hoverglow-front": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "hoverglow-rear": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "side-glow1": { + "attachment": [ + { "name": "hoverglow-small" }, + { "time": 0.9667, "name": null } + ] + }, + "side-glow2": { + "attachment": [ + { "time": 0.0667, "name": "hoverglow-small" }, + { "time": 1, "name": null } + ] + }, + "side-glow3": { + "attachment": [ + { "name": "hoverglow-small" }, + { "time": 0.9667, "name": null } + ] + } + }, + "bones": { + "hoverboard-controller": { + "translate": [ + { + "x": 319.55, + "y": -1.59, + "curve": [ 0.064, 319.55, 0.2, 347.85, 0.058, -1.2, 0.2, 23.11 ] + }, + { + "time": 0.2667, + "x": 347.66, + "y": 39.62, + "curve": [ 0.35, 347.41, 0.476, 341.47, 0.323, 53.58, 0.44, 85.82 ] + }, + { + "time": 0.5333, + "x": 338.47, + "y": 85.72, + "curve": [ 0.603, 334.83, 0.913, 319.65, 0.621, 85.62, 0.88, -1.53 ] + }, + { "time": 1, "x": 319.55, "y": -1.59 } + ] + }, + "hip": { + "translate": [ + { + "x": -53.49, + "y": 32.14, + "curve": [ 0.061, -53.77, 0.093, -51.81, 0.044, 16.34, 0.063, 9.67 ] + }, + { + "time": 0.1333, + "x": -49.31, + "y": 7.01, + "curve": [ 0.3, -35.27, 0.461, -20.06, 0.314, 9.52, 0.408, 121.09 ] + }, + { + "time": 0.5667, + "x": -20.06, + "y": 122.72, + "curve": [ 0.716, -20.09, 0.912, -53.29, 0.753, 121.8, 0.946, 51.85 ] + }, + { "time": 1, "x": -53.49, "y": 32.14 } + ] + }, + "exhaust1": { + "scale": [ + { + "x": 1.593, + "y": 0.964, + "curve": [ 0.033, 1.593, 0.1, 1, 0.033, 0.964, 0.1, 0.713 ] + }, + { + "time": 0.1333, + "y": 0.713, + "curve": [ 0.15, 1, 0.183, 1.774, 0.15, 0.713, 0.183, 0.883 ] + }, + { + "time": 0.2, + "x": 1.774, + "y": 0.883, + "curve": [ 0.242, 1.774, 0.325, 1.181, 0.242, 0.883, 0.325, 0.649 ] + }, + { + "time": 0.3667, + "x": 1.181, + "y": 0.649, + "curve": [ 0.408, 1.181, 0.492, 1.893, 0.408, 0.649, 0.492, 0.819 ] + }, + { + "time": 0.5333, + "x": 1.893, + "y": 0.819, + "curve": [ 0.558, 1.893, 0.608, 1.18, 0.558, 0.819, 0.608, 0.686 ] + }, + { + "time": 0.6333, + "x": 1.18, + "y": 0.686, + "curve": [ 0.658, 1.18, 0.708, 1.903, 0.658, 0.686, 0.708, 0.855 ] + }, + { + "time": 0.7333, + "x": 1.903, + "y": 0.855, + "curve": [ 0.767, 1.903, 0.833, 1.311, 0.767, 0.855, 0.833, 0.622 ] + }, + { + "time": 0.8667, + "x": 1.311, + "y": 0.622, + "curve": [ 0.9, 1.311, 0.967, 1.593, 0.9, 0.622, 0.967, 0.964 ] + }, + { "time": 1, "x": 1.593, "y": 0.964 } + ] + }, + "exhaust2": { + "scale": [ + { + "x": 1.88, + "y": 0.832, + "curve": [ 0.025, 1.88, 0.075, 1.311, 0.025, 0.832, 0.075, 0.686 ] + }, + { + "time": 0.1, + "x": 1.311, + "y": 0.686, + "curve": [ 0.133, 1.311, 0.2, 2.01, 0.133, 0.686, 0.208, 0.736 ] + }, + { + "time": 0.2333, + "x": 2.01, + "y": 0.769, + "curve": [ 0.267, 2.01, 0.333, 1, 0.282, 0.831, 0.333, 0.91 ] + }, + { + "time": 0.3667, + "y": 0.91, + "curve": [ 0.4, 1, 0.467, 1.699, 0.4, 0.91, 0.474, 0.891 ] + }, + { + "time": 0.5, + "x": 1.699, + "y": 0.86, + "curve": [ 0.517, 1.699, 0.55, 1.181, 0.54, 0.813, 0.55, 0.713 ] + }, + { + "time": 0.5667, + "x": 1.181, + "y": 0.713, + "curve": [ 0.617, 1.181, 0.717, 1.881, 0.617, 0.713, 0.717, 0.796 ] + }, + { + "time": 0.7667, + "x": 1.881, + "y": 0.796, + "curve": [ 0.8, 1.881, 0.867, 1.3, 0.8, 0.796, 0.867, 0.649 ] + }, + { + "time": 0.9, + "x": 1.3, + "y": 0.649, + "curve": [ 0.925, 1.3, 0.975, 1.88, 0.925, 0.649, 0.975, 0.832 ] + }, + { "time": 1, "x": 1.88, "y": 0.832 } + ] + }, + "hoverboard-thruster-front": { + "rotate": [ + { + "curve": [ 0.125, 0, 0.375, 24.06 ] + }, + { + "time": 0.5, + "value": 24.06, + "curve": [ 0.625, 24.06, 0.875, 0 ] + }, + { "time": 1 } + ] + }, + "hoverglow-front": { + "scale": [ + { + "x": 0.849, + "y": 1.764, + "curve": [ 0.017, 0.849, 0.05, 0.835, 0.017, 1.764, 0.05, 2.033 ] + }, + { + "time": 0.0667, + "x": 0.835, + "y": 2.033, + "curve": [ 0.092, 0.835, 0.142, 0.752, 0.092, 2.033, 0.142, 1.584 ] + }, + { + "time": 0.1667, + "x": 0.752, + "y": 1.584, + "curve": [ 0.183, 0.752, 0.217, 0.809, 0.183, 1.584, 0.217, 1.71 ] + }, + { + "time": 0.2333, + "x": 0.809, + "y": 1.71, + "curve": [ 0.25, 0.809, 0.283, 0.717, 0.25, 1.71, 0.283, 1.45 ] + }, + { + "time": 0.3, + "x": 0.717, + "y": 1.45, + "curve": [ 0.317, 0.717, 0.35, 0.777, 0.317, 1.45, 0.35, 1.698 ] + }, + { + "time": 0.3667, + "x": 0.777, + "y": 1.698, + "curve": [ 0.4, 0.781, 0.45, 0.685, 0.375, 1.698, 0.45, 1.173 ] + }, + { + "time": 0.4667, + "x": 0.685, + "y": 1.173, + "curve": [ 0.492, 0.685, 0.542, 0.825, 0.492, 1.173, 0.542, 1.572 ] + }, + { + "time": 0.5667, + "x": 0.825, + "y": 1.572, + "curve": [ 0.611, 0.816, 0.63, 0.727, 0.611, 1.577, 0.606, 1.255 ] + }, + { + "time": 0.6667, + "x": 0.725, + "y": 1.241, + "curve": [ 0.692, 0.725, 0.742, 0.895, 0.692, 1.241, 0.749, 1.799 ] + }, + { + "time": 0.7667, + "x": 0.895, + "y": 1.857, + "curve": [ 0.783, 0.895, 0.796, 0.892, 0.796, 1.955, 0.817, 1.962 ] + }, + { + "time": 0.8333, + "x": 0.845, + "y": 1.962, + "curve": [ 0.845, 0.831, 0.883, 0.802, 0.85, 1.962, 0.872, 1.704 ] + }, + { + "time": 0.9, + "x": 0.802, + "y": 1.491, + "curve": [ 0.917, 0.802, 0.95, 0.845, 0.907, 1.441, 0.936, 1.508 ] + }, + { + "time": 0.9667, + "x": 0.845, + "y": 1.627, + "curve": [ 0.975, 0.845, 0.992, 0.849, 0.973, 1.652, 0.992, 1.764 ] + }, + { "time": 1, "x": 0.849, "y": 1.764 } + ] + }, + "hoverboard-thruster-rear": { + "rotate": [ + { + "curve": [ 0.125, 0, 0.375, 24.06 ] + }, + { + "time": 0.5, + "value": 24.06, + "curve": [ 0.625, 24.06, 0.875, 0 ] + }, + { "time": 1 } + ] + }, + "hoverglow-rear": { + "scale": [ + { + "x": 0.845, + "y": 1.31, + "curve": [ 0.017, 0.845, 0.117, 0.899, 0.017, 1.31, 0.117, 2.033 ] + }, + { + "time": 0.1333, + "x": 0.899, + "y": 2.033, + "curve": [ 0.15, 0.899, 0.183, 0.752, 0.15, 2.033, 0.183, 1.574 ] + }, + { + "time": 0.2, + "x": 0.752, + "y": 1.574, + "curve": [ 0.225, 0.752, 0.275, 0.809, 0.225, 1.574, 0.275, 1.71 ] + }, + { + "time": 0.3, + "x": 0.809, + "y": 1.71, + "curve": [ 0.317, 0.809, 0.35, 0.717, 0.317, 1.71, 0.35, 1.397 ] + }, + { + "time": 0.3667, + "x": 0.717, + "y": 1.397, + "curve": [ 0.383, 0.717, 0.417, 0.777, 0.383, 1.397, 0.417, 1.45 ] + }, + { + "time": 0.4333, + "x": 0.777, + "y": 1.45, + "curve": [ 0.45, 0.777, 0.496, 0.689, 0.45, 1.45, 0.481, 1.168 ] + }, + { + "time": 0.5333, + "x": 0.685, + "y": 1.173, + "curve": [ 0.565, 0.682, 0.617, 0.758, 0.575, 1.177, 0.617, 1.297 ] + }, + { + "time": 0.6333, + "x": 0.758, + "y": 1.297, + "curve": [ 0.658, 0.758, 0.708, 0.725, 0.658, 1.297, 0.708, 1.241 ] + }, + { + "time": 0.7333, + "x": 0.725, + "y": 1.241, + "curve": [ 0.772, 0.732, 0.796, 0.893, 0.782, 1.238, 0.778, 1.854 ] + }, + { + "time": 0.8333, + "x": 0.895, + "y": 1.857, + "curve": [ 0.878, 0.9, 0.992, 0.845, 0.88, 1.86, 0.992, 1.31 ] + }, + { "time": 1, "x": 0.845, "y": 1.31 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -85.92, + "curve": [ 0.08, -85.59, 0.284, -62.7 ] + }, + { + "time": 0.3667, + "value": -55.14, + "curve": [ 0.438, -48.65, 0.551, -43.21 ] + }, + { + "time": 0.6333, + "value": -43.21, + "curve": [ 0.716, -43.22, 0.908, -85.92 ] + }, + { "time": 1, "value": -85.92 } + ], + "translate": [ + { + "x": -0.59, + "y": -2.94, + "curve": [ 0.1, -1.21, 0.275, -1.74, 0.092, -2.94, 0.275, -6.39 ] + }, + { + "time": 0.3667, + "x": -1.74, + "y": -6.39, + "curve": [ 0.433, -1.74, 0.567, 0.72, 0.433, -6.39, 0.587, -4.48 ] + }, + { + "time": 0.6333, + "x": 0.72, + "y": -4.21, + "curve": [ 0.725, 0.72, 0.908, -0.08, 0.743, -3.57, 0.908, -2.94 ] + }, + { "time": 1, "x": -0.59, "y": -2.94 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": 7.61, + "curve": [ 0.143, 7.62, 0.247, -23.17 ] + }, + { + "time": 0.2667, + "value": -26.56, + "curve": [ 0.281, -29.08, 0.351, -37.36 ] + }, + { + "time": 0.4333, + "value": -37.2, + "curve": [ 0.513, -37.05, 0.562, -29.88 ] + }, + { + "time": 0.6, + "value": -25.18, + "curve": [ 0.621, -22.58, 0.694, -3.98 ] + }, + { + "time": 0.8, + "value": 3.63, + "curve": [ 0.861, 8.03, 0.946, 7.57 ] + }, + { "time": 1, "value": 7.61 } + ], + "translate": [ + { + "curve": [ 0.117, 0, 0.35, 0.52, 0.117, 0, 0.35, -3.27 ] + }, + { + "time": 0.4667, + "x": 0.52, + "y": -3.27, + "curve": [ 0.6, 0.52, 0.867, 0, 0.6, -3.27, 0.867, 0 ] + }, + { "time": 1 } + ], + "shear": [ + { + "y": 19.83, + "curve": [ 0.117, 0, 0.35, 15.28, 0.117, 19.83, 0.35, 28.31 ] + }, + { + "time": 0.4667, + "x": 15.28, + "y": 28.31, + "curve": [ 0.6, 15.28, 0.867, 0, 0.6, 28.31, 0.867, 19.83 ] + }, + { "time": 1, "y": 19.83 } + ] + }, + "board-ik": { + "translate": [ + { + "x": 393.62, + "curve": [ 0.083, 393.62, 0.25, 393.48, 0.083, 0, 0.25, 117.69 ] + }, + { + "time": 0.3333, + "x": 393.48, + "y": 117.69, + "curve": [ 0.375, 393.48, 0.458, 393.62, 0.375, 117.69, 0.458, 83.82 ] + }, + { "time": 0.5, "x": 393.62, "y": 83.82 }, + { "time": 0.6667, "x": 393.62, "y": 30.15 }, + { "time": 1, "x": 393.62 } + ] + }, + "front-thigh": { + "translate": [ + { "x": -7.49, "y": 8.51 } + ] + }, + "front-leg-target": { + "translate": [ + { + "time": 0.3667, + "curve": [ 0.428, 10.83, 0.567, 12.78, 0.414, 7.29, 0.567, 8.79 ] + }, + { + "time": 0.6, + "x": 12.78, + "y": 8.79, + "curve": [ 0.692, 12.78, 0.772, 11.27, 0.692, 8.79, 0.766, 8.62 ] + }, + { "time": 0.8667 } + ] + }, + "rear-leg-target": { + "translate": [ + { + "time": 0.4667, + "curve": [ 0.492, 0, 0.534, 4.47, 0.492, 0, 0.542, 1.63 ] + }, + { + "time": 0.5667, + "x": 4.53, + "y": 1.77, + "curve": [ 0.622, 4.64, 0.717, 3.31, 0.615, 2.06, 0.71, 2.1 ] + }, + { "time": 0.8 } + ] + }, + "exhaust3": { + "scale": [ + { + "x": 1.882, + "y": 0.81, + "curve": [ 0.017, 1.882, 0.167, 1.3, 0.017, 0.81, 0.167, 0.649 ] + }, + { + "time": 0.2, + "x": 1.3, + "y": 0.649, + "curve": [ 0.225, 1.3, 0.275, 2.051, 0.225, 0.649, 0.275, 0.984 ] + }, + { + "time": 0.3, + "x": 2.051, + "y": 0.984, + "curve": [ 0.325, 2.051, 0.375, 1.311, 0.325, 0.984, 0.384, 0.715 ] + }, + { + "time": 0.4, + "x": 1.311, + "y": 0.686, + "curve": [ 0.433, 1.311, 0.5, 1.86, 0.426, 0.638, 0.5, 0.537 ] + }, + { + "time": 0.5333, + "x": 1.86, + "y": 0.537, + "curve": [ 0.567, 1.86, 0.633, 1.187, 0.567, 0.537, 0.604, 0.854 ] + }, + { + "time": 0.6667, + "x": 1.187, + "y": 0.854, + "curve": [ 0.7, 1.187, 0.767, 1.549, 0.707, 0.854, 0.774, 0.775 ] + }, + { + "time": 0.8, + "x": 1.549, + "y": 0.746, + "curve": [ 0.817, 1.549, 0.85, 1.181, 0.815, 0.729, 0.85, 0.713 ] + }, + { + "time": 0.8667, + "x": 1.181, + "y": 0.713, + "curve": [ 0.9, 1.181, 0.967, 1.882, 0.9, 0.713, 0.967, 0.81 ] + }, + { "time": 1, "x": 1.882, "y": 0.81 } + ] + }, + "side-glow1": { + "rotate": [ + { "value": 51.12, "curve": "stepped" }, + { "time": 0.0667, "value": 43.82, "curve": "stepped" }, + { "time": 0.1, "value": 40.95, "curve": "stepped" }, + { "time": 0.1667, "value": 27.78, "curve": "stepped" }, + { "time": 0.2, "value": 10.24, "curve": "stepped" }, + { "time": 0.2667, "curve": "stepped" }, + { "time": 0.8, "value": -25.81 } + ], + "translate": [ + { "x": 338.28, "y": 40.22, "curve": "stepped" }, + { "time": 0.0667, "x": 331.2, "y": 30.39, "curve": "stepped" }, + { "time": 0.1, "x": 318.63, "y": 20.59, "curve": "stepped" }, + { "time": 0.1667, "x": 302.45, "y": 9.64, "curve": "stepped" }, + { "time": 0.2, "x": 276.87, "y": 1.13, "curve": "stepped" }, + { "time": 0.2667, "x": 248.16, "curve": "stepped" }, + { "time": 0.3, "x": 221.36, "curve": "stepped" }, + { "time": 0.3667, "x": 195.69, "curve": "stepped" }, + { "time": 0.4, "x": 171.08, "curve": "stepped" }, + { "time": 0.4667, "x": 144.84, "curve": "stepped" }, + { "time": 0.5, "x": 121.22, "curve": "stepped" }, + { "time": 0.5667, "x": 91.98, "curve": "stepped" }, + { "time": 0.6, "x": 62.63, "curve": "stepped" }, + { "time": 0.6667, "x": 30.78, "curve": "stepped" }, + { "time": 0.7, "curve": "stepped" }, + { "time": 0.7667, "x": -28.45, "curve": "stepped" }, + { "time": 0.8, "x": -67.49, "y": 16.82, "curve": "stepped" }, + { "time": 0.8667, "x": -83.07, "y": 24.36, "curve": "stepped" }, + { "time": 0.9, "x": -93.81, "y": 29.55 } + ], + "scale": [ + { "x": 0.535, "curve": "stepped" }, + { "time": 0.0667, "x": 0.594, "curve": "stepped" }, + { "time": 0.1, "x": 0.844, "curve": "stepped" }, + { "time": 0.1667, "curve": "stepped" }, + { "time": 0.8, "x": 0.534, "curve": "stepped" }, + { "time": 0.8667, "x": 0.428, "y": 0.801, "curve": "stepped" }, + { "time": 0.9, "x": 0.349, "y": 0.654 } + ] + }, + "side-glow2": { + "rotate": [ + { "time": 0.0667, "value": 51.12, "curve": "stepped" }, + { "time": 0.1, "value": 43.82, "curve": "stepped" }, + { "time": 0.1667, "value": 40.95, "curve": "stepped" }, + { "time": 0.2, "value": 27.78, "curve": "stepped" }, + { "time": 0.2667, "value": 10.24, "curve": "stepped" }, + { "time": 0.3, "curve": "stepped" }, + { "time": 0.8667, "value": -25.81 } + ], + "translate": [ + { "time": 0.0667, "x": 338.28, "y": 40.22, "curve": "stepped" }, + { "time": 0.1, "x": 331.2, "y": 30.39, "curve": "stepped" }, + { "time": 0.1667, "x": 318.63, "y": 20.59, "curve": "stepped" }, + { "time": 0.2, "x": 302.45, "y": 9.64, "curve": "stepped" }, + { "time": 0.2667, "x": 276.87, "y": 1.13, "curve": "stepped" }, + { "time": 0.3, "x": 248.16, "curve": "stepped" }, + { "time": 0.3667, "x": 221.36, "curve": "stepped" }, + { "time": 0.4, "x": 195.69, "curve": "stepped" }, + { "time": 0.4667, "x": 171.08, "curve": "stepped" }, + { "time": 0.5, "x": 144.84, "curve": "stepped" }, + { "time": 0.5667, "x": 121.22, "curve": "stepped" }, + { "time": 0.6, "x": 91.98, "curve": "stepped" }, + { "time": 0.6667, "x": 62.63, "curve": "stepped" }, + { "time": 0.7, "x": 30.78, "curve": "stepped" }, + { "time": 0.7667, "curve": "stepped" }, + { "time": 0.8, "x": -28.45, "curve": "stepped" }, + { "time": 0.8667, "x": -67.49, "y": 16.82, "curve": "stepped" }, + { "time": 0.9, "x": -83.07, "y": 24.36, "curve": "stepped" }, + { "time": 0.9667, "x": -93.81, "y": 29.55 } + ], + "scale": [ + { "time": 0.0667, "x": 0.535, "curve": "stepped" }, + { "time": 0.1, "x": 0.594, "curve": "stepped" }, + { "time": 0.1667, "x": 0.844, "curve": "stepped" }, + { "time": 0.2, "curve": "stepped" }, + { "time": 0.8667, "x": 0.534, "curve": "stepped" }, + { "time": 0.9, "x": 0.428, "y": 0.801, "curve": "stepped" }, + { "time": 0.9667, "x": 0.349, "y": 0.654 } + ] + }, + "torso": { + "rotate": [ + { + "value": -34.73, + "curve": [ 0.034, -36.31, 0.162, -39.33 ] + }, + { + "time": 0.2667, + "value": -39.37, + "curve": [ 0.384, -39.37, 0.491, -29.52 ] + }, + { + "time": 0.5, + "value": -28.86, + "curve": [ 0.525, -26.95, 0.571, -21.01 ] + }, + { + "time": 0.6333, + "value": -21.01, + "curve": [ 0.725, -21.01, 0.969, -33.35 ] + }, + { "time": 1, "value": -34.73 } + ] + }, + "neck": { + "rotate": [ + { + "value": 10.2, + "curve": [ 0.07, 12.09, 0.189, 16.03 ] + }, + { + "time": 0.2667, + "value": 16.14, + "curve": [ 0.333, 16.14, 0.449, 8.03 ] + }, + { + "time": 0.5, + "value": 5.83, + "curve": [ 0.542, 4.02, 0.6, 2.68 ] + }, + { + "time": 0.6333, + "value": 2.68, + "curve": [ 0.725, 2.68, 0.943, 8.57 ] + }, + { "time": 1, "value": 10.2 } + ] + }, + "head": { + "rotate": [ + { + "value": 10.2, + "curve": [ 0.044, 11.52, 0.2, 16.12 ] + }, + { + "time": 0.2667, + "value": 16.14, + "curve": [ 0.375, 16.17, 0.492, 2.65 ] + }, + { + "time": 0.6333, + "value": 2.68, + "curve": [ 0.725, 2.7, 0.963, 9.26 ] + }, + { "time": 1, "value": 10.2 } + ], + "translate": [ + { + "curve": [ 0.03, -0.24, 0.2, -4.22, 0.051, -1.06, 0.2, -3.62 ] + }, + { + "time": 0.2667, + "x": -4.22, + "y": -3.62, + "curve": [ 0.358, -4.22, 0.542, 0.84, 0.358, -3.62, 0.542, 6.01 ] + }, + { + "time": 0.6333, + "x": 0.84, + "y": 6.01, + "curve": [ 0.725, 0.84, 0.939, 0.32, 0.725, 6.01, 0.945, 1.14 ] + }, + { "time": 1 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": -11.18, + "curve": [ 0.064, -14.82, 0.25, -20.01 ] + }, + { + "time": 0.3333, + "value": -20.01, + "curve": [ 0.429, -20.12, 0.58, 5.12 ] + }, + { + "time": 0.6, + "value": 8.67, + "curve": [ 0.617, 11.72, 0.687, 20.52 ] + }, + { + "time": 0.7667, + "value": 20.55, + "curve": [ 0.848, 20.7, 0.963, -9.43 ] + }, + { "time": 1, "value": -11.18 } + ] + }, + "hair3": { + "rotate": [ + { + "value": 9.61, + "curve": [ 0.014, 8.51, 0.075, 2.63 ] + }, + { + "time": 0.1, + "value": 2.63, + "curve": [ 0.15, 2.63, 0.25, 13.52 ] + }, + { + "time": 0.3, + "value": 13.52, + "curve": [ 0.35, 13.52, 0.45, 11.28 ] + }, + { + "time": 0.5, + "value": 11.28, + "curve": [ 0.575, 11.28, 0.725, 18.13 ] + }, + { + "time": 0.8, + "value": 18.13, + "curve": [ 0.85, 18.13, 0.978, 11.07 ] + }, + { "time": 1, "value": 9.61 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -17.7, + "curve": [ 0.008, -17.7, 0.025, -23.73 ] + }, + { + "time": 0.0333, + "value": -23.73, + "curve": [ 0.067, -23.73, 0.154, -4.4 ] + }, + { + "time": 0.1667, + "value": -1.92, + "curve": [ 0.197, 4.09, 0.236, 12.91 ] + }, + { + "time": 0.2667, + "value": 17.56, + "curve": [ 0.301, 22.68, 0.342, 27.97 ] + }, + { + "time": 0.3667, + "value": 27.97, + "curve": [ 0.4, 27.97, 0.467, -1.45 ] + }, + { + "time": 0.5, + "value": -1.45, + "curve": [ 0.517, -1.45, 0.55, 3.16 ] + }, + { + "time": 0.5667, + "value": 3.16, + "curve": [ 0.583, 3.16, 0.617, -8.9 ] + }, + { + "time": 0.6333, + "value": -8.9, + "curve": [ 0.642, -8.9, 0.658, -5.4 ] + }, + { + "time": 0.6667, + "value": -5.4, + "curve": [ 0.683, -5.4, 0.717, -15.32 ] + }, + { + "time": 0.7333, + "value": -15.32, + "curve": [ 0.75, -15.32, 0.783, -9.19 ] + }, + { + "time": 0.8, + "value": -9.19, + "curve": [ 0.817, -9.19, 0.85, -23.6 ] + }, + { + "time": 0.8667, + "value": -23.6, + "curve": [ 0.883, -23.6, 0.917, -17.38 ] + }, + { + "time": 0.9333, + "value": -17.38, + "curve": [ 0.942, -17.38, 0.958, -20.46 ] + }, + { + "time": 0.9667, + "value": -20.46, + "curve": [ 0.975, -20.46, 0.992, -17.7 ] + }, + { "time": 1, "value": -17.7 } + ] + }, + "hair1": { + "rotate": [ + { + "value": 9.61, + "curve": [ 0.06, 9.04, 0.25, 8.9 ] + }, + { + "time": 0.3333, + "value": 8.9, + "curve": [ 0.392, 8.9, 0.508, 14.58 ] + }, + { + "time": 0.5667, + "value": 14.58, + "curve": [ 0.675, 14.58, 0.956, 10.28 ] + }, + { "time": 1, "value": 9.61 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -3.82, + "curve": [ 0.017, -3.82, 0.064, -9.16 ] + }, + { + "time": 0.1333, + "value": -9.09, + "curve": [ 0.178, -9.04, 0.234, 1.29 ] + }, + { + "time": 0.2667, + "value": 5.98, + "curve": [ 0.276, 7.27, 0.336, 17.1 ] + }, + { + "time": 0.3667, + "value": 17.1, + "curve": [ 0.413, 17.1, 0.467, 1.59 ] + }, + { + "time": 0.5, + "value": 1.59, + "curve": [ 0.533, 1.59, 0.567, 13.63 ] + }, + { + "time": 0.6, + "value": 13.63, + "curve": [ 0.617, 13.63, 0.683, 0.78 ] + }, + { + "time": 0.7, + "value": 0.78, + "curve": [ 0.717, 0.78, 0.75, 12.01 ] + }, + { + "time": 0.7667, + "value": 11.9, + "curve": [ 0.792, 11.73, 0.817, -0.85 ] + }, + { + "time": 0.8333, + "value": -0.85, + "curve": [ 0.85, -0.85, 0.88, 1.99 ] + }, + { + "time": 0.9, + "value": 1.82, + "curve": [ 0.916, 1.68, 0.95, -6.9 ] + }, + { + "time": 0.9667, + "value": -6.9, + "curve": [ 0.975, -6.9, 0.992, -3.82 ] + }, + { "time": 1, "value": -3.82 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 31.65, + "curve": [ 0.108, 31.65, 0.325, 13.01 ] + }, + { + "time": 0.4333, + "value": 13.01, + "curve": [ 0.71, 13.01, 0.917, 31.65 ] + }, + { "time": 1, "value": 31.65 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 31, + "curve": [ 0.108, 31, 0.325, 12.76 ] + }, + { + "time": 0.4333, + "value": 12.79, + "curve": [ 0.587, 12.82, 0.917, 31 ] + }, + { "time": 1, "value": 31 } + ] + }, + "gun": { + "rotate": [ + { + "value": 1.95, + "curve": [ 0.083, 1.95, 0.245, 36.73 ] + }, + { + "time": 0.3333, + "value": 36.71, + "curve": [ 0.439, 36.69, 0.589, 10.68 ] + }, + { + "time": 0.6333, + "value": 8.75, + "curve": [ 0.701, 5.81, 0.917, 1.95 ] + }, + { "time": 1, "value": 1.95 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 2.35 ] + }, + { + "time": 0.1333, + "value": 2.35, + "curve": [ 0.225, 2.35, 0.408, -2.4 ] + }, + { + "time": 0.5, + "value": -2.4, + "curve": [ 0.567, -2.4, 0.7, 1.44 ] + }, + { + "time": 0.7667, + "value": 1.44, + "curve": [ 0.825, 1.44, 0.942, 0 ] + }, + { "time": 1 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.063, 0.77, 0.106, 1.42 ] + }, + { + "time": 0.1667, + "value": 1.42, + "curve": [ 0.259, 1.42, 0.344, -1.25 ] + }, + { + "time": 0.4667, + "value": -1.26, + "curve": [ 0.656, -1.26, 0.917, -0.78 ] + }, + { "time": 1 } + ] + }, + "head-control": { + "translate": [ + { + "x": 0.37, + "y": -11.17, + "curve": [ 0.133, 0.37, 0.335, -10.23, 0.133, -11.17, 0.335, 3.15 ] + }, + { + "time": 0.5333, + "x": -10.23, + "y": 3.15, + "curve": [ 0.71, -10.23, 0.883, 0.37, 0.71, 3.15, 0.883, -11.17 ] + }, + { "time": 1, "x": 0.37, "y": -11.17 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.46, + "y": 10.15, + "curve": [ 0.103, 1.46, 0.249, 1.36, 0.103, 10.15, 0.249, -4.39 ] + }, + { + "time": 0.4, + "x": 1.36, + "y": -4.39, + "curve": [ 0.621, 1.36, 0.85, 1.46, 0.621, -4.39, 0.85, 10.15 ] + }, + { "time": 1, "x": 1.46, "y": 10.15 } + ] + }, + "back-shoulder": { + "translate": [ + { + "x": 1.4, + "y": 0.44, + "curve": [ 0.088, 1.4, 0.208, -2.47, 0.088, 0.44, 0.208, 8.61 ] + }, + { + "time": 0.3333, + "x": -2.47, + "y": 8.61, + "curve": [ 0.572, -2.47, 0.833, 1.4, 0.572, 8.61, 0.833, 0.44 ] + }, + { "time": 1, "x": 1.4, "y": 0.44 } + ] + } + }, + "transform": { + "front-foot-board-transform": [ + { "mixRotate": 0.997 } + ], + "rear-foot-board-transform": [ + {} + ], + "toes-board": [ + { "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ] + }, + "deform": { + "default": { + "front-foot": { + "front-foot": [ + { + "offset": 26, + "vertices": [ -0.02832, -5.37024, -0.02832, -5.37024, 3.8188, -3.7757, -0.02832, -5.37024, -3.82159, 3.77847 ] + } + ] + }, + "front-shin": { + "front-shin": [ + { + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + }, + { + "time": 0.3667, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -11.66571, -9.07211, -25.65866, -17.53735, -25.53217, -16.50978, -11.78232, -11.26097, 0, 0, 0.60487, -1.63589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0, 0, -2.64522, -7.35739, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0.60487, -1.63589, 0.60487, -1.63589, 0.60487, -1.63589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0, 0, -10.06873, -12.0999 ] + }, + { + "time": 0.5333, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -7.00775, -8.24771, -6.45482, -6.49312, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + }, + { + "time": 1, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + } + ] + }, + "hoverboard-board": { + "hoverboard-board": [ + { + "curve": [ 0.067, 0, 0.2, 1 ] + }, + { + "time": 0.2667, + "offset": 1, + "vertices": [ 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 3.55673, -3.0E-4, 3.55673, -3.0E-4, 0, 0, 0, 0, 0, 0, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, 0, 0, 0, 0, 0, 0, 0, 0, -4.90558, 0.11214, -9.40706, 6.2E-4, -6.34871, 4.3E-4, -6.34925, -6.57018, -6.34925, -6.57018, -6.34871, 4.3E-4, -2.3308, 1.7E-4, -2.33133, -6.57045, -2.33133, -6.57045, -2.3308, 1.7E-4, 0, 0, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 3.3297, 4.44005, 3.3297, 4.44005, 3.3297, 4.44005, 1.2E-4, 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, 1.2E-4, 2.45856, 1.2E-4, 2.45856, -9.40694, 2.45918, 1.88063, 0.44197, -2.9E-4, -3.54808, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.46227, 1.7E-4, 0, 0, 0, 0, 1.2E-4, 2.45856 ], + "curve": [ 0.45, 0, 0.817, 1 ] + }, + { "time": 1 } + ] + }, + "rear-foot": { + "rear-foot": [ + { + "offset": 28, + "vertices": [ -1.93078, 1.34782, -0.31417, 2.33363, 3.05122, 0.33946, 2.31472, -2.01678, 2.17583, -2.05795, -0.04277, -2.99459, 1.15429, 0.26328, 0.97501, -0.67169 ] + } + ] + } + } + } + }, + "idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-foot-target": { + "translate": [ + { "x": -69.06 } + ] + }, + "hip": { + "rotate": [ + { + "curve": [ 0.073, 0.35, 0.303, 1.27 ] + }, + { + "time": 0.4, + "value": 1.28, + "curve": [ 0.615, 1.3, 0.847, -1.41 ] + }, + { + "time": 1.2, + "value": -1.38, + "curve": [ 1.344, -1.37, 1.602, -0.28 ] + }, + { "time": 1.6667 } + ], + "translate": [ + { + "x": -11.97, + "y": -23.15, + "curve": [ 0.059, -12.96, 0.258, -15.19, 0.142, -23.15, 0.341, -24.89 ] + }, + { + "time": 0.4667, + "x": -15.14, + "y": -26.74, + "curve": [ 0.62, -15.1, 0.788, -13.28, 0.597, -28.66, 0.75, -30.01 ] + }, + { + "time": 0.9, + "x": -12.02, + "y": -30.01, + "curve": [ 0.978, -11.13, 1.175, -9.05, 1.036, -29.94, 1.234, -28.08 ] + }, + { + "time": 1.3333, + "x": -9.06, + "y": -26.64, + "curve": [ 1.501, -9.06, 1.614, -10.95, 1.454, -24.89, 1.609, -23.15 ] + }, + { "time": 1.6667, "x": -11.97, "y": -23.15 } + ] + }, + "rear-foot-target": { + "translate": [ + { "x": 48.87 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -60.87, + "curve": [ 0.154, -60.85, 0.452, -68.65 ] + }, + { + "time": 0.8333, + "value": -68.65, + "curve": [ 1.221, -68.65, 1.542, -60.87 ] + }, + { "time": 1.6667, "value": -60.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 42.46, + "curve": [ 0.029, 42.97, 0.134, 45.28 ] + }, + { + "time": 0.3333, + "value": 45.27, + "curve": [ 0.578, 45.26, 0.798, 40.07 ] + }, + { + "time": 0.8333, + "value": 39.74, + "curve": [ 0.878, 39.32, 1.019, 38.23 ] + }, + { + "time": 1.2, + "value": 38.22, + "curve": [ 1.377, 38.22, 1.619, 41.68 ] + }, + { "time": 1.6667, "value": 42.46 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 39.2, + "curve": [ 0.185, 39.22, 0.5, 29.37 ] + }, + { + "time": 0.6667, + "value": 29.37, + "curve": [ 0.917, 29.37, 1.417, 39.2 ] + }, + { "time": 1.6667, "value": 39.2 } + ] + }, + "head": { + "rotate": [ + { + "value": -6.75, + "curve": [ 0.176, -7.88, 0.349, -8.95 ] + }, + { + "time": 0.4667, + "value": -8.95, + "curve": [ 0.55, -8.95, 0.697, -6.77 ] + }, + { + "time": 0.8333, + "value": -5.44, + "curve": [ 0.88, -4.98, 1.05, -4.12 ] + }, + { + "time": 1.1333, + "value": -4.12, + "curve": [ 1.266, -4.12, 1.469, -5.48 ] + }, + { "time": 1.6667, "value": -6.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "curve": [ 0.086, 0, 0.233, 2.48 ] + }, + { + "time": 0.3333, + "value": 4.13, + "curve": [ 0.429, 5.7, 0.711, 10.06 ] + }, + { + "time": 0.8333, + "value": 10.06, + "curve": [ 0.926, 10.06, 1.092, 4.21 ] + }, + { + "time": 1.2, + "value": 2.78, + "curve": [ 1.349, 0.8, 1.551, 0 ] + }, + { "time": 1.6667 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "curve": [ 0.063, 0.54, 0.367, 3.39 ] + }, + { + "time": 0.5333, + "value": 3.39, + "curve": [ 0.696, 3.39, 0.939, -1.63 ] + }, + { + "time": 1.2, + "value": -1.61, + "curve": [ 1.42, -1.59, 1.574, -0.67 ] + }, + { "time": 1.6667 } + ] + }, + "gun": { + "rotate": [ + { + "curve": [ 0.099, 0.27, 0.367, 1.23 ] + }, + { + "time": 0.5333, + "value": 1.23, + "curve": [ 0.665, 1.23, 0.937, -0.56 ] + }, + { + "time": 1.1333, + "value": -0.55, + "curve": [ 1.316, -0.55, 1.582, -0.21 ] + }, + { "time": 1.6667 } + ] + }, + "torso": { + "rotate": [ + { + "value": -22.88, + "curve": [ 0.099, -23.45, 0.363, -24.74 ] + }, + { + "time": 0.5333, + "value": -24.74, + "curve": [ 0.706, -24.74, 0.961, -20.97 ] + }, + { + "time": 1.1333, + "value": -20.97, + "curve": [ 1.355, -20.97, 1.567, -22.28 ] + }, + { "time": 1.6667, "value": -22.88 } + ] + }, + "neck": { + "rotate": [ + { + "value": 3.78, + "curve": [ 0.167, 3.78, 0.5, 5.45 ] + }, + { + "time": 0.6667, + "value": 5.45, + "curve": [ 0.917, 5.45, 1.417, 3.78 ] + }, + { "time": 1.6667, "value": 3.78 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.067, 0.33, 0.341, 2.54 ] + }, + { + "time": 0.5333, + "value": 2.54, + "curve": [ 0.734, 2.55, 0.982, -0.94 ] + }, + { + "time": 1.1333, + "value": -0.93, + "curve": [ 1.365, -0.91, 1.549, -0.56 ] + }, + { "time": 1.6667 } + ] + }, + "torso3": { + "rotate": [ + { + "value": -2.15, + "curve": [ 0.052, -1.9, 0.384, -0.15 ] + }, + { + "time": 0.5333, + "value": -0.14, + "curve": [ 0.762, -0.13, 0.895, -3.1 ] + }, + { + "time": 1.1333, + "value": -3.1, + "curve": [ 1.348, -3.1, 1.592, -2.46 ] + }, + { "time": 1.6667, "value": -2.15 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.067, 0, 0.213, 2.86 ] + }, + { + "time": 0.2667, + "value": 3.65, + "curve": [ 0.358, 4.99, 0.535, 7.92 ] + }, + { + "time": 0.6667, + "value": 7.92, + "curve": [ 0.809, 7.92, 1.067, 5.49 ] + }, + { + "time": 1.1333, + "value": 4.7, + "curve": [ 1.245, 3.34, 1.525, 0 ] + }, + { "time": 1.6667 } + ] + }, + "hair2": { + "rotate": [ + { + "curve": [ 0.067, 0, 0.225, -7.97 ] + }, + { + "time": 0.2667, + "value": -9.75, + "curve": [ 0.316, -11.84, 0.519, -16.66 ] + }, + { + "time": 0.6667, + "value": -16.66, + "curve": [ 0.817, -16.66, 1.029, -11.43 ] + }, + { + "time": 1.1333, + "value": -9.14, + "curve": [ 1.25, -6.56, 1.525, 0 ] + }, + { "time": 1.6667 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.1, 0, 0.3, 1.32 ] + }, + { + "time": 0.4, + "value": 1.32, + "curve": [ 0.55, 1.32, 0.866, 0.93 ] + }, + { + "time": 1, + "value": 0.73, + "curve": [ 1.189, 0.46, 1.5, 0 ] + }, + { "time": 1.6667 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.118, -0.44, 0.3, -8.52 ] + }, + { + "time": 0.4, + "value": -8.52, + "curve": [ 0.55, -8.52, 0.85, 1.96 ] + }, + { + "time": 1, + "value": 1.96, + "curve": [ 1.167, 1.96, 1.577, 0.38 ] + }, + { "time": 1.6667 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.098, 1.46, 0.3, 4.49, 0.17, 0.13, 0.316, -3.28 ] + }, + { + "time": 0.4, + "x": 4.55, + "y": -5.95, + "curve": [ 0.53, 4.64, 0.776, 2.59, 0.492, -8.89, 0.668, -14.21 ] + }, + { + "time": 0.8667, + "x": 1.42, + "y": -14.26, + "curve": [ 0.966, 0.15, 1.109, -2.91, 0.994, -14.26, 1.144, -10.58 ] + }, + { + "time": 1.2333, + "x": -3.02, + "y": -8.26, + "curve": [ 1.342, -3.02, 1.568, -1.48, 1.317, -6.1, 1.558, 0 ] + }, + { "time": 1.6667 } + ] + }, + "front-shoulder": { + "translate": [ + { + "curve": [ 0.21, 0, 0.525, -1.72, 0.21, 0, 0.525, 4.08 ] + }, + { + "time": 0.8333, + "x": -1.72, + "y": 4.08, + "curve": [ 1.15, -1.72, 1.46, 0, 1.15, 4.08, 1.46, 0 ] + }, + { "time": 1.6667 } + ] + } + } + }, + "idle-turn": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-upper-arm": { + "rotate": [ + { + "value": -302.77, + "curve": [ 0, -406.9, 0.125, -420.87 ] + }, + { "time": 0.2667, "value": -420.87 } + ], + "translate": [ + { + "x": 2.24, + "y": -4.98, + "curve": [ 0.067, 2.24, 0.111, 0, 0.067, -4.98, 0.111, 0 ] + }, + { "time": 0.2667 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 248.56, + "curve": [ 0, 371.28, 0.062, 399.2 ] + }, + { "time": 0.1333, "value": 399.2 } + ], + "translate": [ + { + "x": -2.84, + "y": 37.28, + "curve": [ 0.033, -2.84, 0.069, 0, 0.033, 37.28, 0.069, 0 ] + }, + { "time": 0.1333 } + ] + }, + "gun": { + "rotate": [ + { + "value": -3.95, + "curve": [ 0, -10.4, 0.019, -20.43 ] + }, + { + "time": 0.0333, + "value": -20.45, + "curve": [ 0.044, -20.47, 0.125, 0 ] + }, + { "time": 0.2 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.2, + "curve": [ 0, 6.27, 0.125, 3.78 ] + }, + { "time": 0.2667, "value": 3.78 } + ] + }, + "hip": { + "translate": [ + { + "x": -2.69, + "y": -6.79, + "curve": [ 0.067, -2.69, 0.2, -11.97, 0.067, -6.79, 0.2, -23.15 ] + }, + { "time": 0.2667, "x": -11.97, "y": -23.15 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -15.54, + "curve": [ 0, -3.08, 0.034, 18.44 ] + }, + { + "time": 0.0667, + "value": 19.02, + "curve": [ 0.108, 19.75, 0.169, 0 ] + }, + { "time": 0.2667 } + ], + "scale": [ + { + "x": 0.94, + "curve": [ 0, 0.962, 0.024, 1.237, 0, 1, 0.026, 0.947 ] + }, + { + "time": 0.0667, + "x": 1.236, + "y": 0.947, + "curve": [ 0.117, 1.235, 0.189, 1, 0.117, 0.947, 0.189, 1 ] + }, + { "time": 0.2667 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 11.75, + "curve": [ 0, -7.97, 0.017, -33.4 ] + }, + { + "time": 0.0333, + "value": -33.39, + "curve": [ 0.049, -33.37, 0.131, 0 ] + }, + { "time": 0.2 } + ] + }, + "torso": { + "rotate": [ + { + "value": -18.25, + "curve": [ 0, -10.59, 0.125, -22.88 ] + }, + { "time": 0.2667, "value": -22.88 } + ], + "scale": [ + { + "y": 1.03, + "curve": [ 0.067, 1, 0.132, 1, 0.067, 1.03, 0.132, 1 ] + }, + { "time": 0.2667 } + ] + }, + "head": { + "rotate": [ + { + "value": 5.12, + "curve": [ 0, -6.34, 0.125, -6.75 ] + }, + { "time": 0.2667, "value": -6.75 } + ], + "scale": [ + { + "y": 1.03, + "curve": [ 0.067, 1, 0.107, 1, 0.067, 1.03, 0.107, 1 ] + }, + { "time": 0.2667 } + ] + }, + "rear-foot-target": { + "translate": [ + { + "x": -58.39, + "y": 30.48, + "curve": [ 0, -7.15, 0.047, 16.62, 0, 12.71, 0.039, 0.22 ] + }, + { + "time": 0.1, + "x": 34.14, + "y": -0.19, + "curve": [ 0.136, 45.79, 0.163, 48.87, 0.133, -0.41, 0.163, 0 ] + }, + { "time": 0.2, "x": 48.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 6.69, + "curve": [ 0, 19.76, 0.039, 56.53 ] + }, + { + "time": 0.0667, + "value": 56.63, + "curve": [ 0.114, 56.79, 0.189, 42.46 ] + }, + { "time": 0.2667, "value": 42.46 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": -1.85, + "curve": [ 0.014, -8.91, 0.047, -28.4 ] + }, + { + "time": 0.1, + "value": -28.89, + "curve": [ 0.144, -29.29, 0.262, -21.77 ] + }, + { "time": 0.2667 } + ], + "translate": [ + { + "x": 9.97, + "y": 0.82, + "curve": [ 0, -54.41, 0.078, -69.06, 0, 0.15, 0.078, 0 ] + }, + { "time": 0.1667, "x": -69.06 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -9.01, + "curve": [ 0.044, -9.01, 0.072, 7.41 ] + }, + { + "time": 0.1333, + "value": 10.08, + "curve": [ 0.166, 11.47, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -16.49, + "curve": [ 0.044, -16.49, 0.101, -5.98 ] + }, + { + "time": 0.1333, + "value": -2.95, + "curve": [ 0.162, -0.34, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -3.85, + "curve": [ 0.044, -3.85, 0.072, 6.91 ] + }, + { + "time": 0.1333, + "value": 8.05, + "curve": [ 0.166, 8.65, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair2": { + "rotate": [ + { + "value": 1.25, + "curve": [ 0.044, 1.25, 0.072, 8.97 ] + }, + { + "time": 0.1333, + "value": 8.6, + "curve": [ 0.166, 8.4, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "front-thigh": { + "translate": [ + { + "x": 12.21, + "y": 1.89, + "curve": [ 0.033, 12.21, 0.1, 0, 0.033, 1.89, 0.1, 0 ] + }, + { "time": 0.1333 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -16.11, + "y": -1.38, + "curve": [ 0.033, -16.11, 0.1, 0, 0.033, -1.38, 0.1, 0 ] + }, + { "time": 0.1333 } + ] + }, + "torso3": { + "rotate": [ + { "time": 0.2667, "value": -2.15 } + ] + }, + "head-control": { + "translate": [ + { + "x": -13.72, + "y": -34.7, + "curve": [ 0.067, -13.72, 0.2, 0, 0.067, -34.7, 0.2, 0 ] + }, + { "time": 0.2667 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.13, + "y": -14.31, + "curve": [ 0.067, 1.13, 0.2, 0, 0.067, -14.31, 0.2, 0 ] + }, + { "time": 0.2667 } + ] + } + } + }, + "jump": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" }, + { "time": 0.1, "name": "front-fist-closed" }, + { "time": 0.8333, "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { + "value": 55.08, + "curve": [ 0.007, 46.66, 0.043, 26.3 ] + }, + { + "time": 0.0667, + "value": 22.84, + "curve": [ 0.1, 17.99, 0.165, 15.78 ] + }, + { + "time": 0.2333, + "value": 15.71, + "curve": [ 0.309, 15.63, 0.408, 46.67 ] + }, + { + "time": 0.5, + "value": 63.6, + "curve": [ 0.56, 74.72, 0.762, 91.48 ] + }, + { + "time": 0.9667, + "value": 91.81, + "curve": [ 1.068, 92.01, 1.096, 22.05 ] + }, + { + "time": 1.1667, + "value": 22.25, + "curve": [ 1.18, 22.29, 1.176, 56.17 ] + }, + { + "time": 1.2, + "value": 56.16, + "curve": [ 1.246, 56.15, 1.263, 54.94 ] + }, + { "time": 1.3333, "value": 55.08 } + ], + "translate": [ + { "x": -5.13, "y": 11.55 } + ] + }, + "torso": { + "rotate": [ + { + "value": -45.57, + "curve": [ 0.022, -44.61, 0.03, -39.06 ] + }, + { + "time": 0.0667, + "value": -35.29, + "curve": [ 0.12, -29.77, 0.28, -19.95 ] + }, + { + "time": 0.4333, + "value": -19.95, + "curve": [ 0.673, -19.95, 0.871, -22.38 ] + }, + { + "time": 0.9667, + "value": -27.08, + "curve": [ 1.094, -33.33, 1.176, -44.93 ] + }, + { "time": 1.3333, "value": -45.57 } + ], + "translate": [ + { "x": -3.79, "y": -0.77 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 12.81, + "curve": [ 0.067, 12.81, 0.242, 67.88 ] + }, + { + "time": 0.2667, + "value": 74.11, + "curve": [ 0.314, 86.02, 0.454, 92.23 ] + }, + { + "time": 0.5667, + "value": 92.24, + "curve": [ 0.753, 92.26, 0.966, 67.94 ] + }, + { + "time": 1, + "value": 61.32, + "curve": [ 1.039, 53.75, 1.218, 12.68 ] + }, + { "time": 1.3333, "value": 12.81 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -115.64, + "curve": [ 0.067, -117.17, 0.125, -117.15 ] + }, + { + "time": 0.1667, + "value": -117.15, + "curve": [ 0.225, -117.15, 0.332, -108.76 ] + }, + { + "time": 0.4, + "value": -107.15, + "curve": [ 0.48, -105.26, 0.685, -103.49 ] + }, + { + "time": 0.7667, + "value": -101.97, + "curve": [ 0.826, -100.87, 0.919, -92.3 ] + }, + { + "time": 1, + "value": -92.28, + "curve": [ 1.113, -92.26, 1.297, -114.22 ] + }, + { "time": 1.3333, "value": -115.64 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -40.21, + "curve": [ 0.054, -35.46, 0.15, -31.12 ] + }, + { + "time": 0.2, + "value": -31.12, + "curve": [ 0.308, -31.12, 0.547, -80.12 ] + }, + { + "time": 0.6333, + "value": -96.56, + "curve": [ 0.697, -108.56, 0.797, -112.54 ] + }, + { + "time": 0.8667, + "value": -112.6, + "curve": [ 1.137, -112.84, 1.274, -49.19 ] + }, + { "time": 1.3333, "value": -40.21 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 20.54, + "curve": [ 0.054, 32.23, 0.192, 55.84 ] + }, + { + "time": 0.2333, + "value": 62.58, + "curve": [ 0.29, 71.87, 0.375, 79.28 ] + }, + { + "time": 0.4333, + "value": 79.18, + "curve": [ 0.555, 78.98, 0.684, 27.54 ] + }, + { + "time": 0.7333, + "value": 13.28, + "curve": [ 0.786, -1.85, 0.874, -24.76 ] + }, + { + "time": 1, + "value": -25.45, + "curve": [ 1.165, -26.36, 1.303, 9.1 ] + }, + { "time": 1.3333, "value": 20.54 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16, + "curve": [ 0.114, -39.59, 0.3, -45.61 ] + }, + { + "time": 0.4, + "value": -45.61, + "curve": [ 0.442, -45.61, 0.537, -21.54 ] + }, + { + "time": 0.5667, + "value": -15.4, + "curve": [ 0.592, -10.23, 0.692, 11.89 ] + }, + { + "time": 0.7333, + "value": 11.73, + "curve": [ 0.783, 11.54, 0.831, 1.8 ] + }, + { + "time": 0.8667, + "value": -5.78, + "curve": [ 0.897, -12.22, 0.901, -14.22 ] + }, + { + "time": 0.9333, + "value": -14.51, + "curve": [ 0.974, -14.89, 0.976, 10.38 ] + }, + { + "time": 1, + "value": 10.55, + "curve": [ 1.027, 10.74, 1.023, -8.44 ] + }, + { + "time": 1.0333, + "value": -8.42, + "curve": [ 1.059, -8.36, 1.074, 10.12 ] + }, + { + "time": 1.1, + "value": 10.22, + "curve": [ 1.168, 10.48, 1.27, -36.07 ] + }, + { "time": 1.3333, "value": -36.16 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.5, + "curve": [ 0.048, 36.1, 0.168, 20.45 ] + }, + { + "time": 0.3, + "value": 20.45, + "curve": [ 0.476, 20.45, 0.571, 33.76 ] + }, + { + "time": 0.6, + "value": 38.67, + "curve": [ 0.642, 45.8, 0.681, 57.44 ] + }, + { + "time": 0.7333, + "value": 62.91, + "curve": [ 0.829, 72.8, 0.996, 77.61 ] + }, + { + "time": 1.0333, + "value": 80.37, + "curve": [ 1.082, 83.94, 1.148, 90.6 ] + }, + { + "time": 1.2, + "value": 90.6, + "curve": [ 1.248, 90.46, 1.317, 53.07 ] + }, + { "time": 1.3333, "value": 49.06 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.022, 25.12, 0.187, -0.89 ] + }, + { + "time": 0.2, + "value": -2.52, + "curve": [ 0.257, -9.92, 0.372, -17.38 ] + }, + { + "time": 0.4333, + "value": -17.41, + "curve": [ 0.54, -17.47, 0.659, -16.91 ] + }, + { + "time": 0.7667, + "value": -12.1, + "curve": [ 0.907, -5.79, 1.025, 14.58 ] + }, + { + "time": 1.1, + "value": 20.58, + "curve": [ 1.191, 27.85, 1.283, 29.67 ] + }, + { "time": 1.3333, "value": 29.67 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.88, + "curve": [ 0.104, 11.82, 0.179, 11.15 ] + }, + { + "time": 0.2, + "value": 10.08, + "curve": [ 0.255, 7.29, 0.405, -8.15 ] + }, + { + "time": 0.4333, + "value": -9.35, + "curve": [ 0.508, -12.48, 0.595, -13.14 ] + }, + { + "time": 0.6667, + "value": -12.61, + "curve": [ 0.714, -12.26, 0.815, -5.57 ] + }, + { + "time": 0.8333, + "value": -4.08, + "curve": [ 0.883, -0.07, 1.045, 12.77 ] + }, + { + "time": 1.1, + "value": 15.06, + "curve": [ 1.208, 19.6, 1.279, 20.64 ] + }, + { "time": 1.3333, "value": 20.73 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.14, + "curve": [ 0.008, 12.19, 0.197, -23.53 ] + }, + { + "time": 0.3333, + "value": -23.95, + "curve": [ 0.509, -23.95, 0.667, -2.66 ] + }, + { + "time": 0.7333, + "value": -2.66, + "curve": [ 0.792, -2.66, 0.908, -13.32 ] + }, + { + "time": 0.9667, + "value": -13.32, + "curve": [ 1.158, -13.11, 1.241, -1.58 ] + }, + { "time": 1.3333, "value": -1.58 } + ], + "scale": [ + { + "curve": [ 0.041, 1, 0.052, 0.962, 0.041, 1, 0.052, 1.137 ] + }, + { + "time": 0.1, + "x": 0.954, + "y": 1.137, + "curve": [ 0.202, 0.962, 0.318, 1, 0.202, 1.137, 0.252, 1.002 ] + }, + { "time": 0.4667 }, + { + "time": 1.0667, + "x": 1.002, + "curve": [ 1.092, 1.002, 1.126, 1.143, 1.092, 1, 1.128, 0.975 ] + }, + { + "time": 1.1667, + "x": 1.144, + "y": 0.973, + "curve": [ 1.204, 1.145, 1.233, 0.959, 1.206, 0.972, 1.227, 1.062 ] + }, + { + "time": 1.2667, + "x": 0.958, + "y": 1.063, + "curve": [ 1.284, 0.958, 1.292, 1.001, 1.288, 1.063, 1.288, 1.001 ] + }, + { "time": 1.3333 } + ] + }, + "hip": { + "translate": [ + { + "y": -45.46, + "curve": [ 0.042, -0.09, 0.15, 15.22, 0.031, 44.98, 0.123, 289.73 ] + }, + { + "time": 0.2, + "x": 15.22, + "y": 415.85, + "curve": [ 0.332, 15.22, 0.539, -34.52, 0.271, 532.93, 0.483, 720.5 ] + }, + { + "time": 0.7667, + "x": -34.52, + "y": 721.6, + "curve": [ 0.888, -34.52, 1.057, -21.95, 1.049, 721.17, 1.098, 379.84 ] + }, + { + "time": 1.1333, + "x": -15.67, + "y": 266.77, + "curve": [ 1.144, -14.77, 1.188, -10.53, 1.15, 213.72, 1.172, -61.32 ] + }, + { + "time": 1.2333, + "x": -6.53, + "y": -61.34, + "curve": [ 1.272, -3.22, 1.311, 0.05, 1.291, -61.36, 1.296, -44.8 ] + }, + { "time": 1.3333, "y": -45.46 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -74.19, + "curve": [ 0, -51.14, 0.042, -12.54 ] + }, + { + "time": 0.1667, + "value": -12.28, + "curve": [ 0.285, -12.32, 0.37, -74.44 ] + }, + { + "time": 0.4333, + "value": -92.92, + "curve": [ 0.498, -111.86, 0.617, -140.28 ] + }, + { + "time": 0.9, + "value": -140.84, + "curve": [ 1.004, -141.04, 1.09, -47.87 ] + }, + { + "time": 1.1, + "value": -37.44, + "curve": [ 1.108, -29.83, 1.14, -21.18 ] + }, + { + "time": 1.1667, + "value": -21.08, + "curve": [ 1.18, -21.03, 1.191, -50.65 ] + }, + { + "time": 1.2, + "value": -53.17, + "curve": [ 1.22, -58.53, 1.271, -73.38 ] + }, + { "time": 1.3333, "value": -74.19 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 7.35, + "curve": [ 0, 4.8, 0.05, -26.64 ] + }, + { + "time": 0.0667, + "value": -26.64, + "curve": [ 0.192, -26.64, 0.442, -11.77 ] + }, + { + "time": 0.5667, + "value": -11.77, + "curve": [ 0.692, -11.77, 0.942, -19.36 ] + }, + { + "time": 1.0667, + "value": -19.36, + "curve": [ 1.133, -19.36, 1.32, 3.82 ] + }, + { "time": 1.3333, "value": 7.35 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": -7.14 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.36, + "curve": [ 0.022, 16.28, 0.15, 30.81 ] + }, + { + "time": 0.2, + "value": 30.81, + "curve": [ 0.258, 30.81, 0.375, 13.26 ] + }, + { + "time": 0.4333, + "value": 13.26, + "curve": [ 0.508, 13.26, 0.658, 15.05 ] + }, + { + "time": 0.7333, + "value": 14.98, + "curve": [ 0.789, 14.94, 0.828, 13.62 ] + }, + { + "time": 0.8667, + "value": 12.72, + "curve": [ 0.887, 12.25, 0.984, 9.83 ] + }, + { + "time": 1.0333, + "value": 8.6, + "curve": [ 1.045, 8.31, 1.083, 7.55 ] + }, + { + "time": 1.1333, + "value": 7.13, + "curve": [ 1.175, 6.78, 1.283, 6.18 ] + }, + { "time": 1.3333, "value": 6.18 } + ] + }, + "front-leg-target": { + "translate": [ + { "x": -13.95, "y": -30.34 } + ] + }, + "rear-leg-target": { + "rotate": [ + { "value": -38.43 } + ], + "translate": [ + { "x": 85, "y": -33.59 } + ] + }, + "front-foot-target": { + "rotate": [ + { "value": -62.54 } + ], + "translate": [ + { "x": 16.34, "y": 0.18 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": 18.55 } + ], + "translate": [ + { "x": -176.39, "y": 134.12 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "value": -143.73, + "curve": [ 0.083, -144.24, 0.167, -74.26 ] + }, + { + "time": 0.2667, + "value": -52.76, + "curve": [ 0.342, -36.57, 0.513, -36.57 ] + }, + { + "time": 0.6333, + "value": -30.97, + "curve": [ 0.724, -26.78, 0.848, -17.06 ] + }, + { + "time": 0.9667, + "value": -16.74, + "curve": [ 1.167, -16.2, 1.272, -144.17 ] + }, + { "time": 1.3333, "value": -143.73 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -1.57, + "curve": [ 0, -24.71, 0.162, -60.88 ] + }, + { + "time": 0.2667, + "value": -60.83, + "curve": [ 0.342, -60.8, 0.582, -43.5 ] + }, + { + "time": 0.7, + "value": -39.45, + "curve": [ 0.773, -36.94, 0.832, -36.78 ] + }, + { + "time": 0.9667, + "value": -36.6, + "curve": [ 1.054, -36.49, 1.092, -37.37 ] + }, + { + "time": 1.1667, + "value": -33.26, + "curve": [ 1.237, -29.37, 1.147, -1.41 ] + }, + { "time": 1.2, "value": -1.57 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0, 13.59, 0.117, 18.21 ] + }, + { + "time": 0.1333, + "value": 18.21, + "curve": [ 0.167, 18.21, 0.26, 12.95 ] + }, + { + "time": 0.3, + "value": 11.56, + "curve": [ 0.382, 8.7, 0.55, 9.43 ] + }, + { + "time": 0.6667, + "value": 9.32, + "curve": [ 0.843, 9.15, 0.918, -7.34 ] + }, + { "time": 1.3333, "value": -6.81 } + ], + "translate": [ + { + "time": 0.6667, + "curve": [ 0.781, 0, 0.972, 16.03, 0.781, 0, 0.972, 0.92 ] + }, + { + "time": 1.1333, + "x": 16.03, + "y": 0.92, + "curve": [ 1.211, 16.03, 1.281, 0, 1.211, 0.92, 1.281, 0 ] + }, + { "time": 1.3333 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.001, -3.88, 0.063, 16.18 ] + }, + { + "time": 0.1667, + "value": 16.14, + "curve": [ 0.242, 16.1, 0.249, 16.07 ] + }, + { + "time": 0.3333, + "value": 13.46, + "curve": [ 0.442, 10.09, 0.573, -2.2 ] + }, + { + "time": 0.6, + "value": -6.04, + "curve": [ 0.614, -8.05, 0.717, -33.44 ] + }, + { + "time": 0.7667, + "value": -33.44, + "curve": [ 0.809, -33.44, 0.835, -31.32 ] + }, + { + "time": 0.8667, + "value": -27.36, + "curve": [ 0.874, -26.47, 0.903, -14.28 ] + }, + { + "time": 0.9333, + "value": -14.47, + "curve": [ 0.956, -14.62, 0.944, -25.91 ] + }, + { + "time": 1, + "value": -25.96, + "curve": [ 1.062, -26.02, 1.051, -1.87 ] + }, + { + "time": 1.0667, + "value": -1.87, + "curve": [ 1.096, -1.87, 1.096, -16.09 ] + }, + { + "time": 1.1333, + "value": -16.08, + "curve": [ 1.169, -16.08, 1.153, -3.38 ] + }, + { + "time": 1.2, + "value": -3.38, + "curve": [ 1.234, -3.38, 1.271, -6.07 ] + }, + { "time": 1.3333, "value": -6.07 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0, -3.17, 0.042, 16.33 ] + }, + { + "time": 0.0667, + "value": 16.33, + "curve": [ 0.21, 15.74, 0.208, -12.06 ] + }, + { + "time": 0.3333, + "value": -12.21, + "curve": [ 0.417, -12.3, 0.552, -3.98 ] + }, + { + "time": 0.6667, + "value": 1.52, + "curve": [ 0.726, 4.35, 0.817, 4.99 ] + }, + { + "time": 0.8667, + "value": 4.99, + "curve": [ 0.901, 4.99, 0.912, -29.05 ] + }, + { + "time": 0.9667, + "value": -27.45, + "curve": [ 0.987, -26.83, 1.018, -5.42 ] + }, + { + "time": 1.0667, + "value": -5.46, + "curve": [ 1.107, -5.22, 1.095, -33.51 ] + }, + { + "time": 1.1333, + "value": -33.28, + "curve": [ 1.162, -33.57, 1.192, 8.04 ] + }, + { + "time": 1.2667, + "value": 7.86, + "curve": [ 1.302, 7.77, 1.313, 2.7 ] + }, + { "time": 1.3333, "value": 2.7 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.001, -3.12, 0.074, 14.66 ] + }, + { + "time": 0.1333, + "value": 14.66, + "curve": [ 0.188, 14.8, 0.293, 9.56 ] + }, + { + "time": 0.3333, + "value": 5.99, + "curve": [ 0.381, 1.72, 0.55, -11.11 ] + }, + { + "time": 0.6667, + "value": -11.11, + "curve": [ 0.833, -11.11, 0.933, 22.54 ] + }, + { + "time": 1.1, + "value": 22.54, + "curve": [ 1.158, 22.54, 1.275, -6.81 ] + }, + { "time": 1.3333, "value": -6.81 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 4.52, + "curve": [ 0.013, 2.33, 0.092, -9.75 ] + }, + { + "time": 0.1333, + "value": -9.75, + "curve": [ 0.175, -9.75, 0.291, -1.26 ] + }, + { + "time": 0.3333, + "value": 0.96, + "curve": [ 0.359, 2.3, 0.543, 4.25 ] + }, + { + "time": 0.6, + "value": 4.68, + "curve": [ 0.683, 5.3, 0.771, 5.92 ] + }, + { + "time": 0.8333, + "value": 6.48, + "curve": [ 0.871, 6.82, 1.083, 11.37 ] + }, + { + "time": 1.1667, + "value": 11.37, + "curve": [ 1.208, 11.37, 1.317, 6.18 ] + }, + { "time": 1.3333, "value": 4.52 } + ], + "translate": [ + { + "curve": [ 0, 0, 0.082, -2.24, 0, 0, 0.082, -0.42 ] + }, + { + "time": 0.1667, + "x": -2.98, + "y": -0.56, + "curve": [ 0.232, -2.24, 0.298, 0, 0.232, -0.42, 0.298, 0 ] + }, + { "time": 0.3333, "curve": "stepped" }, + { + "time": 0.8667, + "curve": [ 0.889, 0, 0.912, 0.26, 0.889, 0, 0.912, 0.06 ] + }, + { + "time": 0.9333, + "x": 0.68, + "y": 0.23, + "curve": [ 1.016, 2.22, 1.095, 5.9, 1.023, 0.97, 1.095, 1.99 ] + }, + { + "time": 1.1667, + "x": 6.47, + "y": 2.18, + "curve": [ 1.23, 5.75, 1.286, 0, 1.23, 1.94, 1.286, 0 ] + }, + { "time": 1.3333 } + ] + }, + "torso3": { + "rotate": [ + { + "value": 4.52, + "curve": [ 0.025, 4.52, 0.075, -6.17 ] + }, + { + "time": 0.1, + "value": -6.17, + "curve": [ 0.175, -6.17, 0.381, -0.71 ] + }, + { + "time": 0.4, + "value": -0.25, + "curve": [ 0.447, 0.87, 0.775, 4.84 ] + }, + { + "time": 0.9, + "value": 4.84, + "curve": [ 1.008, 4.84, 1.225, 4.52 ] + }, + { "time": 1.3333, "value": 4.52 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.138, -2.4, 0.227, -10.44, 0.123, 1.05, 0.227, 2.7 ] + }, + { + "time": 0.3667, + "x": -10.44, + "y": 2.7, + "curve": [ 0.484, -10.44, 0.585, -5.63, 0.484, 2.7, 0.629, -23.62 ] + }, + { + "time": 0.7333, + "x": -2.29, + "y": -26.61, + "curve": [ 0.818, -0.39, 0.962, 1.21, 0.858, -30.17, 0.972, -28.75 ] + }, + { + "time": 1.1, + "x": 1.25, + "y": -28.75, + "curve": [ 1.192, 1.28, 1.234, 0.98, 1.224, -28.75, 1.235, -2.15 ] + }, + { "time": 1.3333 } + ] + }, + "front-shoulder": { + "translate": [ + { + "curve": [ 0.031, -2.22, 0.065, -3.73, 0.02, -3.25, 0.065, -14.74 ] + }, + { + "time": 0.1, + "x": -3.73, + "y": -14.74, + "curve": [ 0.216, -3.73, 0.384, -0.17, 0.216, -14.74, 0.402, -12.51 ] + }, + { + "time": 0.5, + "x": 1.63, + "y": -9.51, + "curve": [ 0.632, 3.69, 0.935, 7.41, 0.585, -6.91, 0.909, 10.86 ] + }, + { + "time": 1.1, + "x": 7.45, + "y": 10.99, + "curve": [ 1.18, 7.46, 1.265, 2.86, 1.193, 11.05, 1.294, 3.38 ] + }, + { "time": 1.3333 } + ] + } + }, + "ik": { + "front-foot-ik": [ + { + "mix": 0, + "curve": [ 0.3, 0, 0.9, 1, 0.3, 0, 0.9, 0 ] + }, + { "time": 1.2 } + ], + "front-leg-ik": [ + { + "mix": 0, + "bendPositive": false, + "curve": [ 0.3, 0, 0.9, 1, 0.3, 0, 0.9, 0 ] + }, + { "time": 1.2, "bendPositive": false } + ], + "rear-foot-ik": [ + { "mix": 0 } + ], + "rear-leg-ik": [ + { "mix": 0, "bendPositive": false } + ] + }, + "events": [ + { "time": 1.2, "name": "footstep" } + ] + }, + "portal": { + "slots": { + "clipping": { + "attachment": [ + { "name": "clipping" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "time": 0.9, "name": "mouth-grind" }, + { "time": 2.2667, "name": "mouth-smile" } + ] + }, + "portal-bg": { + "attachment": [ + { "name": "portal-bg" }, + { "time": 3, "name": null } + ] + }, + "portal-flare1": { + "attachment": [ + { "time": 1.1, "name": "portal-flare1" }, + { "time": 1.1333, "name": "portal-flare2" }, + { "time": 1.1667, "name": "portal-flare3" }, + { "time": 1.2, "name": "portal-flare1" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3333, "name": null } + ] + }, + "portal-flare2": { + "attachment": [ + { "time": 1.1, "name": "portal-flare2" }, + { "time": 1.1333, "name": "portal-flare3" }, + { "time": 1.1667, "name": "portal-flare1" }, + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667, "name": null } + ] + }, + "portal-flare3": { + "attachment": [ + { "time": 1.2, "name": "portal-flare3" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667, "name": null } + ] + }, + "portal-flare4": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare1" }, + { "time": 1.2667, "name": "portal-flare2" }, + { "time": 1.3333, "name": null } + ] + }, + "portal-flare5": { + "attachment": [ + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3333, "name": null } + ] + }, + "portal-flare6": { + "attachment": [ + { "time": 1.2667, "name": "portal-flare3" }, + { "time": 1.3333, "name": null } + ] + }, + "portal-flare7": { + "attachment": [ + { "time": 1.1333, "name": "portal-flare2" }, + { "time": 1.1667, "name": null } + ] + }, + "portal-flare8": { + "attachment": [ + { "time": 1.2, "name": "portal-flare3" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667, "name": null } + ] + }, + "portal-flare9": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3, "name": null } + ] + }, + "portal-flare10": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare1" }, + { "time": 1.2667, "name": "portal-flare3" }, + { "time": 1.3, "name": null } + ] + }, + "portal-shade": { + "attachment": [ + { "name": "portal-shade" }, + { "time": 3, "name": null } + ] + }, + "portal-streaks1": { + "attachment": [ + { "name": "portal-streaks1" }, + { "time": 3, "name": null } + ] + }, + "portal-streaks2": { + "attachment": [ + { "name": "portal-streaks2" }, + { "time": 3, "name": null } + ] + } + }, + "bones": { + "portal-root": { + "translate": [ + { + "x": -458.35, + "y": 105.19, + "curve": [ 0.333, -458.22, 0.669, -457.86, 0.934, 105.19, 0.671, 105.19 ] + }, + { + "time": 1, + "x": -456.02, + "y": 105.19, + "curve": [ 1.339, -454.14, 2.208, -447.28, 1.35, 105.19, 2.05, 105.19 ] + }, + { + "time": 2.4, + "x": -439.12, + "y": 105.19, + "curve": [ 2.463, -436.44, 2.502, -432.92, 2.487, 105.19, 2.512, 105.09 ] + }, + { + "time": 2.6, + "x": -432.58, + "y": 105.09, + "curve": [ 2.784, -431.94, 2.978, -446.6, 2.772, 105.09, 2.933, 105.19 ] + }, + { "time": 3.0333, "x": -457.42, "y": 105.19 } + ], + "scale": [ + { + "x": 0.003, + "y": 0.006, + "curve": [ 0.329, 0.044, 0.347, 0.117, 0.329, 0.097, 0.37, 0.249 ] + }, + { + "time": 0.4, + "x": 0.175, + "y": 0.387, + "curve": [ 0.63, 0.619, 0.663, 0.723, 0.609, 1.338, 0.645, 1.524 ] + }, + { + "time": 0.7333, + "x": 0.724, + "y": 1.52, + "curve": [ 0.798, 0.725, 0.907, 0.647, 0.797, 1.517, 0.895, 1.424 ] + }, + { + "time": 1, + "x": 0.645, + "y": 1.426, + "curve": [ 1.095, 0.643, 1.139, 0.688, 1.089, 1.428, 1.115, 1.513 ] + }, + { + "time": 1.2333, + "x": 0.685, + "y": 1.516, + "curve": [ 1.325, 0.683, 1.508, 0.636, 1.343, 1.518, 1.467, 1.4 ] + }, + { + "time": 1.6, + "x": 0.634, + "y": 1.401, + "curve": [ 1.728, 0.631, 1.946, 0.687, 1.722, 1.402, 1.924, 1.522 ] + }, + { + "time": 2.0667, + "x": 0.688, + "y": 1.522, + "curve": [ 2.189, 0.69, 2.289, 0.649, 2.142, 1.522, 2.265, 1.417 ] + }, + { + "time": 2.4, + "x": 0.65, + "y": 1.426, + "curve": [ 2.494, 0.651, 2.504, 0.766, 2.508, 1.434, 2.543, 1.566 ] + }, + { + "time": 2.6, + "x": 0.766, + "y": 1.568, + "curve": [ 2.73, 0.765, 3.006, 0.098, 2.767, 1.564, 2.997, 0.1 ] + }, + { "time": 3.0333, "x": 0.007, "y": 0.015 } + ] + }, + "portal-streaks1": { + "rotate": [ + {}, + { "time": 3.1667, "value": 1200 } + ], + "translate": [ + { + "x": 15.15, + "curve": [ 0.162, 15.15, 0.432, 12.6, 0.162, 0, 0.432, -3.86 ] + }, + { + "time": 0.6667, + "x": 10.9, + "y": -6.44, + "curve": [ 0.794, 9.93, 0.912, 9.21, 0.794, -7.71, 0.912, -8.66 ] + }, + { + "time": 1, + "x": 9.21, + "y": -8.66, + "curve": [ 1.083, 9.21, 1.25, 21.53, 1.083, -8.66, 1.265, -4.9 ] + }, + { + "time": 1.3333, + "x": 21.53, + "y": -3.19, + "curve": [ 1.5, 21.53, 1.939, 12.3, 1.446, -0.37, 1.9, 6.26 ] + }, + { + "time": 2.0667, + "x": 11.26, + "y": 6.26, + "curve": [ 2.239, 9.85, 2.389, 9.68, 2.208, 6.26, 2.523, 0.51 ] + }, + { + "time": 2.5667, + "x": 9.39, + "y": -0.8, + "curve": [ 2.657, 9.24, 2.842, 9.21, 2.646, -3.2, 2.842, -8.91 ] + }, + { "time": 2.9333, "x": 9.21, "y": -8.91 } + ], + "scale": [ + { + "curve": [ 0.167, 1, 0.5, 1.053, 0.167, 1, 0.5, 1.053 ] + }, + { + "time": 0.6667, + "x": 1.053, + "y": 1.053, + "curve": [ 0.833, 1.053, 1.167, 0.986, 0.833, 1.053, 1.167, 0.986 ] + }, + { + "time": 1.3333, + "x": 0.986, + "y": 0.986, + "curve": [ 1.5, 0.986, 1.833, 1.053, 1.5, 0.986, 1.833, 1.053 ] + }, + { "time": 2, "x": 1.053, "y": 1.053 } + ] + }, + "portal-streaks2": { + "rotate": [ + {}, + { "time": 3.1667, "value": 600 } + ], + "translate": [ + { "x": -2.11 }, + { "time": 1, "x": -2.11, "y": 6.63 }, + { "time": 1.9333, "x": -2.11 } + ], + "scale": [ + { + "x": 1.014, + "y": 1.014, + "curve": [ 0.229, 0.909, 0.501, 0.755, 0.242, 0.892, 0.502, 0.768 ] + }, + { + "time": 0.8667, + "x": 0.745, + "y": 0.745, + "curve": [ 1.282, 0.733, 2.021, 0.699, 1.27, 0.719, 2.071, 0.709 ] + }, + { + "time": 2.2, + "x": 0.7, + "y": 0.704, + "curve": [ 2.315, 0.7, 2.421, 0.794, 2.311, 0.701, 2.485, 0.797 ] + }, + { + "time": 2.5667, + "x": 0.794, + "y": 0.794, + "curve": [ 2.734, 0.794, 2.99, 0.323, 2.714, 0.789, 3.019, 0.341 ] + }, + { "time": 3.1667, "x": 0, "y": 0 } + ] + }, + "portal-shade": { + "translate": [ + { "x": -29.68 } + ], + "scale": [ + { "x": 0.714, "y": 0.714 } + ] + }, + "portal": { + "rotate": [ + {}, + { "time": 3.1667, "value": 600 } + ] + }, + "clipping": { + "translate": [ + { "x": -476.55, "y": 2.27 } + ], + "scale": [ + { "x": 0.983, "y": 1.197 } + ] + }, + "hip": { + "rotate": [ + { + "time": 1.0667, + "value": 22.74, + "curve": [ 1.163, 18.84, 1.77, 8.77 ] + }, + { + "time": 1.9, + "value": 7.82, + "curve": [ 2.271, 5.1, 2.89, 0 ] + }, + { "time": 3.1667 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { + "time": 1.0667, + "x": -694.16, + "y": 183.28, + "curve": [ 1.091, -602.08, 1.138, -427.59, 1.115, 185.6, 1.171, 133.18 ] + }, + { + "time": 1.2333, + "x": -316.97, + "y": 55.29, + "curve": [ 1.317, -220.27, 1.512, -123.21, 1.271, 8.68, 1.461, -83.18 ] + }, + { + "time": 1.6, + "x": -95.53, + "y": -112.23, + "curve": [ 1.718, -58.25, 2.037, -22.54, 1.858, -166.17, 2.109, -31.4 ] + }, + { + "time": 2.1667, + "x": -14.82, + "y": -31.12, + "curve": [ 2.294, -7.28, 2.442, -7.2, 2.274, -30.6, 2.393, -36.76 ] + }, + { + "time": 2.6, + "x": -7.2, + "y": -36.96, + "curve": [ 2.854, -7.2, 3.071, -11.87, 2.786, -36.27, 3.082, -22.98 ] + }, + { "time": 3.1667, "x": -11.97, "y": -23.15 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "time": 1.0667, "value": 41.6, "curve": "stepped" }, + { + "time": 1.2333, + "value": 41.6, + "curve": [ 1.258, 41.6, 1.379, 35.46 ] + }, + { + "time": 1.4, + "value": 30.09, + "curve": [ 1.412, 27.04, 1.433, 10.65 ] + }, + { "time": 1.4333, "value": -0.28 }, + { "time": 1.6, "value": 2.44 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { + "time": 1.0667, + "x": -591.13, + "y": 438.46, + "curve": [ 1.076, -539.77, 1.206, -268.1, 1.117, 418.44, 1.21, 333.18 ] + }, + { + "time": 1.2333, + "x": -225.28, + "y": 304.53, + "curve": [ 1.265, -175.22, 1.393, -74.21, 1.296, 226.52, 1.401, 49.61 ] + }, + { + "time": 1.4333, + "x": -52.32, + "y": 0.2, + "curve": [ 1.454, -40.85, 1.616, 40.87, 1.466, 0.17, 1.614, 0.04 ] + }, + { "time": 1.6667, "x": 45.87, "y": 0.01 }, + { "time": 1.9333, "x": 48.87 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "time": 1.0667, + "value": 32.08, + "curve": [ 1.108, 32.08, 1.192, 35.16 ] + }, + { + "time": 1.2333, + "value": 35.16, + "curve": [ 1.258, 35.16, 1.317, 2.23 ] + }, + { + "time": 1.3333, + "value": -4.74, + "curve": [ 1.351, -12.14, 1.429, -34.96 ] + }, + { + "time": 1.6, + "value": -34.77, + "curve": [ 1.765, -34.58, 1.897, -17.25 ] + }, + { "time": 1.9333 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { + "time": 1.0667, + "x": -533.93, + "y": 363.75, + "curve": [ 1.074, -480.85, 1.18, -261.31, 1.094, 362.3, 1.195, 267.77 ] + }, + { + "time": 1.2333, + "x": -201.23, + "y": 199.93, + "curve": [ 1.269, -161.38, 1.294, -140.32, 1.274, 126.67, 1.308, 77.12 ] + }, + { + "time": 1.3333, + "x": -124.08, + "y": 0.2, + "curve": [ 1.426, -85.6, 1.633, -69.06, 1.45, 0.48, 1.633, 0 ] + }, + { "time": 1.7333, "x": -69.06 } + ] + }, + "torso": { + "rotate": [ + { + "time": 1.0667, + "value": 27.02, + "curve": [ 1.187, 26.86, 1.291, 7.81 ] + }, + { + "time": 1.3333, + "value": -2.62, + "curve": [ 1.402, -19.72, 1.429, -48.64 ] + }, + { + "time": 1.4667, + "value": -56.31, + "curve": [ 1.509, -64.87, 1.62, -77.14 ] + }, + { + "time": 1.7333, + "value": -77.34, + "curve": [ 1.837, -76.89, 1.895, -71.32 ] + }, + { + "time": 2, + "value": -57.52, + "curve": [ 2.104, -43.83, 2.189, -28.59 ] + }, + { + "time": 2.3, + "value": -29.03, + "curve": [ 2.413, -29.48, 2.513, -36.79 ] + }, + { + "time": 2.6667, + "value": -36.79, + "curve": [ 2.814, -36.95, 2.947, -22.88 ] + }, + { "time": 3.1667, "value": -22.88 } + ] + }, + "neck": { + "rotate": [ + { + "time": 1.0667, + "value": -3.57, + "curve": [ 1.146, -3.66, 1.15, -13.5 ] + }, + { + "time": 1.2333, + "value": -13.5, + "curve": [ 1.428, -13.5, 1.443, 11.58 ] + }, + { + "time": 1.5667, + "value": 11.42, + "curve": [ 1.658, 11.3, 1.775, 3.78 ] + }, + { + "time": 1.8667, + "value": 3.78, + "curve": [ 1.92, 3.78, 2.036, 8.01 ] + }, + { + "time": 2.1, + "value": 7.93, + "curve": [ 2.266, 7.72, 2.42, 3.86 ] + }, + { + "time": 2.5333, + "value": 3.86, + "curve": [ 2.783, 3.86, 3.004, 3.78 ] + }, + { "time": 3.1667, "value": 3.78 } + ] + }, + "head": { + "rotate": [ + { + "time": 1.0667, + "value": 16.4, + "curve": [ 1.133, 9.9, 1.207, 1.87 ] + }, + { + "time": 1.3333, + "value": 1.67, + "curve": [ 1.46, 1.56, 1.547, 47.54 ] + }, + { + "time": 1.7333, + "value": 47.55, + "curve": [ 1.897, 47.56, 2.042, 5.68 ] + }, + { + "time": 2.0667, + "value": 0.86, + "curve": [ 2.074, -0.61, 2.086, -2.81 ] + }, + { + "time": 2.1, + "value": -5.31, + "curve": [ 2.145, -13.07, 2.216, -23.65 ] + }, + { + "time": 2.2667, + "value": -23.71, + "curve": [ 2.334, -23.79, 2.426, -13.43 ] + }, + { + "time": 2.4667, + "value": -9.18, + "curve": [ 2.498, -5.91, 2.604, 2.53 ] + }, + { + "time": 2.6667, + "value": 2.52, + "curve": [ 2.738, 2.24, 2.85, -8.76 ] + }, + { + "time": 2.9333, + "value": -8.67, + "curve": [ 3.036, -8.55, 3.09, -7.09 ] + }, + { "time": 3.1667, "value": -6.75 } + ], + "scale": [ + { + "time": 1.3333, + "curve": [ 1.392, 1, 1.526, 1, 1.392, 1, 1.508, 1.043 ] + }, + { + "time": 1.5667, + "x": 0.992, + "y": 1.043, + "curve": [ 1.598, 0.985, 1.676, 0.955, 1.584, 1.043, 1.672, 1.04 ] + }, + { + "time": 1.7333, + "x": 0.954, + "y": 1.029, + "curve": [ 1.843, 0.954, 1.933, 1, 1.825, 1.013, 1.933, 1 ] + }, + { "time": 2 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "time": 0.9, + "value": 39.24, + "curve": [ 0.968, 39.93, 1.267, 85.31 ] + }, + { + "time": 1.4667, + "value": 112.27, + "curve": [ 1.555, 124.24, 1.576, 126.44 ] + }, + { + "time": 1.6333, + "value": 126.44, + "curve": [ 1.782, 126.44, 1.992, 94.55 ] + }, + { + "time": 2.1, + "value": 79.96, + "curve": [ 2.216, 64.26, 2.407, 34.36 ] + }, + { + "time": 2.5667, + "value": 33.38, + "curve": [ 2.815, 31.87, 3.1, 39.2 ] + }, + { "time": 3.1667, "value": 39.2 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "time": 1.0667, + "value": 56.07, + "curve": [ 1.138, 59.21, 1.192, 59.65 ] + }, + { + "time": 1.2333, + "value": 59.46, + "curve": [ 1.295, 59.17, 1.45, 22.54 ] + }, + { "time": 1.4667, "value": -0.84 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "time": 1.0667, + "value": 118.03, + "curve": [ 1.075, 93.64, 1.358, -34.03 ] + }, + { + "time": 1.6667, + "value": -33.94, + "curve": [ 1.808, -33.89, 1.879, -25 ] + }, + { + "time": 1.9667, + "value": -25.19, + "curve": [ 2.09, -25.46, 2.312, -34.58 ] + }, + { + "time": 2.3667, + "value": -38.36, + "curve": [ 2.465, -45.18, 2.557, -60.1 ] + }, + { + "time": 2.8333, + "value": -61.1, + "curve": [ 2.843, -61.06, 3.16, -60.87 ] + }, + { "time": 3.1667, "value": -60.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "time": 1.0667, + "value": 0.66, + "curve": [ 1.108, 0.66, 1.221, 44.95 ] + }, + { + "time": 1.2333, + "value": 49.25, + "curve": [ 1.263, 59.42, 1.342, 68.06 ] + }, + { + "time": 1.3667, + "value": 68.34, + "curve": [ 1.409, 68.8, 1.476, 4.9 ] + }, + { + "time": 1.5, + "value": -2.05, + "curve": [ 1.529, -10.3, 1.695, -15.95 ] + }, + { + "time": 1.7333, + "value": -17.38, + "curve": [ 1.807, -20.1, 1.878, -21.19 ] + }, + { + "time": 1.9333, + "value": -21.08, + "curve": [ 2.073, -20.8, 2.146, -7.63 ] + }, + { + "time": 2.1667, + "value": -3.64, + "curve": [ 2.186, 0.12, 2.275, 15.28 ] + }, + { + "time": 2.3333, + "value": 21.78, + "curve": [ 2.392, 28.31, 2.575, 37.66 ] + }, + { + "time": 2.7, + "value": 39.43, + "curve": [ 2.947, 42.93, 3.02, 42.46 ] + }, + { "time": 3.1667, "value": 42.46 } + ] + }, + "front-thigh": { + "translate": [ + { "time": 1.1, "x": -6.41, "y": 18.23, "curve": "stepped" }, + { "time": 1.1333, "x": -6.41, "y": 18.23 }, + { "time": 1.2, "x": 1.61, "y": 3.66 }, + { "time": 1.2333, "x": 4.5, "y": -3.15 }, + { "time": 1.3667, "x": -3.79, "y": 2.94 }, + { "time": 1.4, "x": -8.37, "y": 8.72 }, + { "time": 1.4333, "x": -11.26, "y": 16.99 }, + { "time": 1.4667, "x": -9.89, "y": 24.73, "curve": "stepped" }, + { "time": 1.8667, "x": -9.89, "y": 24.73 }, + { "time": 2.1 } + ] + }, + "front-foot-tip": { + "rotate": [ + { "time": 1.0667, "value": 42.55, "curve": "stepped" }, + { "time": 1.1333, "value": 42.55 }, + { "time": 1.2333, "value": 17.71 }, + { "time": 1.3667, "value": 3.63 }, + { "time": 1.4333 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "time": 1.0667, + "value": 108.71, + "curve": [ 1.082, 108.29, 1.437, 50.73 ] + }, + { + "time": 1.5667, + "value": 24.87, + "curve": [ 1.62, 14.2, 1.66, -11.74 ] + }, + { + "time": 1.7333, + "value": -11.74, + "curve": [ 1.961, -11.73, 2.172, 1.66 ] + }, + { + "time": 2.2667, + "value": 7.88, + "curve": [ 2.331, 12.13, 2.439, 18.65 ] + }, + { + "time": 2.5333, + "value": 18.72, + "curve": [ 2.788, 18.91, 3.145, -0.3 ] + }, + { "time": 3.1667 } + ] + }, + "front-fist": { + "rotate": [ + { + "time": 1.1, + "value": 6.32, + "curve": [ 1.11, 3.31, 1.153, -5.07 ] + }, + { + "time": 1.2333, + "value": -5.13, + "curve": [ 1.311, -5.19, 1.364, 34.65 ] + }, + { + "time": 1.4667, + "value": 34.53, + "curve": [ 1.574, 34.41, 1.547, -55.78 ] + }, + { + "time": 1.8667, + "value": -54.7, + "curve": [ 1.947, -54.7, 2.03, -53.94 ] + }, + { + "time": 2.1333, + "value": -42.44, + "curve": [ 2.215, -33.42, 2.358, -4.43 ] + }, + { + "time": 2.4, + "value": 0.03, + "curve": [ 2.444, 4.66, 2.536, 8.2 ] + }, + { + "time": 2.6333, + "value": 8.2, + "curve": [ 2.733, 8.19, 2.804, -0.67 ] + }, + { + "time": 2.9, + "value": -0.82, + "curve": [ 3.127, -1.16, 3.093, 0 ] + }, + { "time": 3.1667 } + ] + }, + "gun": { + "rotate": [ + { + "time": 1.2667, + "curve": [ 1.35, 0, 1.549, 7.49 ] + }, + { + "time": 1.6, + "value": 9.5, + "curve": [ 1.663, 12.02, 1.846, 19.58 ] + }, + { + "time": 1.9333, + "value": 19.43, + "curve": [ 1.985, 19.4, 2.057, 2.98 ] + }, + { + "time": 2.2, + "value": 2.95, + "curve": [ 2.304, 3.55, 2.458, 10.8 ] + }, + { + "time": 2.5, + "value": 10.8, + "curve": [ 2.642, 10.8, 2.873, -2.54 ] + }, + { + "time": 2.9333, + "value": -2.55, + "curve": [ 3.09, -2.57, 3.08, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair2": { + "rotate": [ + { + "time": 1.0667, + "value": 26.19, + "curve": [ 1.158, 26.19, 1.368, 26 ] + }, + { + "time": 1.4333, + "value": 24.43, + "curve": [ 1.534, 22.03, 2, -29.14 ] + }, + { + "time": 2.2, + "value": -29.14, + "curve": [ 2.292, -29.14, 2.475, 6.71 ] + }, + { + "time": 2.5667, + "value": 6.71, + "curve": [ 2.675, 6.71, 2.814, -5.06 ] + }, + { + "time": 2.9, + "value": -5.06, + "curve": [ 2.973, -5.06, 3.123, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair4": { + "rotate": [ + { + "time": 1.0667, + "value": 5.21, + "curve": [ 1.108, 5.21, 1.192, 26.19 ] + }, + { + "time": 1.2333, + "value": 26.19, + "curve": [ 1.317, 26.19, 1.483, 10.63 ] + }, + { + "time": 1.5667, + "value": 10.63, + "curve": [ 1.627, 10.63, 1.642, 17.91 ] + }, + { + "time": 1.7, + "value": 17.94, + "curve": [ 1.761, 17.97, 1.774, 8.22 ] + }, + { + "time": 1.8, + "value": 3.33, + "curve": [ 1.839, -4.21, 1.95, -22.67 ] + }, + { + "time": 2, + "value": -22.67, + "curve": [ 2.025, -22.67, 2.123, -21.86 ] + }, + { + "time": 2.1667, + "value": -18.71, + "curve": [ 2.228, -14.31, 2.294, -0.3 ] + }, + { + "time": 2.3667, + "value": 6.36, + "curve": [ 2.433, 12.45, 2.494, 19.21 ] + }, + { + "time": 2.6, + "value": 19.21, + "curve": [ 2.729, 19.21, 2.854, 6.75 ] + }, + { + "time": 2.9333, + "value": 4.62, + "curve": [ 3.09, 0.45, 3.062, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair3": { + "rotate": [ + { + "time": 1.4333, + "curve": [ 1.45, 0, 1.452, 11.29 ] + }, + { + "time": 1.5, + "value": 11.21, + "curve": [ 1.596, 11.06, 1.573, -14.17 ] + }, + { + "time": 1.7333, + "value": -20.4, + "curve": [ 1.851, -24.98, 1.943, -28.45 ] + }, + { + "time": 2.2, + "value": -28.75, + "curve": [ 2.317, -28.75, 2.55, 7.04 ] + }, + { + "time": 2.6667, + "value": 7.04, + "curve": [ 2.792, 7.04, 2.885, -5.19 ] + }, + { + "time": 2.9667, + "value": -5.19, + "curve": [ 3.037, -5.19, 3.096, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair1": { + "rotate": [ + { + "time": 1.2333, + "curve": [ 1.283, 0, 1.349, 3.99 ] + }, + { + "time": 1.4333, + "value": 6.58, + "curve": [ 1.497, 8.54, 1.683, 9.35 ] + }, + { + "time": 1.7667, + "value": 9.35, + "curve": [ 1.825, 9.35, 1.945, -8.71 ] + }, + { + "time": 2, + "value": -11.15, + "curve": [ 2.058, -13.71, 2.2, -14.97 ] + }, + { + "time": 2.2667, + "value": -14.97, + "curve": [ 2.367, -14.97, 2.567, 18.77 ] + }, + { + "time": 2.6667, + "value": 18.77, + "curve": [ 2.733, 18.77, 2.817, 8.29 ] + }, + { + "time": 2.8667, + "value": 6.51, + "curve": [ 2.988, 2.17, 3.058, 0 ] + }, + { "time": 3.1667 } + ] + }, + "flare1": { + "rotate": [ + { "time": 1.1, "value": 8.2 } + ], + "translate": [ + { "time": 1.1, "x": -19.97, "y": 149.68 }, + { "time": 1.2, "x": 3.85, "y": 152.43 }, + { "time": 1.2333, "x": -15.42, "y": 152.29 } + ], + "scale": [ + { + "time": 1.1, + "x": 0.805, + "y": 0.805, + "curve": [ 1.119, 0.763, 1.16, 1.162, 1.117, 0.805, 1.15, 0.605 ] + }, + { + "time": 1.1667, + "x": 1.279, + "y": 0.605, + "curve": [ 1.177, 1.47, 1.192, 2.151, 1.175, 0.605, 1.192, 0.911 ] + }, + { + "time": 1.2, + "x": 2.151, + "y": 0.911, + "curve": [ 1.208, 2.151, 1.231, 1.668, 1.208, 0.911, 1.227, 0.844 ] + }, + { + "time": 1.2333, + "x": 1.608, + "y": 0.805, + "curve": [ 1.249, 1.205, 1.283, 0.547, 1.254, 0.685, 1.283, 0.416 ] + }, + { "time": 1.3, "x": 0.547, "y": 0.416 } + ], + "shear": [ + { "time": 1.1, "y": 4.63 }, + { "time": 1.2333, "x": -5.74, "y": 4.63 } + ] + }, + "flare2": { + "rotate": [ + { "time": 1.1, "value": 12.29 } + ], + "translate": [ + { "time": 1.1, "x": -8.63, "y": 132.96 }, + { "time": 1.2, "x": 4.35, "y": 132.93 } + ], + "scale": [ + { "time": 1.1, "x": 0.864, "y": 0.864 }, + { "time": 1.1667, "x": 0.945, "y": 0.945 }, + { "time": 1.2, "x": 1.511, "y": 1.081 } + ], + "shear": [ + { "time": 1.1, "y": 24.03 } + ] + }, + "flare3": { + "rotate": [ + { "time": 1.1667, "value": 2.88 } + ], + "translate": [ + { "time": 1.1667, "x": 3.24, "y": 114.81 } + ], + "scale": [ + { "time": 1.1667, "x": 0.668, "y": 0.668 } + ], + "shear": [ + { "time": 1.1667, "y": 38.59 } + ] + }, + "flare4": { + "rotate": [ + { "time": 1.1667, "value": -8.64 } + ], + "translate": [ + { "time": 1.1667, "x": -3.82, "y": 194.06 }, + { "time": 1.2667, "x": -1.82, "y": 198.47, "curve": "stepped" }, + { "time": 1.3, "x": -1.94, "y": 187.81 } + ], + "scale": [ + { "time": 1.1667, "x": 0.545, "y": 0.545 }, + { "time": 1.2667, "x": 0.757, "y": 0.757 } + ], + "shear": [ + { "time": 1.1667, "x": 7.42, "y": -22.04 } + ] + }, + "flare5": { + "translate": [ + { "time": 1.2, "x": -11.17, "y": 176.42 }, + { "time": 1.2333, "x": -8.56, "y": 179.04, "curve": "stepped" }, + { "time": 1.3, "x": -14.57, "y": 168.69 } + ], + "scale": [ + { "time": 1.2333, "x": 1.146 }, + { "time": 1.3, "x": 0.703, "y": 0.61 } + ], + "shear": [ + { "time": 1.2, "x": 6.9 } + ] + }, + "flare6": { + "rotate": [ + { "time": 1.2333, "value": -5.36 }, + { "time": 1.2667, "value": -0.54 } + ], + "translate": [ + { "time": 1.2333, "x": 14.52, "y": 204.67 }, + { "time": 1.2667, "x": 19.16, "y": 212.9, "curve": "stepped" }, + { "time": 1.3, "x": 9.23, "y": 202.85 } + ], + "scale": [ + { "time": 1.2333, "x": 0.777, "y": 0.49 }, + { "time": 1.2667, "x": 0.777, "y": 0.657 }, + { "time": 1.3, "x": 0.475, "y": 0.401 } + ] + }, + "flare7": { + "rotate": [ + { "time": 1.1, "value": 5.98 }, + { "time": 1.1333, "value": 32.82 } + ], + "translate": [ + { "time": 1.1, "x": -6.34, "y": 112.98 }, + { "time": 1.1333, "x": 2.66, "y": 111.6 } + ], + "scale": [ + { "time": 1.1, "x": 0.588, "y": 0.588 } + ], + "shear": [ + { "time": 1.1333, "x": -19.93 } + ] + }, + "flare8": { + "rotate": [ + { "time": 1.2333, "value": -6.85 } + ], + "translate": [ + { "time": 1.1667, "x": 66.67, "y": 125.52, "curve": "stepped" }, + { "time": 1.2, "x": 58.24, "y": 113.53, "curve": "stepped" }, + { "time": 1.2333, "x": 40.15, "y": 114.69 } + ], + "scale": [ + { "time": 1.1667, "x": 1.313, "y": 1.203 }, + { "time": 1.2333, "x": 1.038, "y": 0.95 } + ], + "shear": [ + { "time": 1.2, "y": -13.01 } + ] + }, + "flare9": { + "rotate": [ + { "time": 1.1667, "value": 2.9 } + ], + "translate": [ + { "time": 1.1667, "x": 28.45, "y": 151.35, "curve": "stepped" }, + { "time": 1.2, "x": 48.8, "y": 191.09, "curve": "stepped" }, + { "time": 1.2333, "x": 52, "y": 182.52, "curve": "stepped" }, + { "time": 1.2667, "x": 77.01, "y": 195.96 } + ], + "scale": [ + { "time": 1.1667, "x": 0.871, "y": 1.073 }, + { "time": 1.2, "x": 0.927, "y": 0.944 }, + { "time": 1.2333, "x": 1.165, "y": 1.336 } + ], + "shear": [ + { "time": 1.1667, "x": 7.95, "y": 25.48 } + ] + }, + "flare10": { + "rotate": [ + { "time": 1.1667, "value": 2.18 } + ], + "translate": [ + { "time": 1.1667, "x": 55.64, "y": 137.64, "curve": "stepped" }, + { "time": 1.2, "x": 90.49, "y": 151.07, "curve": "stepped" }, + { "time": 1.2333, "x": 114.06, "y": 153.05, "curve": "stepped" }, + { "time": 1.2667, "x": 90.44, "y": 164.61 } + ], + "scale": [ + { "time": 1.1667, "x": 2.657, "y": 0.891 }, + { "time": 1.2, "x": 3.314, "y": 1.425 }, + { "time": 1.2333, "x": 2.871, "y": 0.924 }, + { "time": 1.2667, "x": 2.317, "y": 0.775 } + ], + "shear": [ + { "time": 1.1667, "x": -1.35 } + ] + }, + "torso2": { + "rotate": [ + { + "time": 1, + "curve": [ 1.117, 0, 1.255, 24.94 ] + }, + { + "time": 1.4, + "value": 24.94, + "curve": [ 1.477, 24.94, 1.59, -17.62 ] + }, + { + "time": 1.6333, + "value": -19.48, + "curve": [ 1.717, -23.1, 1.784, -26.12 ] + }, + { + "time": 1.9333, + "value": -26.14, + "curve": [ 2.067, -26.15, 2.158, 4.3 ] + }, + { + "time": 2.3, + "value": 4.22, + "curve": [ 2.45, 4.13, 2.579, -1.76 ] + }, + { + "time": 2.7333, + "value": -1.8, + "curve": [ 2.816, -1.82, 2.857, -2.94 ] + }, + { + "time": 2.9333, + "value": -2.99, + "curve": [ 3.056, -3.08, 3.09, 0 ] + }, + { "time": 3.1667 } + ] + }, + "torso3": { + "rotate": [ + { + "time": 1.3, + "curve": [ 1.352, 0, 1.408, 6.47 ] + }, + { + "time": 1.4667, + "value": 6.43, + "curve": [ 1.55, 6.39, 1.723, -5.05 ] + }, + { + "time": 1.7333, + "value": -5.53, + "curve": [ 1.782, -7.72, 1.843, -16.94 ] + }, + { + "time": 1.9667, + "value": -16.86, + "curve": [ 2.111, -16.78, 2.259, -3.97 ] + }, + { + "time": 2.4, + "value": -2.43, + "curve": [ 2.525, -1.12, 2.639, -0.5 ] + }, + { + "time": 2.7333, + "value": -0.49, + "curve": [ 2.931, -0.47, 2.999, -2.15 ] + }, + { "time": 3.1667, "value": -2.15 } + ] + }, + "head-control": { + "translate": [ + { + "time": 1.2333, + "curve": [ 1.25, 0, 1.474, 6.89, 1.25, 0, 1.496, 0.98 ] + }, + { + "time": 1.6667, + "x": 11.99, + "y": -6.42, + "curve": [ 1.743, 14.01, 1.86, 14.33, 1.785, -11.55, 1.86, -27.1 ] + }, + { + "time": 1.9667, + "x": 13.91, + "y": -26.88, + "curve": [ 2.074, 13.49, 2.244, 8.13, 2.074, -26.65, 2.215, -21.78 ] + }, + { + "time": 2.3, + "x": 6.07, + "y": -16.64, + "curve": [ 2.416, 1.84, 2.497, -1.41, 2.417, -9.57, 2.526, -1.72 ] + }, + { + "time": 2.5667, + "x": -3.78, + "y": -1.71, + "curve": [ 2.661, -6.98, 2.76, -8.76, 2.692, -1.68, 2.821, -15.75 ] + }, + { + "time": 2.9, + "x": -8.32, + "y": -16.7, + "curve": [ 2.962, -8.12, 3.082, -0.04, 2.958, -17.39, 3.089, 0 ] + }, + { "time": 3.1667 } + ] + }, + "front-shoulder": { + "translate": [ + { + "time": 1.3333, + "curve": [ 1.488, 0, 1.717, 0.21, 1.488, 0, 1.688, -30.29 ] + }, + { + "time": 1.9, + "x": 0.83, + "y": -30.29, + "curve": [ 2.078, 1.43, 2.274, 2.88, 2.071, -30.29, 2.289, 4.48 ] + }, + { + "time": 2.4333, + "x": 2.89, + "y": 4.59, + "curve": [ 2.604, 2.89, 2.677, -0.68, 2.57, 4.7, 2.694, -2.43 ] + }, + { + "time": 2.7667, + "x": -0.67, + "y": -2.47, + "curve": [ 2.866, -0.67, 2.986, -0.07, 2.882, -2.47, 3.036, -0.06 ] + }, + { "time": 3.1667 } + ] + } + }, + "ik": { + "rear-leg-ik": [ + { "time": 3.1667, "softness": 10, "bendPositive": false } + ] + } + }, + "run": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" } + ] + } + }, + "bones": { + "front-thigh": { + "translate": [ + { + "x": -5.14, + "y": 11.13, + "curve": [ 0.033, -7.77, 0.112, -9.03, 0.034, 11.13, 0.108, 9.74 ] + }, + { + "time": 0.1667, + "x": -9.03, + "y": 7.99, + "curve": [ 0.23, -9.05, 0.314, -1.34, 0.236, 5.93, 0.28, 3.22 ] + }, + { + "time": 0.3333, + "x": 0.41, + "y": 3.19, + "curve": [ 0.352, 2.09, 0.449, 11.16, 0.384, 3.16, 0.449, 4.98 ] + }, + { + "time": 0.5, + "x": 11.17, + "y": 6.76, + "curve": [ 0.571, 10.79, 0.621, -1.83, 0.542, 8.21, 0.625, 11.13 ] + }, + { "time": 0.6667, "x": -5.14, "y": 11.13 } + ] + }, + "torso": { + "rotate": [ + { + "value": -37.66, + "curve": [ 0.034, -37.14, 0.107, -36.21 ] + }, + { + "time": 0.1333, + "value": -36.21, + "curve": [ 0.158, -36.21, 0.209, -38.8 ] + }, + { + "time": 0.2333, + "value": -38.79, + "curve": [ 0.259, -38.78, 0.313, -38.03 ] + }, + { + "time": 0.3333, + "value": -37.66, + "curve": [ 0.357, -37.21, 0.4, -36.21 ] + }, + { + "time": 0.4333, + "value": -36.21, + "curve": [ 0.458, -36.21, 0.539, -38.8 ] + }, + { + "time": 0.5667, + "value": -38.8, + "curve": [ 0.592, -38.8, 0.645, -38 ] + }, + { "time": 0.6667, "value": -37.66 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -16.41, + "y": 1.55, + "curve": [ 0.013, -15.67, 0.183, -8.55, 0.03, 2.39, 0.183, 6.17 ] + }, + { + "time": 0.2333, + "x": -8.55, + "y": 6.17, + "curve": [ 0.308, -8.55, 0.492, -19.75, 0.308, 6.17, 0.492, 0.61 ] + }, + { + "time": 0.5667, + "x": -19.75, + "y": 0.61, + "curve": [ 0.592, -19.75, 0.641, -18.06, 0.592, 0.61, 0.632, 0.78 ] + }, + { "time": 0.6667, "x": -16.41, "y": 1.55 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -39.03, + "curve": [ 0.051, -0.1, 0.145, 88.36 ] + }, + { + "time": 0.2333, + "value": 88.36, + "curve": [ 0.28, 88.76, 0.324, 59.52 ] + }, + { + "time": 0.3333, + "value": 51.13, + "curve": [ 0.358, 30.2, 0.445, -74.91 ] + }, + { + "time": 0.5667, + "value": -75.82, + "curve": [ 0.599, -76.06, 0.642, -55.72 ] + }, + { "time": 0.6667, "value": -39.03 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 20.54, + "curve": [ 0.052, 11.42, 0.089, 0.13 ] + }, + { + "time": 0.1333, + "value": 0.15, + "curve": [ 0.186, 0.17, 0.221, 26.29 ] + }, + { + "time": 0.2333, + "value": 32.37, + "curve": [ 0.247, 39.19, 0.286, 61.45 ] + }, + { + "time": 0.3333, + "value": 61.58, + "curve": [ 0.371, 61.69, 0.42, 55.79 ] + }, + { "time": 0.4667, "value": 49.68 }, + { "time": 0.6667, "value": 20.54 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16, + "curve": [ 0.014, -38.8, 0.036, -43.27 ] + }, + { + "time": 0.0667, + "value": -43.37, + "curve": [ 0.102, -43.49, 0.182, -28.46 ] + }, + { + "time": 0.2, + "value": -23.04, + "curve": [ 0.23, -13.87, 0.264, 3.86 ] + }, + { + "time": 0.3333, + "value": 3.7, + "curve": [ 0.38, 3.64, 0.535, -16.22 ] + }, + { "time": 0.5667, "value": -21.29 }, + { "time": 0.6667, "value": -36.16 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.5, + "curve": [ 0.028, 23.74, 0.128, -79.86 ] + }, + { + "time": 0.2333, + "value": -79.87, + "curve": [ 0.38, -79.88, 0.403, 63.25 ] + }, + { + "time": 0.5667, + "value": 64.13, + "curve": [ 0.607, 64.35, 0.644, 53.1 ] + }, + { "time": 0.6667, "value": 40.5 } + ], + "translate": [ + { + "x": -3.79, + "y": -0.77, + "curve": [ 0.044, -4.58, 0.169, -5.48, 0.044, 0.93, 0.169, 2.85 ] + }, + { + "time": 0.2333, + "x": -5.48, + "y": 2.85, + "curve": [ 0.346, -5.48, 0.475, -2.68, 0.346, 2.85, 0.475, -3.13 ] + }, + { + "time": 0.5667, + "x": -2.68, + "y": -3.13, + "curve": [ 0.611, -2.68, 0.642, -3.34, 0.611, -3.13, 0.642, -1.73 ] + }, + { "time": 0.6667, "x": -3.79, "y": -0.77 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": 28.28 }, + { + "time": 0.2333, + "value": -11.12, + "curve": [ 0.252, -14.12, 0.297, -19.37 ] + }, + { + "time": 0.3333, + "value": -19.38, + "curve": [ 0.435, -19.41, 0.522, 38.96 ] + }, + { + "time": 0.5667, + "value": 38.87, + "curve": [ 0.619, 38.76, 0.644, 32.01 ] + }, + { "time": 0.6667, "value": 28.28 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.88, + "curve": [ 0.024, 11.4, 0.075, 9.74 ] + }, + { + "time": 0.1, + "value": 9.74, + "curve": [ 0.125, 9.74, 0.208, 13.36 ] + }, + { + "time": 0.2333, + "value": 13.36, + "curve": [ 0.258, 13.36, 0.321, 12.2 ] + }, + { + "time": 0.3333, + "value": 11.88, + "curve": [ 0.365, 11.06, 0.408, 9.72 ] + }, + { + "time": 0.4333, + "value": 9.72, + "curve": [ 0.458, 9.72, 0.542, 13.36 ] + }, + { + "time": 0.5667, + "value": 13.36, + "curve": [ 0.592, 13.36, 0.636, 12.48 ] + }, + { "time": 0.6667, "value": 11.88 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.14, + "curve": [ 0.02, 11.99, 0.039, 8.94 ] + }, + { + "time": 0.0667, + "value": 8.93, + "curve": [ 0.122, 8.9, 0.232, 15.8 ] + }, + { + "time": 0.2667, + "value": 15.81, + "curve": [ 0.325, 15.82, 0.357, 8.95 ] + }, + { + "time": 0.4, + "value": 8.93, + "curve": [ 0.444, 8.91, 0.568, 15.8 ] + }, + { + "time": 0.6, + "value": 15.77, + "curve": [ 0.632, 15.74, 0.649, 14.05 ] + }, + { "time": 0.6667, "value": 13.14 } + ], + "scale": [ + { + "curve": [ 0.014, 0.996, 0.068, 0.991, 0.027, 1.005, 0.083, 1.012 ] + }, + { + "time": 0.1, + "x": 0.991, + "y": 1.012, + "curve": [ 0.128, 0.991, 0.205, 1.018, 0.128, 1.012, 0.197, 0.988 ] + }, + { + "time": 0.2333, + "x": 1.018, + "y": 0.988, + "curve": [ 0.272, 1.018, 0.305, 1.008, 0.262, 0.988, 0.311, 0.995 ] + }, + { + "time": 0.3333, + "curve": [ 0.351, 0.995, 0.417, 0.987, 0.359, 1.006, 0.417, 1.013 ] + }, + { + "time": 0.4333, + "x": 0.987, + "y": 1.013, + "curve": [ 0.467, 0.987, 0.533, 1.02, 0.467, 1.013, 0.533, 0.989 ] + }, + { + "time": 0.5667, + "x": 1.02, + "y": 0.989, + "curve": [ 0.592, 1.02, 0.652, 1.004, 0.592, 0.989, 0.644, 0.996 ] + }, + { "time": 0.6667 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.36, + "curve": [ 0.022, 16.28, 0.087, 20.25 ] + }, + { + "time": 0.1333, + "value": 20.19, + "curve": [ 0.168, 20.32, 0.254, -8.82 ] + }, + { + "time": 0.2667, + "value": -11.88, + "curve": [ 0.291, -17.91, 0.344, -24.11 ] + }, + { + "time": 0.4, + "value": -23.88, + "curve": [ 0.448, -23.69, 0.533, -15.47 ] + }, + { "time": 0.5667, "value": -8.69 }, + { "time": 0.6667, "value": 12.36 } + ] + }, + "hip": { + "rotate": [ + { "value": -8.24 } + ], + "translate": [ + { + "x": -3.6, + "y": -34.1, + "curve": [ 0.042, -3.84, 0.118, 7.62, 0.042, -33.74, 0.112, 20.55 ] + }, + { + "time": 0.1667, + "x": 7.61, + "y": 20.36, + "curve": [ 0.194, 7.6, 0.21, 5.06, 0.204, 20.65, 0.217, -8.69 ] + }, + { + "time": 0.2333, + "x": 1.68, + "y": -18.48, + "curve": [ 0.279, -4.99, 0.297, -5.64, 0.254, -31.08, 0.292, -34.55 ] + }, + { + "time": 0.3333, + "x": -5.76, + "y": -35, + "curve": [ 0.379, -5.9, 0.451, 6.8, 0.384, -35.56, 0.428, 17.6 ] + }, + { + "time": 0.5, + "x": 6.61, + "y": 17.01, + "curve": [ 0.536, 6.47, 0.545, 3.56, 0.533, 16.75, 0.548, -8.71 ] + }, + { + "time": 0.5667, + "x": 0.35, + "y": -18.81, + "curve": [ 0.597, -4.07, 0.642, -3.45, 0.584, -28.58, 0.642, -34.32 ] + }, + { "time": 0.6667, "x": -3.6, "y": -34.1 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": -62.54, + "curve": [ 0.015, -74.19, 0.056, -103.19 ] + }, + { + "time": 0.0667, + "value": -111.08, + "curve": [ 0.092, -129.44, 0.189, -146.55 ] + }, + { + "time": 0.2333, + "value": -146.32, + "curve": [ 0.285, -146.06, 0.32, -125.1 ] + }, + { "time": 0.3333, "value": -117.24 }, + { + "time": 0.5, + "value": -35.07, + "curve": [ 0.522, -28.64, 0.546, -24.84 ] + }, + { + "time": 0.5667, + "value": -24.9, + "curve": [ 0.595, -25, 0.623, -40.82 ] + }, + { "time": 0.6667, "value": -62.54 } + ], + "translate": [ + { "x": 16.34, "y": 0.18 }, + { + "time": 0.0667, + "x": -101.43, + "y": 8.04, + "curve": [ 0.085, -131.35, 0.129, -207.69, 0.08, 14.9, 0.124, 113.28 ] + }, + { + "time": 0.1667, + "x": -207.92, + "y": 145.81, + "curve": [ 0.196, -208.13, 0.21, -202.91, 0.186, 160.26, 0.206, 163.48 ] + }, + { + "time": 0.2333, + "x": -189.94, + "y": 163.85, + "curve": [ 0.27, -169.94, 0.31, -126.19, 0.269, 164.35, 0.316, 85.97 ] + }, + { + "time": 0.3333, + "x": -90.56, + "y": 78.57, + "curve": [ 0.355, -57.99, 0.376, -29.14, 0.35, 71.55, 0.376, 66.4 ] + }, + { + "time": 0.4, + "x": 2.87, + "y": 66.38, + "curve": [ 0.412, 19.24, 0.469, 90.73, 0.429, 66.37, 0.469, 70.66 ] + }, + { + "time": 0.5, + "x": 117.18, + "y": 70.46, + "curve": [ 0.522, 136.24, 0.542, 151.33, 0.539, 70.2, 0.555, 38.25 ] + }, + { + "time": 0.5667, + "x": 151.49, + "y": 25.29, + "curve": [ 0.578, 146.76, 0.586, 133.13, 0.572, 19.7, 0.582, 12.23 ] + }, + { "time": 0.6, "x": 115.02, "y": 0.1 }, + { "time": 0.6667, "x": 16.34, "y": 0.18 } + ] + }, + "front-leg-target": { + "translate": [ + { "x": -13.95, "y": -30.34 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": 18.55 }, + { + "time": 0.2333, + "value": 167.84, + "curve": [ 0.246, 153.66, 0.256, 129.74 ] + }, + { + "time": 0.2667, + "value": 124.32, + "curve": [ 0.296, 124.43, 0.313, 129.93 ] + }, + { + "time": 0.3667, + "value": 129.87, + "curve": [ 0.421, 128.32, 0.519, 0.98 ] + }, + { + "time": 0.5667, + "curve": [ 0.6, 0.27, 0.642, 4.73 ] + }, + { "time": 0.6667, "value": 18.55 } + ], + "translate": [ + { + "x": -176.39, + "y": 134.12, + "curve": [ 0.018, -142.26, 0.054, -94.41, 0.01, 120.96, 0.044, 84.08 ] + }, + { + "time": 0.0667, + "x": -73.56, + "y": 76.68, + "curve": [ 0.086, -42.82, 0.194, 101.2, 0.098, 66.73, 0.198, 60.88 ] + }, + { "time": 0.2333, "x": 98.32, "y": 32.17 }, + { "time": 0.2667, "x": 49.13, "y": -0.63 }, + { + "time": 0.4, + "x": -147.9, + "y": 0.32, + "curve": [ 0.414, -168.78, 0.478, -284.76, 0.43, 30.09, 0.478, 129.14 ] + }, + { + "time": 0.5, + "x": -283.37, + "y": 167.12, + "curve": [ 0.526, -285.66, 0.548, -280.54, 0.516, 194.84, 0.55, 216.53 ] + }, + { + "time": 0.5667, + "x": -266.98, + "y": 216.12, + "curve": [ 0.581, -256.27, 0.643, -206.54, 0.61, 214.82, 0.65, 145.33 ] + }, + { "time": 0.6667, "x": -176.39, "y": 134.12 } + ] + }, + "rear-leg-target": { + "translate": [ + { "x": 85, "y": -33.59 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "value": -147.04, + "curve": [ 0.033, -113.4, 0.161, 44.34 ] + }, + { + "time": 0.2333, + "value": 43.48, + "curve": [ 0.24, 43.41, 0.282, 35.72 ] + }, + { + "time": 0.3, + "value": 0.29, + "curve": [ 0.347, 0.28, 0.396, 4.27 ] + }, + { + "time": 0.4, + "curve": [ 0.424, -23.8, 0.525, -181.39 ] + }, + { + "time": 0.5667, + "value": -181.39, + "curve": [ 0.592, -181.39, 0.642, -169.09 ] + }, + { "time": 0.6667, "value": -147.04 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -0.25, + "curve": [ 0.008, -0.25, 0.056, 1.73 ] + }, + { + "time": 0.0667, + "value": -7.68, + "curve": [ 0.075, -43.13, 0.15, -130.44 ] + }, + { + "time": 0.2, + "value": -130.08, + "curve": [ 0.239, -129.79, 0.272, -126.8 ] + }, + { + "time": 0.3, + "value": -116.24, + "curve": [ 0.333, -103.91, 0.348, -86.1 ] + }, + { + "time": 0.3667, + "value": -71.08, + "curve": [ 0.386, -55.25, 0.415, -32.44 ] + }, + { + "time": 0.4333, + "value": -21.63, + "curve": [ 0.47, -0.01, 0.542, 33.42 ] + }, + { + "time": 0.5667, + "value": 33.2, + "curve": [ 0.622, 32.7, 0.569, 0.64 ] + }, + { "time": 0.6667, "value": -0.25 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.087, -6.81, 0.143, -5.75 ] + }, + { + "time": 0.1667, + "value": -4.3, + "curve": [ 0.183, -3.28, 0.209, 2.79 ] + }, + { + "time": 0.2333, + "value": 2.78, + "curve": [ 0.262, 2.77, 0.305, -6.63 ] + }, + { + "time": 0.3333, + "value": -6.64, + "curve": [ 0.419, -6.68, 0.49, -4.84 ] + }, + { + "time": 0.5, + "value": -4.38, + "curve": [ 0.518, -3.56, 0.574, 2.32 ] + }, + { + "time": 0.6, + "value": 2.33, + "curve": [ 0.643, 2.35, 0.633, -6.81 ] + }, + { "time": 0.6667, "value": -6.81 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.014, -3.17, 0.109, 43.93 ] + }, + { + "time": 0.1333, + "value": 43.95, + "curve": [ 0.177, 43.97, 0.192, -13.76 ] + }, + { + "time": 0.2667, + "value": -13.83, + "curve": [ 0.302, -13.72, 0.322, -8.86 ] + }, + { + "time": 0.3333, + "value": -6.6, + "curve": [ 0.349, -3.5, 0.436, 41.1 ] + }, + { + "time": 0.4667, + "value": 41.05, + "curve": [ 0.51, 40.99, 0.549, -14.06 ] + }, + { + "time": 0.6, + "value": -14.18, + "curve": [ 0.63, -14.26, 0.656, -9.04 ] + }, + { "time": 0.6667, "value": -6.81 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.079, -6.83, 0.108, 0.3 ] + }, + { + "time": 0.1333, + "value": 1.96, + "curve": [ 0.177, 4.89, 0.208, 6.28 ] + }, + { + "time": 0.2333, + "value": 6.29, + "curve": [ 0.313, 6.31, 0.383, 3.49 ] + }, + { + "time": 0.4, + "value": 2.58, + "curve": [ 0.442, 0.28, 0.523, -6.81 ] + }, + { "time": 0.6, "value": -6.81 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.011, -4.06, 0.108, 24.92 ] + }, + { + "time": 0.1333, + "value": 24.92, + "curve": [ 0.158, 24.92, 0.208, -10.62 ] + }, + { + "time": 0.2333, + "value": -10.62, + "curve": [ 0.254, -10.62, 0.312, -9.73 ] + }, + { + "time": 0.3333, + "value": -6.4, + "curve": [ 0.356, -2.95, 0.438, 24.93 ] + }, + { + "time": 0.4667, + "value": 24.93, + "curve": [ 0.492, 24.93, 0.575, -9.78 ] + }, + { + "time": 0.6, + "value": -9.78, + "curve": [ 0.617, -9.78, 0.655, -8.63 ] + }, + { "time": 0.6667, "value": -6.81 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 3.5, + "curve": [ 0.07, 3.51, 0.075, 8.69 ] + }, + { + "time": 0.1, + "value": 8.69, + "curve": [ 0.139, 8.69, 0.214, 6.9 ] + }, + { + "time": 0.2333, + "value": 6.33, + "curve": [ 0.266, 5.34, 0.285, 3.48 ] + }, + { + "time": 0.3333, + "value": 3.48, + "curve": [ 0.398, 3.48, 0.408, 8.68 ] + }, + { + "time": 0.4333, + "value": 8.68, + "curve": [ 0.458, 8.68, 0.551, 6.8 ] + }, + { + "time": 0.5667, + "value": 6.26, + "curve": [ 0.598, 5.17, 0.642, 3.49 ] + }, + { "time": 0.6667, "value": 3.5 } + ] + }, + "torso3": { + "rotate": [ + { + "value": 4.52, + "curve": [ 0.067, 4.54, 0.075, -7.27 ] + }, + { + "time": 0.1, + "value": -7.27, + "curve": [ 0.125, -7.27, 0.227, 0.84 ] + }, + { + "time": 0.2333, + "value": 1.24, + "curve": [ 0.254, 2.5, 0.301, 4.51 ] + }, + { + "time": 0.3333, + "value": 4.52, + "curve": [ 0.386, 4.54, 0.408, -7.35 ] + }, + { + "time": 0.4333, + "value": -7.35, + "curve": [ 0.458, -7.35, 0.549, -0.14 ] + }, + { + "time": 0.5667, + "value": 0.95, + "curve": [ 0.586, 2.18, 0.632, 4.54 ] + }, + { "time": 0.6667, "value": 4.52 } + ] + }, + "aim-constraint-target": { + "rotate": [ + { "value": 30.57 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": -6.5 } + ] + }, + "front-foot": { + "rotate": [ + { "value": 4.5 } + ] + }, + "head-control": { + "translate": [ + { + "y": -9.94, + "curve": [ 0.058, 0, 0.175, -15.32, 0.044, -4.19, 0.175, 5 ] + }, + { + "time": 0.2333, + "x": -15.32, + "y": 5, + "curve": [ 0.317, -15.32, 0.429, -9.74, 0.317, 5, 0.382, -31.71 ] + }, + { + "time": 0.4667, + "x": -7.81, + "y": -31.59, + "curve": [ 0.507, -5.76, 0.617, 0, 0.549, -31.47, 0.628, -13.33 ] + }, + { "time": 0.6667, "y": -9.94 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": -0.74, + "y": 11.22, + "curve": [ 0.061, -0.74, 0.144, 1.17, 0.061, 11.22, 0.143, -17.93 ] + }, + { + "time": 0.2333, + "x": 1.19, + "y": -17.9, + "curve": [ 0.54, 1.25, 0.558, -0.74, 0.545, -17.8, 0.558, 11.22 ] + }, + { "time": 0.6667, "x": -0.74, "y": 11.22 } + ] + }, + "back-shoulder": { + "translate": [ + { + "curve": [ 0.083, 0, 0.25, 0, 0.083, 0, 0.25, 8.93 ] + }, + { + "time": 0.3333, + "y": 8.93, + "curve": [ 0.417, 0, 0.583, 0, 0.417, 8.93, 0.583, 0 ] + }, + { "time": 0.6667 } + ] + } + }, + "ik": { + "front-leg-ik": [ + { "softness": 10, "bendPositive": false }, + { "time": 0.5667, "softness": 14.8, "bendPositive": false }, + { "time": 0.6, "softness": 48.2, "bendPositive": false }, + { "time": 0.6667, "softness": 10, "bendPositive": false } + ], + "rear-leg-ik": [ + { "bendPositive": false }, + { "time": 0.1667, "softness": 22.5, "bendPositive": false }, + { "time": 0.3, "softness": 61.4, "bendPositive": false }, + { "time": 0.6667, "bendPositive": false } + ] + }, + "events": [ + { "time": 0.2333, "name": "footstep" }, + { "time": 0.5667, "name": "footstep" } + ] + }, + "run-to-idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-foot-target": { + "translate": [ + { + "x": -16.5, + "y": 3.41, + "curve": [ 0.033, -16.5, 0.1, -69.06, 0.033, 3.41, 0.1, 0 ] + }, + { "time": 0.1333, "x": -69.06 } + ] + }, + "hip": { + "translate": [ + { + "x": -28.78, + "y": -72.96, + "curve": [ 0.036, -28.63, 0.2, -10.85, 0.135, -62.35, 0.2, -23.15 ] + }, + { "time": 0.2667, "x": -11.97, "y": -23.15 } + ] + }, + "rear-foot-target": { + "translate": [ + { + "x": 33.15, + "y": 31.61, + "curve": [ 0.017, 33.15, 0.05, 24.41, 0.017, 31.61, 0.041, 20.73 ] + }, + { + "time": 0.0667, + "x": 24.41, + "y": 0.19, + "curve": [ 0.117, 24.41, 0.217, 48.87, 0.117, 0.19, 0.217, 0 ] + }, + { "time": 0.2667, "x": 48.87 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -80.61, + "curve": [ 0.067, -80.61, 0.2, -60.87 ] + }, + { "time": 0.2667, "value": -60.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 8.79, + "curve": [ 0.041, 8.79, 0.115, 6.3 ] + }, + { + "time": 0.1667, + "value": 6.41, + "curve": [ 0.201, 6.48, 0.241, 42.46 ] + }, + { "time": 0.2667, "value": 42.46 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 55.3, + "curve": [ 0.067, 55.3, 0.2, 39.2 ] + }, + { "time": 0.2667, "value": 39.2 } + ] + }, + "head": { + "rotate": [ + { + "curve": [ 0.05, 0, 0.083, 2.67 ] + }, + { + "time": 0.1333, + "value": 2.67, + "curve": [ 0.15, 2.67, 0.25, -6.75 ] + }, + { "time": 0.2667, "value": -6.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": 38.26, + "curve": [ 0.041, 38.26, 0.127, -2.19 ] + }, + { + "time": 0.1667, + "value": -3, + "curve": [ 0.209, -3.84, 0.241, 0 ] + }, + { "time": 0.2667 } + ], + "scale": [ + { + "x": 0.844, + "curve": [ 0.067, 0.844, 0.2, 1, 0.067, 1, 0.2, 1 ] + }, + { "time": 0.2667 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 57.24, + "curve": [ 0.067, 57.24, 0.2, 0 ] + }, + { "time": 0.2667 } + ] + }, + "gun": { + "rotate": [ + { + "value": 2.28, + "curve": [ 0.041, 2.28, 0.105, 15.34 ] + }, + { + "time": 0.1667, + "value": 15.32, + "curve": [ 0.205, 15.31, 0.241, 0 ] + }, + { "time": 0.2667 } + ] + }, + "torso": { + "rotate": [ + { + "value": -12.98, + "curve": [ 0.033, -12.98, 0.103, -14.81 ] + }, + { + "time": 0.1333, + "value": -16.63, + "curve": [ 0.168, -18.69, 0.233, -22.88 ] + }, + { "time": 0.2667, "value": -22.88 } + ], + "scale": [ + { + "x": 0.963, + "y": 1.074, + "curve": [ 0.067, 0.963, 0.132, 1, 0.067, 1.074, 0.132, 1 ] + }, + { "time": 0.2667 } + ] + }, + "neck": { + "rotate": [ + {}, + { "time": 0.2667, "value": 3.78 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 0.88 ] + }, + { + "time": 0.1333, + "value": 0.88, + "curve": [ 0.167, 0.88, 0.233, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 15.97 ] + }, + { + "time": 0.1333, + "value": 15.97, + "curve": [ 0.167, 15.97, 0.233, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 10.76 ] + }, + { + "time": 0.1333, + "value": 10.76, + "curve": [ 0.167, 10.76, 0.233, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair2": { + "rotate": [ + { + "curve": [ 0.014, -2.28, 0.042, -7.84 ] + }, + { + "time": 0.0667, + "value": -7.82, + "curve": [ 0.108, -7.79, 0.166, 6.57 ] + }, + { + "time": 0.2, + "value": 6.67, + "curve": [ 0.222, 6.73, 0.255, 1.98 ] + }, + { "time": 0.2667 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.041, 0, 0.107, 3.03 ] + }, + { + "time": 0.1667, + "value": 3.03, + "curve": [ 0.205, 3.03, 0.241, 0 ] + }, + { "time": 0.2667 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.049, 0, 0.166, 0.66 ] + }, + { + "time": 0.2, + "value": 0.66, + "curve": [ 0.232, 0.65, 0.249, -2.15 ] + }, + { "time": 0.2667, "value": -2.15 } + ] + }, + "head-control": { + "translate": [ + { "x": -10.12, "y": 8.71 }, + { "time": 0.2667 } + ] + }, + "front-shoulder": { + "translate": [ + { "x": 4.91, "y": 11.54 }, + { "time": 0.2667 } + ] + } + } + }, + "shoot": { + "slots": { + "muzzle": { + "rgba": [ + { "time": 0.1333, "color": "ffffffff" }, + { "time": 0.2, "color": "ffffff62" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle01" }, + { "time": 0.0667, "name": "muzzle02" }, + { "time": 0.1, "name": "muzzle03" }, + { "time": 0.1333, "name": "muzzle04" }, + { "time": 0.1667, "name": "muzzle05" }, + { "time": 0.2, "name": null } + ] + }, + "muzzle-glow": { + "rgba": [ + { "color": "ff0c0c00" }, + { + "time": 0.0333, + "color": "ffc9adff", + "curve": [ 0.255, 1, 0.273, 1, 0.255, 0.76, 0.273, 0.4, 0.255, 0.65, 0.273, 0.22, 0.255, 1, 0.273, 1 ] + }, + { "time": 0.3, "color": "ff400cff" }, + { "time": 0.6333, "color": "ff0c0c00" } + ], + "attachment": [ + { "name": "muzzle-glow" } + ] + }, + "muzzle-ring": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.202, 0.85, 0.214, 0.84, 0.202, 0.73, 0.214, 0.73, 0.202, 1, 0.214, 1, 0.202, 1, 0.214, 0.21 ] + }, + { "time": 0.2333, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2333, "name": null } + ] + }, + "muzzle-ring2": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.174, 0.85, 0.184, 0.84, 0.174, 0.73, 0.184, 0.73, 0.174, 1, 0.184, 1, 0.174, 1, 0.184, 0.21 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2, "name": null } + ] + }, + "muzzle-ring3": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.174, 0.85, 0.184, 0.84, 0.174, 0.73, 0.184, 0.73, 0.174, 1, 0.184, 1, 0.174, 1, 0.184, 0.21 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2, "name": null } + ] + }, + "muzzle-ring4": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.174, 0.85, 0.184, 0.84, 0.174, 0.73, 0.184, 0.73, 0.174, 1, 0.184, 1, 0.174, 1, 0.184, 0.21 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2, "name": null } + ] + } + }, + "bones": { + "gun": { + "rotate": [ + { + "time": 0.0667, + "curve": [ 0.094, 25.89, 0.112, 45.27 ] + }, + { + "time": 0.1333, + "value": 45.35, + "curve": [ 0.192, 45.28, 0.18, -0.09 ] + }, + { "time": 0.6333 } + ] + }, + "muzzle": { + "translate": [ + { "x": -11.02, "y": 25.16 } + ] + }, + "rear-upper-arm": { + "translate": [ + { + "time": 0.0333, + "curve": [ 0.045, 0.91, 0.083, 3.46, 0.044, 0.86, 0.083, 3.32 ] + }, + { + "time": 0.1, + "x": 3.46, + "y": 3.32, + "curve": [ 0.133, 3.46, 0.176, -0.1, 0.133, 3.32, 0.169, 0 ] + }, + { "time": 0.2333 } + ] + }, + "rear-bracer": { + "translate": [ + { + "time": 0.0333, + "curve": [ 0.075, -3.78, 0.083, -4.36, 0.08, -2.7, 0.083, -2.88 ] + }, + { + "time": 0.1, + "x": -4.36, + "y": -2.88, + "curve": [ 0.133, -4.36, 0.168, 0.18, 0.133, -2.88, 0.167, 0 ] + }, + { "time": 0.2333 } + ] + }, + "gun-tip": { + "translate": [ + {}, + { "time": 0.3, "x": 3.15, "y": 0.39 } + ], + "scale": [ + { "x": 0.366, "y": 0.366 }, + { "time": 0.0333, "x": 1.453, "y": 1.453 }, + { "time": 0.3, "x": 0.366, "y": 0.366 } + ] + }, + "muzzle-ring": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2333, "x": 64.47 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2333, "x": 5.951, "y": 5.951 } + ] + }, + "muzzle-ring2": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 172.57 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 4, "y": 4 } + ] + }, + "muzzle-ring3": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 277.17 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 2, "y": 2 } + ] + }, + "muzzle-ring4": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 392.06 } + ] + } + } + }, + "walk": { + "bones": { + "rear-foot-target": { + "rotate": [ + { + "value": -32.82, + "curve": [ 0.035, -42.69, 0.057, -70.49 ] + }, + { + "time": 0.1, + "value": -70.59, + "curve": [ 0.236, -70.78, 0.335, -9.87 ] + }, + { + "time": 0.3667, + "value": -1.56, + "curve": [ 0.393, 5.5, 0.477, 13.96 ] + }, + { + "time": 0.5, + "value": 13.96, + "curve": [ 0.519, 13.96, 0.508, 0.13 ] + }, + { "time": 0.5667, "value": -0.28 }, + { + "time": 0.7333, + "value": -0.28, + "curve": [ 0.827, -0.06, 0.958, -21.07 ] + }, + { "time": 1, "value": -32.82 } + ], + "translate": [ + { + "x": -167.32, + "y": 0.58, + "curve": [ 0.022, -180.55, 0.075, -235.51, 0.045, 0.58, 0.075, 30.12 ] + }, + { + "time": 0.1, + "x": -235.51, + "y": 39.92, + "curve": [ 0.142, -235.51, 0.208, -201.73, 0.138, 54.94, 0.18, 60.78 ] + }, + { + "time": 0.2333, + "x": -176.33, + "y": 61.48, + "curve": [ 0.272, -136.61, 0.321, -45.18, 0.275, 62.02, 0.321, 56.6 ] + }, + { + "time": 0.3667, + "x": 8.44, + "y": 49.67, + "curve": [ 0.403, 51.03, 0.486, 66.86, 0.401, 44.37, 0.48, 23.11 ] + }, + { "time": 0.5, "x": 66.57, "y": 14.22 }, + { "time": 0.5333, "x": 52.58, "y": 0.6 }, + { "time": 1, "x": -167.32, "y": 0.58 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": 18.19, + "curve": [ 0.01, 11.17, 0.043, 1.37 ] + }, + { "time": 0.1, "value": 0.47 }, + { + "time": 0.2333, + "value": 0.55, + "curve": [ 0.364, 0.3, 0.515, -80.48 ] + }, + { + "time": 0.7333, + "value": -80.78, + "curve": [ 0.788, -80.38, 0.921, 17.42 ] + }, + { "time": 1, "value": 18.19 } + ], + "translate": [ + { + "x": 139.21, + "y": 22.94, + "curve": [ 0.025, 139.21, 0.069, 111.46, 0.031, 3.25, 0.075, 0.06 ] + }, + { "time": 0.1, "x": 96.69, "y": 0.06 }, + { + "time": 0.5, + "x": -94.87, + "y": -0.03, + "curve": [ 0.518, -106.82, 0.575, -152.56, 0.534, 5.42, 0.557, 38.46 ] + }, + { + "time": 0.6, + "x": -152.56, + "y": 57.05, + "curve": [ 0.633, -152.56, 0.688, -128.05, 0.643, 75.61, 0.7, 84.14 ] + }, + { + "time": 0.7333, + "x": -109.42, + "y": 84.14, + "curve": [ 0.771, -93.91, 0.832, -30.64, 0.787, 84.14, 0.799, 89.65 ] + }, + { + "time": 0.8667, + "x": 17, + "y": 75.25, + "curve": [ 0.903, 66.18, 0.967, 139.21, 0.932, 61.53, 0.967, 44.02 ] + }, + { "time": 1, "x": 139.21, "y": 22.94 } + ] + }, + "hip": { + "rotate": [ + { "value": -4.35 } + ], + "translate": [ + { + "x": -2.86, + "y": -13.86, + "curve": [ 0.025, -2.84, 0.067, -2.82, 0.028, -19.14, 0.054, -24.02 ] + }, + { + "time": 0.1, + "x": -2.61, + "y": -24.19, + "curve": [ 0.143, -2.34, 0.202, -1.79, 0.152, -23.98, 0.213, -14.81 ] + }, + { + "time": 0.2667, + "x": -1.21, + "y": -7.12, + "curve": [ 0.308, -0.86, 0.345, -0.51, 0.306, -1.63, 0.341, 3.15 ] + }, + { + "time": 0.3667, + "x": -0.33, + "y": 3.15, + "curve": [ 0.41, 0.02, 0.458, 0.26, 0.427, 3.3, 0.481, -6.75 ] + }, + { + "time": 0.5, + "x": 0.26, + "y": -10.59, + "curve": [ 0.553, 0.26, 0.559, 0.2, 0.519, -14.41, 0.548, -23.88 ] + }, + { + "time": 0.6, + "x": -0.17, + "y": -23.71, + "curve": [ 0.663, -0.72, 0.798, -2.09, 0.702, -23.36, 0.802, 3.53 ] + }, + { + "time": 0.8667, + "x": -2.46, + "y": 3.48, + "curve": [ 0.901, -2.63, 0.967, -2.87, 0.913, 3.45, 0.967, -7.64 ] + }, + { "time": 1, "x": -2.86, "y": -13.86 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": 28.96, + "curve": [ 0.056, 28.74, 0.049, 19.6 ] + }, + { "time": 0.0667, "value": 1.68 }, + { + "time": 0.5, + "value": -10, + "curve": [ 0.525, -10, 0.592, -54.69 ] + }, + { + "time": 0.6, + "value": -59.66, + "curve": [ 0.623, -74.54, 0.674, -101.78 ] + }, + { + "time": 0.7333, + "value": -101.78, + "curve": [ 0.812, -101.78, 0.855, -84.67 ] + }, + { + "time": 0.8667, + "value": -63.53, + "curve": [ 0.869, -58.38, 0.975, 28.96 ] + }, + { "time": 1, "value": 28.96 } + ] + }, + "torso": { + "rotate": [ + { + "value": -20.72, + "curve": [ 0.025, -20.57, 0.071, -20.04 ] + }, + { + "time": 0.1333, + "value": -20.04, + "curve": [ 0.187, -20.04, 0.285, -21.16 ] + }, + { + "time": 0.3667, + "value": -21.16, + "curve": [ 0.405, -21.16, 0.47, -20.9 ] + }, + { + "time": 0.5, + "value": -20.71, + "curve": [ 0.518, -20.6, 0.582, -20.03 ] + }, + { + "time": 0.6333, + "value": -20.04, + "curve": [ 0.709, -20.05, 0.815, -21.18 ] + }, + { + "time": 0.8667, + "value": -21.18, + "curve": [ 0.908, -21.18, 0.971, -20.93 ] + }, + { "time": 1, "value": -20.72 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.78, + "curve": [ 0.025, 17.93, 0.071, 18.46 ] + }, + { + "time": 0.1333, + "value": 18.46, + "curve": [ 0.187, 18.46, 0.285, 17.34 ] + }, + { + "time": 0.3667, + "value": 17.34, + "curve": [ 0.405, 17.34, 0.47, 17.6 ] + }, + { + "time": 0.5, + "value": 17.79, + "curve": [ 0.518, 17.9, 0.582, 18.47 ] + }, + { + "time": 0.6333, + "value": 18.46, + "curve": [ 0.709, 18.45, 0.815, 17.32 ] + }, + { + "time": 0.8667, + "value": 17.32, + "curve": [ 0.908, 17.32, 0.971, 17.57 ] + }, + { "time": 1, "value": 17.78 } + ] + }, + "head": { + "rotate": [ + { + "value": -12.23, + "curve": [ 0.061, -12.23, 0.191, -7.45 ] + }, + { + "time": 0.2667, + "value": -7.43, + "curve": [ 0.341, -7.42, 0.421, -12.23 ] + }, + { + "time": 0.5, + "value": -12.23, + "curve": [ 0.567, -12.26, 0.694, -7.46 ] + }, + { + "time": 0.7667, + "value": -7.47, + "curve": [ 0.853, -7.49, 0.943, -12.23 ] + }, + { "time": 1, "value": -12.23 } + ], + "scale": [ + { + "curve": [ 0.039, 1, 0.084, 0.991, 0.039, 1, 0.084, 1.019 ] + }, + { + "time": 0.1333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.205, 0.991, 0.318, 1.019, 0.205, 1.019, 0.337, 0.992 ] + }, + { + "time": 0.4, + "x": 1.019, + "y": 0.992, + "curve": [ 0.456, 1.019, 0.494, 1.001, 0.483, 0.991, 0.493, 0.999 ] + }, + { + "time": 0.5, + "curve": [ 0.508, 0.998, 0.584, 0.991, 0.51, 1.002, 0.584, 1.019 ] + }, + { + "time": 0.6333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.705, 0.991, 0.818, 1.019, 0.705, 1.019, 0.837, 0.992 ] + }, + { + "time": 0.9, + "x": 1.019, + "y": 0.992, + "curve": [ 0.956, 1.019, 0.955, 1, 0.983, 0.991, 0.955, 1 ] + }, + { "time": 1 } + ] + }, + "back-foot-tip": { + "rotate": [ + { "value": 4.09 }, + { "time": 0.0333, "value": 3.05 }, + { + "time": 0.1, + "value": -59.01, + "curve": [ 0.124, -72.97, 0.169, -100.05 ] + }, + { + "time": 0.2333, + "value": -99.71, + "curve": [ 0.326, -99.21, 0.349, -37.4 ] + }, + { + "time": 0.3667, + "value": -17.85, + "curve": [ 0.388, 4.74, 0.451, 32.35 ] + }, + { + "time": 0.5, + "value": 32.4, + "curve": [ 0.537, 32.44, 0.566, 6.43 ] + }, + { "time": 0.5667, "value": 2 }, + { "time": 1, "value": 4.09 } + ] + }, + "front-thigh": { + "translate": [ + { + "x": 17.15, + "y": -0.09, + "curve": [ 0.178, 17.14, 0.295, -4.26, 0.009, -0.09, 0.475, 0.02 ] + }, + { + "time": 0.5, + "x": -4.26, + "y": 0.02, + "curve": [ 0.705, -4.27, 0.848, 17.15, 0.525, 0.02, 0.975, -0.09 ] + }, + { "time": 1, "x": 17.15, "y": -0.09 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -17.71, + "y": -4.63, + "curve": [ 0.036, -19.81, 0.043, -20.86, 0.036, -4.63, 0.05, -7.03 ] + }, + { + "time": 0.1, + "x": -20.95, + "y": -7.06, + "curve": [ 0.162, -21.05, 0.4, 7.79, 0.2, -7.13, 0.4, -1.9 ] + }, + { + "time": 0.5, + "x": 7.79, + "y": -1.94, + "curve": [ 0.612, 7.69, 0.875, -10.49, 0.592, -1.97, 0.917, -3.25 ] + }, + { "time": 1, "x": -17.71, "y": -4.63 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 1, + "curve": [ 0.006, 1.2, 0.084, 2.88 ] + }, + { + "time": 0.1333, + "value": 2.88, + "curve": [ 0.205, 2.88, 0.284, -1.17 ] + }, + { + "time": 0.3667, + "value": -1.17, + "curve": [ 0.411, -1.17, 0.481, 0.57 ] + }, + { + "time": 0.5, + "value": 1, + "curve": [ 0.515, 1.33, 0.59, 2.83 ] + }, + { + "time": 0.6333, + "value": 2.85, + "curve": [ 0.683, 2.86, 0.796, -1.2 ] + }, + { + "time": 0.8667, + "value": -1.2, + "curve": [ 0.916, -1.2, 0.984, 0.62 ] + }, + { "time": 1, "value": 1 } + ] + }, + "torso3": { + "rotate": [ + { "value": -1.81 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -9.51, + "curve": [ 0.021, -13.32, 0.058, -19.4 ] + }, + { + "time": 0.1, + "value": -19.4, + "curve": [ 0.238, -19.69, 0.337, 7.78 ] + }, + { + "time": 0.3667, + "value": 16.2, + "curve": [ 0.399, 25.42, 0.497, 60.19 ] + }, + { + "time": 0.6, + "value": 60.26, + "curve": [ 0.719, 60.13, 0.845, 27.61 ] + }, + { + "time": 0.8667, + "value": 22.45, + "curve": [ 0.892, 16.38, 0.979, -3.27 ] + }, + { "time": 1, "value": -9.51 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 13.57, + "curve": [ 0.022, 9.71, 0.147, -3.78 ] + }, + { + "time": 0.3667, + "value": -3.69, + "curve": [ 0.457, -3.66, 0.479, 0.83 ] + }, + { + "time": 0.5, + "value": 4.05, + "curve": [ 0.513, 6.08, 0.635, 30.8 ] + }, + { + "time": 0.8, + "value": 30.92, + "curve": [ 0.974, 31, 0.98, 18.35 ] + }, + { "time": 1, "value": 13.57 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -28.72, + "curve": [ 0.024, -31.74, 0.176, -43.4 ] + }, + { + "time": 0.3667, + "value": -43.6, + "curve": [ 0.403, -43.65, 0.47, -40.15 ] + }, + { + "time": 0.5, + "value": -35.63, + "curve": [ 0.547, -28.59, 0.624, -4.57 ] + }, + { + "time": 0.7333, + "value": -4.59, + "curve": [ 0.891, -4.62, 0.954, -24.28 ] + }, + { "time": 1, "value": -28.48 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.034, 30.94, 0.068, 32.05 ] + }, + { + "time": 0.1, + "value": 31.88, + "curve": [ 0.194, 31.01, 0.336, -0.11 ] + }, + { + "time": 0.3667, + "value": -7.11, + "curve": [ 0.421, -19.73, 0.53, -46.21 ] + }, + { + "time": 0.6, + "value": -45.75, + "curve": [ 0.708, -45.03, 0.844, -13.56 ] + }, + { + "time": 0.8667, + "value": -6.48, + "curve": [ 0.909, 6.59, 0.958, 24.21 ] + }, + { "time": 1, "value": 28.28 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -2.79, + "curve": [ 0.074, -2.84, 0.121, 25.08 ] + }, + { + "time": 0.2333, + "value": 24.99, + "curve": [ 0.35, 24.89, 0.427, -2.86 ] + }, + { + "time": 0.5, + "value": -2.8, + "curve": [ 0.575, -2.73, 0.652, 24.5 ] + }, + { + "time": 0.7333, + "value": 24.55, + "curve": [ 0.828, 24.6, 0.932, -2.69 ] + }, + { "time": 1, "value": -2.79 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.01, + "curve": [ 0.106, -5.97, 0.151, 18.62 ] + }, + { + "time": 0.2333, + "value": 18.72, + "curve": [ 0.336, 18.7, 0.405, -11.37 ] + }, + { + "time": 0.5, + "value": -11.45, + "curve": [ 0.626, -11.46, 0.629, 18.94 ] + }, + { + "time": 0.7333, + "value": 18.92, + "curve": [ 0.833, 18.92, 0.913, -6.06 ] + }, + { "time": 1, "value": -6.01 } + ], + "translate": [ + { "x": 0.03, "y": 1.35 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.06, + "curve": [ 0.044, 11.16, 0.063, 11.49 ] + }, + { + "time": 0.1, + "value": 11.49, + "curve": [ 0.215, 11.49, 0.336, 2.92 ] + }, + { + "time": 0.3667, + "value": 0.84, + "curve": [ 0.416, -2.52, 0.498, -10.84 ] + }, + { + "time": 0.6, + "value": -10.83, + "curve": [ 0.762, -10.71, 0.845, -3.05 ] + }, + { + "time": 0.8667, + "value": -1.34, + "curve": [ 0.917, 2.54, 0.977, 8.81 ] + }, + { "time": 1, "value": 10.06 } + ] + }, + "gun": { + "rotate": [ + { + "value": -14.67, + "curve": [ 0.086, -14.67, 0.202, 8.31 ] + }, + { + "time": 0.2333, + "value": 12.14, + "curve": [ 0.279, 17.71, 0.391, 25.79 ] + }, + { + "time": 0.5, + "value": 25.77, + "curve": [ 0.631, 25.74, 0.694, 4.53 ] + }, + { + "time": 0.7333, + "value": -0.65, + "curve": [ 0.768, -5.21, 0.902, -14.4 ] + }, + { "time": 1, "value": -14.67 } + ] + }, + "front-leg-target": { + "translate": [ + { + "x": -2.83, + "y": -8.48, + "curve": [ 0.008, -2.83, 0.058, 0.09, 0.001, 4.97, 0.058, 6.68 ] + }, + { + "time": 0.0667, + "x": 0.09, + "y": 6.68, + "curve": [ 0.3, 0.09, 0.767, -2.83, 0.3, 6.68, 0.767, -8.48 ] + }, + { "time": 1, "x": -2.83, "y": -8.48 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.028, 1.24, 0.016, 3.46 ] + }, + { + "time": 0.1, + "value": 3.45, + "curve": [ 0.159, 3.45, 0.189, 0.23 ] + }, + { + "time": 0.2333, + "value": -2.29, + "curve": [ 0.265, -4.32, 0.305, -5.92 ] + }, + { + "time": 0.3667, + "value": -5.94, + "curve": [ 0.446, -5.96, 0.52, 3.41 ] + }, + { + "time": 0.6, + "value": 3.42, + "curve": [ 0.717, 3.42, 0.772, -5.93 ] + }, + { + "time": 0.8667, + "value": -5.97, + "curve": [ 0.933, -5.99, 0.982, -0.94 ] + }, + { "time": 1 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.067, 0, 0.159, -10.48 ] + }, + { + "time": 0.2333, + "value": -10.49, + "curve": [ 0.334, -10.5, 0.439, -0.09 ] + }, + { + "time": 0.5, + "value": -0.09, + "curve": [ 0.569, -0.09, 0.658, -10.75 ] + }, + { + "time": 0.7333, + "value": -10.7, + "curve": [ 0.833, -10.63, 0.947, 0 ] + }, + { "time": 1 } + ] + }, + "gun-tip": { + "rotate": [ + { "time": 0.2333, "value": 0.11 } + ] + }, + "muzzle-ring": { + "rotate": [ + { "time": 0.2333, "value": 0.11 } + ] + }, + "muzzle-ring2": { + "rotate": [ + { "time": 0.2667, "value": 0.11 } + ] + }, + "muzzle-ring3": { + "rotate": [ + { "time": 0.2667, "value": 0.11 } + ] + }, + "muzzle-ring4": { + "rotate": [ + { "time": 0.2667, "value": 0.11 } + ] + }, + "back-shoulder": { + "translate": [ + { + "x": -0.18, + "y": -4.49, + "curve": [ 0.133, -0.18, 0.333, 7.69, 0.133, -4.49, 0.333, 2.77 ] + }, + { + "time": 0.4667, + "x": 7.69, + "y": 2.77, + "curve": [ 0.6, 7.69, 0.858, -0.18, 0.6, 2.77, 0.858, -4.49 ] + }, + { "time": 1, "x": -0.18, "y": -4.49 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.46, + "y": 9.37, + "curve": [ 0.162, 1.41, 0.333, -1.66, 0.162, 9.37, 0.301, -7.23 ] + }, + { + "time": 0.5, + "x": -1.6, + "y": -7.27, + "curve": [ 0.735, -1.5, 0.847, 1.46, 0.723, -7.31, 0.838, 9.32 ] + }, + { "time": 1, "x": 1.46, "y": 9.37 } + ] + }, + "head-control": { + "translate": [ + { + "x": -6.46, + "y": -8.4, + "curve": [ 0.053, -5.31, 0.167, -3.64, 0.093, -8.4, 0.196, -3.81 ] + }, + { + "time": 0.2333, + "x": -3.64, + "y": -1.32, + "curve": [ 0.309, -3.64, 0.436, -5.84, 0.275, 1.43, 0.38, 10.3 ] + }, + { + "time": 0.5, + "x": -7.03, + "y": 10.29, + "curve": [ 0.538, -7.75, 0.66, -10.54, 0.598, 10.27, 0.694, 1.56 ] + }, + { + "time": 0.7333, + "x": -10.54, + "y": -1.26, + "curve": [ 0.797, -10.54, 0.933, -7.91, 0.768, -3.79, 0.875, -8.4 ] + }, + { "time": 1, "x": -6.46, "y": -8.4 } + ] + } + }, + "ik": { + "front-leg-ik": [ + { + "softness": 25.7, + "bendPositive": false, + "curve": [ 0.008, 1, 0.025, 1, 0.008, 25.7, 0.025, 9.9 ] + }, + { + "time": 0.0333, + "softness": 9.9, + "bendPositive": false, + "curve": [ 0.15, 1, 0.383, 1, 0.15, 9.9, 0.383, 43.2 ] + }, + { + "time": 0.5, + "softness": 43.2, + "bendPositive": false, + "curve": [ 0.625, 1, 0.875, 1, 0.625, 43.2, 0.846, 45.57 ] + }, + { "time": 1, "softness": 25.7, "bendPositive": false } + ], + "rear-leg-ik": [ + { "softness": 5, "bendPositive": false }, + { "time": 0.4333, "softness": 4.9, "bendPositive": false }, + { "time": 0.5, "softness": 28.81, "bendPositive": false }, + { "time": 0.6, "softness": 43.8, "bendPositive": false }, + { "time": 1, "softness": 5, "bendPositive": false } + ] + }, + "events": [ + { "name": "footstep" }, + { "time": 0.5, "name": "footstep" } + ] + } +} +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-pro.skel b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-pro.skel new file mode 100644 index 0000000..6f4f53f Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy-pro.skel differ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy.atlas b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy.atlas new file mode 100644 index 0000000..b07ccc3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy.atlas @@ -0,0 +1,101 @@ +spineboy.png + size: 1024, 256 + filter: Linear, Linear + scale: 0.5 +crosshair + bounds: 813, 160, 45, 45 +eye-indifferent + bounds: 569, 2, 47, 45 +eye-surprised + bounds: 643, 7, 47, 45 + rotate: 90 +front-bracer + bounds: 811, 51, 29, 40 +front-fist-closed + bounds: 807, 93, 38, 41 +front-fist-open + bounds: 815, 210, 43, 44 +front-foot + bounds: 706, 64, 63, 35 + rotate: 90 +front-shin + bounds: 80, 11, 41, 92 +front-thigh + bounds: 754, 12, 23, 56 +front-upper-arm + bounds: 618, 5, 23, 49 +goggles + bounds: 214, 20, 131, 83 +gun + bounds: 347, 14, 105, 102 + rotate: 90 +head + bounds: 80, 105, 136, 149 +hoverboard-board + bounds: 2, 8, 246, 76 + rotate: 90 +hoverboard-thruster + bounds: 478, 2, 30, 32 +hoverglow-small + bounds: 218, 117, 137, 38 + rotate: 90 +mouth-grind + bounds: 775, 80, 47, 30 + rotate: 90 +mouth-oooo + bounds: 779, 31, 47, 30 + rotate: 90 +mouth-smile + bounds: 783, 207, 47, 30 + rotate: 90 +muzzle-glow + bounds: 779, 4, 25, 25 +muzzle-ring + bounds: 451, 14, 25, 105 +muzzle01 + bounds: 664, 60, 67, 40 + rotate: 90 +muzzle02 + bounds: 580, 56, 68, 42 + rotate: 90 +muzzle03 + bounds: 478, 36, 83, 53 + rotate: 90 +muzzle04 + bounds: 533, 49, 75, 45 + rotate: 90 +muzzle05 + bounds: 624, 56, 68, 38 + rotate: 90 +neck + bounds: 806, 8, 18, 21 +portal-bg + bounds: 258, 121, 133, 133 +portal-flare1 + bounds: 690, 2, 56, 30 + rotate: 90 +portal-flare2 + bounds: 510, 3, 57, 31 +portal-flare3 + bounds: 722, 4, 58, 30 + rotate: 90 +portal-shade + bounds: 393, 121, 133, 133 +portal-streaks1 + bounds: 528, 126, 126, 128 +portal-streaks2 + bounds: 656, 129, 125, 125 +rear-bracer + bounds: 826, 13, 28, 36 +rear-foot + bounds: 743, 70, 57, 30 + rotate: 90 +rear-shin + bounds: 174, 14, 38, 89 +rear-thigh + bounds: 783, 158, 28, 47 +rear-upper-arm + bounds: 783, 136, 20, 44 + rotate: 90 +torso + bounds: 123, 13, 49, 90 diff --git a/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy.png b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy.png new file mode 100644 index 0000000..3f7eb06 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/export/spineboy.png differ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/license.txt b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/license.txt new file mode 100644 index 0000000..cd3e3b4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/license.txt @@ -0,0 +1,8 @@ +Copyright (c) 2013, Esoteric Software + +The images in this project may be redistributed as long as they are accompanied +by this license file. The images may not be used for commercial use of any +kind. + +The project file is released into the public domain. It may be used as the basis +for derivative work. \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/spineboy-ess.spine b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/spineboy-ess.spine new file mode 100644 index 0000000..1594eac Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/spineboy-ess.spine differ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/spineboy-pro.spine b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/spineboy-pro.spine new file mode 100644 index 0000000..63190b5 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.0/examples/spineboy/spineboy-pro.spine differ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/CMakeLists.txt b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/CMakeLists.txt new file mode 100644 index 0000000..e008c33 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/CMakeLists.txt @@ -0,0 +1,17 @@ +if(MSVC) + message("MSCV detected") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + set (CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}") +else() + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic -std=c89") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wnon-virtual-dtor -pedantic -std=c++11 -fno-exceptions -fno-rtti") +endif() + +include_directories(include) +file(GLOB INCLUDES "spine-cpp/include/**/*.h") +file(GLOB SOURCES "spine-cpp/src/**/*.cpp") + +add_library(spine-cpp STATIC ${SOURCES} ${INCLUDES}) +target_include_directories(spine-cpp PUBLIC spine-cpp/include) +install(TARGETS spine-cpp DESTINATION dist/lib) +install(FILES ${INCLUDES} DESTINATION dist/include) \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/LICENSE b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/LICENSE new file mode 100644 index 0000000..4501a61 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/LICENSE @@ -0,0 +1,26 @@ +Spine Runtimes License Agreement +Last updated May 1, 2019. Replaces all prior versions. + +Copyright (c) 2013-2019, Esoteric Software LLC + +Integration of the Spine Runtimes into software or otherwise creating +derivative works of the Spine Runtimes is permitted under the terms and +conditions of Section 2 of the Spine Editor License Agreement: +http://esotericsoftware.com/spine-editor-license + +Otherwise, it is permitted to integrate the Spine Runtimes into software +or otherwise create derivative works of the Spine Runtimes (collectively, +"Products"), provided that each user of the Products must obtain their own +Spine Editor license and redistribution of the Products in any form must +include this license and copyright notice. + +THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS +INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/README.md b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/README.md new file mode 100644 index 0000000..1f0773e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/README.md @@ -0,0 +1,54 @@ +# spine-cpp + +The spine-cpp runtime provides basic functionality to load and manipulate [spine](http://esotericsoftware.com) skeletal animation data using C++. It does not perform rendering but can be extended to enable spine animations for other projects that utilize C++. + +## Licensing + +You are welcome to evaluate the Spine Runtimes and the examples we provide in this repository free of charge. + +You can integrate the Spine Runtimes into your software free of charge, but users of your software must have their own [Spine license](https://esotericsoftware.com/spine-purchase). Please make your users aware of this requirement! This option is often chosen by those making development tools, such as an SDK, game toolkit, or software library. + +In order to distribute your software containing the Spine Runtimes to others that don't have a Spine license, you need a [Spine license](https://esotericsoftware.com/spine-purchase) at the time of integration. Then you can distribute your software containing the Spine Runtimes however you like, provided others don't modify it or use it to create new software. If others want to do that, they'll need their own Spine license. + +For the official legal terms governing the Spine Runtimes, please read the [Spine Runtimes License Agreement](http://esotericsoftware.com/spine-runtimes-license) and Section 2 of the [Spine Editor License Agreement](http://esotericsoftware.com/spine-editor-license#s2). + +## Spine version + +spine-cpp works with data exported from spine 4.0.xx. + +spine-cpp supports all spine features. + +## Setup + +1. Download the spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it as a zip via the download button above. +2. Copy the contents of the `spine-cpp/spine-cpp/src` and `spine-cpp/spine-cpp/include` directories into your project. Be sure your header search is configured to find the contents of the `spine-cpp/spine-cpp/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files. + +## Usage +### [Please see the spine-cpp guide for full documentation](http://esotericsoftware.com/spine-cpp) + +## Extension + +Extending spine-cpp requires implementing both the `SpineExtension` class and the TextureLoader class: + +``` +#include +void spine::SpineExtension *spine::getDefaultExtension() { + return new spine::DefaultExtension(); +} + +class MyTextureLoader : public spine::TextureLoader +{ + virtual void load(spine::AtlasPage& page, const spine::String& path) { + void* texture = ... load the texture based on path ... + page->setRendererObject(texture); // use the texture later in your rendering code + } + + virtual void unload(void* texture) { // TODO } +}; +``` + +## Runtimes extending spine-cpp + +- [spine-sfml](../spine-sfml/cpp) +- [spine-cocos2dx](../spine-cocos2dx) +- [spine-ue4](../spine-ue4) diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp-unit-tests/CMakeLists.txt b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp-unit-tests/CMakeLists.txt new file mode 100755 index 0000000..449c08c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp-unit-tests/CMakeLists.txt @@ -0,0 +1,41 @@ +project(spine_cpp_unit_test) + +set(CMAKE_INSTALL_PREFIX "./") +set(CMAKE_VERBOSE_MAKEFILE ON) + +include_directories(../spine-cpp/include teamcity minicppunit tests memory) + +set(SRC + src/main.cpp + ) + +add_executable(spine_cpp_unit_test ${SRC}) +target_link_libraries(spine_cpp_unit_test spine-cpp) + + +######################################################### +# copy resources to build output directory +######################################################### +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/spineboy/export $/testdata/spineboy) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/raptor/export $/testdata/raptor) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/goblins/export $/testdata/goblins) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/coin/export $/testdata/coin) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/tank/export $/testdata/tank) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/stretchyman/export $/testdata/stretchyman) diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp-unit-tests/README.md b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp-unit-tests/README.md new file mode 100755 index 0000000..a7d6efb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp-unit-tests/README.md @@ -0,0 +1,67 @@ +# spine-cpp-unit-tests + +The spine-cpp-unit-tests project is to test the [spine](http://esotericsoftware.com) skeletal animation system. It does not perform rendering. It is primarily used for regression testing and leak detection. It is designed to be run from a Continuous Integration server and to passively verify changes automatically on check-in. + +## Mini CPP Unit Testing +[MiniCppUnit](https://sourceforge.net/p/minicppunit/wiki/Home/) is a minimal unit testing framework similar to JUnit. It is used here to avoid large dependancies. + +Tests are sorted into Suites, Fixtures and Cases. There is one suite, it contains many fixtures and each fixture contains test cases. To turn off a fixture, edit "TestOptions.h". To turn off specific test cases, comment out the TEST_CASE() line in the fixture's header. + +## Memory Leak Detection +This project includes a very minimal memory leak detector. It is based roughly on the leak detector in the [Popcap Framework](https://sourceforge.net/projects/popcapframework/?source=directory), but has been modified over the years. + +## Continuous Integration +The test runner includes the ability to format output messages to signal a CI server. An example interface for [Teamcity](https://www.jetbrains.com/teamcity/) is included. To implement for another server, determine the wireformat for the messages and duplicate/edit the teamcity_messages class. [Teamcity Wire Format](https://confluence.jetbrains.com/display/TCD10/Build+Script+Interaction+with+TeamCity) + +### Trigger +Your CI server should trigger on VCS check-in. + +### CMake Build Step +The first build step for the CI server should be to run CMake on the 'spine-cpp-unit-tests' folder. Follow the usage directions below. + +### Compile Build Step +This build step should not execute if the previous step did not successfully complete. +Depending on the test agent build environment, you should build the output solution or project from the cmake step. Debug is fine. + +### Test Runner Build Step +This build step should not execute if the previous step did not successfully complete. +Again, depending on the test agent build environment, you should have produced an executable. Run this executable. + + +## Usage +Make sure [CMake](https://cmake.org/download/) is installed. + +Create a 'build' directory in the 'spine-cpp-unit-tests' folder. Then switch to that folder and execute cmake: + +mkdir build +cd build +cmake .. + +### Win32 build +msbuild spine_unit_test.sln /t:spine_unit_test /p:Configuration="Debug" /p:Platform="Win32" + + +## Licensing +This spine Runtime may only be used for personal or internal use, typically to evaluate spine before purchasing. If you would like to incorporate a spine Runtime into your applications, distribute software containing a spine Runtime, or modify a spine Runtime, then you will need a valid [spine license](https://esotericsoftware.com/spine-purchase). Please see the [spine Runtimes Software License](https://github.com/EsotericSoftware/spine-runtimes/blob/master/LICENSE) for detailed information. + +The spine Runtimes are developed with the intent to be used with data exported from spine. By purchasing spine, `Section 2` of the [spine Software License](https://esotericsoftware.com/files/license.txt) grants the right to create and distribute derivative works of the spine Runtimes. + +original "walk"": 330 +second "walk": 0d0 + +queue interrupt for original walk +queue start for second walk +drain interrupt and start + +0d0 is interrupted +0d0 is ended + +"run": 0c0 + 0d0 is interrupted + second walk becomes mixingFrom of run + 0c0 is started + + queue is drained + + first walk: 6f0 + second walk: 9c0 diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp-unit-tests/src/main.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp-unit-tests/src/main.cpp new file mode 100644 index 0000000..6cb8e05 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp-unit-tests/src/main.cpp @@ -0,0 +1,116 @@ +#include +#include +#include + +#ifdef MSVC +#pragma warning(disable : 4710) +#endif + +using namespace spine; + +void loadBinary(const String &binaryFile, const String &atlasFile, Atlas *&atlas, SkeletonData *&skeletonData, + AnimationStateData *&stateData, Skeleton *&skeleton, AnimationState *&state) { + atlas = new (__FILE__, __LINE__) Atlas(atlasFile, NULL); + assert(atlas != NULL); + + SkeletonBinary binary(atlas); + skeletonData = binary.readSkeletonDataFile(binaryFile); + assert(skeletonData); + + skeleton = new (__FILE__, __LINE__) Skeleton(skeletonData); + assert(skeleton != NULL); + + stateData = new (__FILE__, __LINE__) AnimationStateData(skeletonData); + assert(stateData != NULL); + stateData->setDefaultMix(0.4f); + + state = new (__FILE__, __LINE__) AnimationState(stateData); +} + +void loadJson(const String &jsonFile, const String &atlasFile, Atlas *&atlas, SkeletonData *&skeletonData, + AnimationStateData *&stateData, Skeleton *&skeleton, AnimationState *&state) { + atlas = new (__FILE__, __LINE__) Atlas(atlasFile, NULL); + assert(atlas != NULL); + + SkeletonJson json(atlas); + skeletonData = json.readSkeletonDataFile(jsonFile); + assert(skeletonData); + + skeleton = new (__FILE__, __LINE__) Skeleton(skeletonData); + assert(skeleton != NULL); + + stateData = new (__FILE__, __LINE__) AnimationStateData(skeletonData); + assert(stateData != NULL); + stateData->setDefaultMix(0.4f); + + state = new (__FILE__, __LINE__) AnimationState(stateData); +} + +void dispose(Atlas *atlas, SkeletonData *skeletonData, AnimationStateData *stateData, Skeleton *skeleton, + AnimationState *state) { + delete skeleton; + delete state; + delete stateData; + delete skeletonData; + delete atlas; +} + +struct TestData { + TestData(const String &jsonSkeleton, const String &binarySkeleton, const String &atlas) : _jsonSkeleton( + jsonSkeleton), + _binarySkeleton( + binarySkeleton), + _atlas(atlas) {} + + String _jsonSkeleton; + String _binarySkeleton; + String _atlas; +}; + +void testLoading() { + Vector testData; + testData.add(TestData("testdata/coin/coin-pro.json", "testdata/coin/coin-pro.skel", "testdata/coin/coin.atlas")); + /*testData.add(TestData("testdata/goblins/goblins-pro.json", "testdata/goblins/goblins-pro.skel", + "testdata/goblins/goblins.atlas")); + testData.add(TestData("testdata/raptor/raptor-pro.json", "testdata/raptor/raptor-pro.skel", + "testdata/raptor/raptor.atlas")); + testData.add(TestData("testdata/spineboy/spineboy-pro.json", "testdata/spineboy/spineboy-pro.skel", + "testdata/spineboy/spineboy.atlas")); + testData.add(TestData("testdata/stretchyman/stretchyman-pro.json", "testdata/stretchyman/stretchyman-pro.skel", + "testdata/stretchyman/stretchyman.atlas")); + testData.add(TestData("testdata/tank/tank-pro.json", "testdata/tank/tank-pro.skel", "testdata/tank/tank.atlas"));*/ + + for (size_t i = 0; i < testData.size(); i++) { + TestData &data = testData[i]; + Atlas *atlas = NULL; + SkeletonData *skeletonData = NULL; + AnimationStateData *stateData = NULL; + Skeleton *skeleton = NULL; + AnimationState *state = NULL; + + printf("Loading %s\n", data._jsonSkeleton.buffer()); + loadJson(data._jsonSkeleton, data._atlas, atlas, skeletonData, stateData, skeleton, state); + dispose(atlas, skeletonData, stateData, skeleton, state); + + printf("Loading %s\n", data._binarySkeleton.buffer()); + loadBinary(data._binarySkeleton, data._atlas, atlas, skeletonData, stateData, skeleton, state); + dispose(atlas, skeletonData, stateData, skeleton, state); + } +} + +namespace spine { + SpineExtension *getDefaultExtension() { + return new DefaultSpineExtension(); + } +}// namespace spine + +int main(int argc, char **argv) { + SP_UNUSED(argc); + SP_UNUSED(argv); + DebugExtension debug(SpineExtension::getInstance()); + SpineExtension::setInstance(&debug); + + testLoading(); + + debug.reportLeaks(); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Animation.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Animation.h new file mode 100644 index 0000000..ac34670 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Animation.h @@ -0,0 +1,132 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Animation_h +#define Spine_Animation_h + +#include +#include +#include +#include +#include +#include +#include + +namespace spine { + class Timeline; + + class Skeleton; + + class Event; + + class AnimationState; + + class SP_API Animation : public SpineObject { + friend class AnimationState; + + friend class TrackEntry; + + friend class AnimationStateData; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class RotateTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + friend class TwoColorTimeline; + + public: + Animation(const String &name, Vector &timelines, float duration); + + ~Animation(); + + /// Applies all the animation's timelines to the specified skeleton. + /// See also Timeline::apply(Skeleton&, float, float, Vector, float, MixPose, MixDirection) + void apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction); + + const String &getName(); + + Vector &getTimelines(); + + bool hasTimeline(Vector ids); + + float getDuration(); + + void setDuration(float inValue); + + private: + Vector _timelines; + HashMap _timelineIds; + float _duration; + String _name; + + /// @param target After the first and before the last entry. + static int search(Vector &values, float target); + + static int search(Vector &values, float target, int step); + }; +} + +#endif /* Spine_Animation_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AnimationState.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AnimationState.h new file mode 100644 index 0000000..384cff9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -0,0 +1,491 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AnimationState_h +#define Spine_AnimationState_h + +#include +#include +#include +#include +#include +#include +#include +#include "Slot.h" + +#ifdef SPINE_USE_STD_FUNCTION +#include +#endif + +namespace spine { + enum EventType { + EventType_Start, + EventType_Interrupt, + EventType_End, + EventType_Complete, + EventType_Dispose, + EventType_Event + }; + + class AnimationState; + + class TrackEntry; + + class Animation; + + class Event; + + class AnimationStateData; + + class Skeleton; + + class RotateTimeline; + + class AttachmentTimeline; + +#ifdef SPINE_USE_STD_FUNCTION + typedef std::function AnimationStateListener; +#else + + typedef void (*AnimationStateListener)(AnimationState *state, EventType type, TrackEntry *entry, Event *event); + +#endif + + /// Abstract class to inherit from to create a callback object + class SP_API AnimationStateListenerObject { + public: + AnimationStateListenerObject() {}; + + virtual ~AnimationStateListenerObject() {}; + public: + /// The callback function to be called + virtual void callback(AnimationState *state, EventType type, TrackEntry *entry, Event *event) = 0; + }; + + /// State for the playback of an animation + class SP_API TrackEntry : public SpineObject, public HasRendererObject { + friend class EventQueue; + + friend class AnimationState; + + public: + TrackEntry(); + + virtual ~TrackEntry(); + + /// The index of the track where this entry is either current or queued. + int getTrackIndex(); + + /// The animation to apply for this track entry. + Animation *getAnimation(); + + TrackEntry *getPrevious(); + + /// If true, the animation will repeat. If false, it will not, instead its last frame is applied if played beyond its duration. + bool getLoop(); + + void setLoop(bool inValue); + + /// If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead + /// of being mixed out. + /// + /// When mixing between animations that key the same property, if a lower track also keys that property then the value will + /// briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0% + /// while the second animation mixes from 0% to 100%. Setting holdPrevious to true applies the first animation + /// at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which + /// keys the property, only when a higher track also keys the property. + /// + /// Snapping will occur if holdPrevious is true and this animation does not key all the same properties as the + /// previous animation. + bool getHoldPrevious(); + + void setHoldPrevious(bool inValue); + + bool getReverse(); + + void setReverse(bool inValue); + + /// Seconds to postpone playing the animation. When a track entry is the current track entry, delay postpones incrementing + /// the track time. When a track entry is queued, delay is the time from the start of the previous animation to when the + /// track entry will become the current track entry. + float getDelay(); + + void setDelay(float inValue); + + /// Current time in seconds this track entry has been the current track entry. The track time determines + /// TrackEntry.AnimationTime. The track time can be set to start the animation at a time other than 0, without affecting looping. + float getTrackTime(); + + void setTrackTime(float inValue); + + /// The track time in seconds when this animation will be removed from the track. Defaults to the animation duration for + /// non-looping animations and to int.MaxValue for looping animations. If the track end time is reached and no + /// other animations are queued for playback, and mixing from any previous animations is complete, properties keyed by the animation, + /// are set to the setup pose and the track is cleared. + /// + /// It may be desired to use AnimationState.addEmptyAnimation(int, float, float) to mix the properties back to the + /// setup pose over time, rather than have it happen instantly. + float getTrackEnd(); + + void setTrackEnd(float inValue); + + /// Seconds when this animation starts, both initially and after looping. Defaults to 0. + /// + /// When changing the animation start time, it often makes sense to set TrackEntry.AnimationLast to the same value to + /// prevent timeline keys before the start time from triggering. + float getAnimationStart(); + + void setAnimationStart(float inValue); + + /// Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will + /// loop back to TrackEntry.AnimationStart at this time. Defaults to the animation duration. + float getAnimationEnd(); + + void setAnimationEnd(float inValue); + + /// The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this + /// animation is applied, event timelines will fire all events between the animation last time (exclusive) and animation time + /// (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation is applied. + float getAnimationLast(); + + void setAnimationLast(float inValue); + + /// Uses TrackEntry.TrackTime to compute the animation time between TrackEntry.AnimationStart. and + /// TrackEntry.AnimationEnd. When the track time is 0, the animation time is equal to the animation start time. + float getAnimationTime(); + + /// Multiplier for the delta time when the animation state is updated, causing time for this animation to play slower or + /// faster. Defaults to 1. + float getTimeScale(); + + void setTimeScale(float inValue); + + /// Values less than 1 mix this animation with the last skeleton pose. Defaults to 1, which overwrites the last skeleton pose with + /// this animation. + /// + /// Typically track 0 is used to completely pose the skeleton, then alpha can be used on higher tracks. It doesn't make sense + /// to use alpha on track 0 if the skeleton pose is from the last frame render. + float getAlpha(); + + void setAlpha(float inValue); + + /// + /// When the mix percentage (mix time / mix duration) is less than the event threshold, event timelines for the animation + /// being mixed out will be applied. Defaults to 0, so event timelines are not applied for an animation being mixed out. + float getEventThreshold(); + + void setEventThreshold(float inValue); + + /// When the mix percentage (mix time / mix duration) is less than the attachment threshold, attachment timelines for the + /// animation being mixed out will be applied. Defaults to 0, so attachment timelines are not applied for an animation being + /// mixed out. + float getAttachmentThreshold(); + + void setAttachmentThreshold(float inValue); + + /// When the mix percentage (mix time / mix duration) is less than the draw order threshold, draw order timelines for the + /// animation being mixed out will be applied. Defaults to 0, so draw order timelines are not applied for an animation being + /// mixed out. + float getDrawOrderThreshold(); + + void setDrawOrderThreshold(float inValue); + + /// The animation queued to start after this animation, or NULL. + TrackEntry *getNext(); + + /// Returns true if at least one loop has been completed. + bool isComplete(); + + /// Seconds from 0 to the mix duration when mixing from the previous animation to this animation. May be slightly more than + /// TrackEntry.MixDuration when the mix is complete. + float getMixTime(); + + void setMixTime(float inValue); + + /// Seconds for mixing from the previous animation to this animation. Defaults to the value provided by + /// AnimationStateData based on the animation before this animation (if any). + /// + /// The mix duration can be set manually rather than use the value from AnimationStateData.GetMix. + /// In that case, the mixDuration must be set before AnimationState.update(float) is next called. + /// + /// When using AnimationState::addAnimation(int, Animation, bool, float) with a delay + /// less than or equal to 0, note the Delay is set using the mix duration from the AnimationStateData + float getMixDuration(); + + void setMixDuration(float inValue); + + MixBlend getMixBlend(); + + void setMixBlend(MixBlend blend); + + /// The track entry for the previous animation when mixing from the previous animation to this animation, or NULL if no + /// mixing is currently occuring. When mixing from multiple animations, MixingFrom makes up a double linked list with MixingTo. + TrackEntry *getMixingFrom(); + + /// The track entry for the next animation when mixing from this animation, or NULL if no mixing is currently occuring. + /// When mixing from multiple animations, MixingTo makes up a double linked list with MixingFrom. + TrackEntry *getMixingTo(); + + /// Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the + /// long way around when using alpha and starting animations on other tracks. + /// + /// Mixing involves finding a rotation between two others, which has two possible solutions: the short way or the long way around. + /// The two rotations likely change over time, so which direction is the short or long way also changes. + /// If the short way was always chosen, bones would flip to the other side when that direction became the long way. + /// TrackEntry chooses the short way the first time it is applied and remembers that direction. + void resetRotationDirections(); + + float getTrackComplete(); + + void setListener(AnimationStateListener listener); + + void setListener(AnimationStateListenerObject *listener); + + private: + Animation *_animation; + TrackEntry *_previous; + TrackEntry *_next; + TrackEntry *_mixingFrom; + TrackEntry *_mixingTo; + int _trackIndex; + + bool _loop, _holdPrevious, _reverse; + float _eventThreshold, _attachmentThreshold, _drawOrderThreshold; + float _animationStart, _animationEnd, _animationLast, _nextAnimationLast; + float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale; + float _alpha, _mixTime, _mixDuration, _interruptAlpha, _totalAlpha; + MixBlend _mixBlend; + Vector _timelineMode; + Vector _timelineHoldMix; + Vector _timelinesRotation; + AnimationStateListener _listener; + AnimationStateListenerObject *_listenerObject; + + void reset(); + }; + + class SP_API EventQueueEntry : public SpineObject { + friend class EventQueue; + + public: + EventType _type; + TrackEntry *_entry; + Event *_event; + + EventQueueEntry(EventType eventType, TrackEntry *trackEntry, Event *event = NULL); + }; + + class SP_API EventQueue : public SpineObject { + friend class AnimationState; + + private: + Vector _eventQueueEntries; + AnimationState &_state; + Pool &_trackEntryPool; + bool _drainDisabled; + + static EventQueue *newEventQueue(AnimationState &state, Pool &trackEntryPool); + + static EventQueueEntry newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event = NULL); + + EventQueue(AnimationState &state, Pool &trackEntryPool); + + ~EventQueue(); + + void start(TrackEntry *entry); + + void interrupt(TrackEntry *entry); + + void end(TrackEntry *entry); + + void dispose(TrackEntry *entry); + + void complete(TrackEntry *entry); + + void event(TrackEntry *entry, Event *event); + + /// Raises all events in the queue and drains the queue. + void drain(); + }; + + class SP_API AnimationState : public SpineObject, public HasRendererObject { + friend class TrackEntry; + + friend class EventQueue; + + public: + explicit AnimationState(AnimationStateData *data); + + ~AnimationState(); + + /// Increments the track entry times, setting queued animations as current if needed + /// @param delta delta time + void update(float delta); + + /// Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the + /// animation state can be applied to multiple skeletons to pose them identically. + bool apply(Skeleton &skeleton); + + /// Removes all animations from all tracks, leaving skeletons in their previous pose. + /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, + /// rather than leaving them in their previous pose. + void clearTracks(); + + /// Removes all animations from the tracks, leaving skeletons in their previous pose. + /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, + /// rather than leaving them in their previous pose. + void clearTrack(size_t trackIndex); + + /// Sets an animation by name. setAnimation(int, Animation, bool) + TrackEntry *setAnimation(size_t trackIndex, const String &animationName, bool loop); + + /// Sets the current animation for a track, discarding any queued animations. + /// @param loop If true, the animation will repeat. + /// If false, it will not, instead its last frame is applied if played beyond its duration. + /// In either case TrackEntry.TrackEnd determines when the track is cleared. + /// @return + /// A track entry to allow further customization of animation playback. References to the track entry must not be kept + /// after AnimationState.Dispose. + TrackEntry *setAnimation(size_t trackIndex, Animation *animation, bool loop); + + /// Queues an animation by name. + /// addAnimation(int, Animation, bool, float) + TrackEntry *addAnimation(size_t trackIndex, const String &animationName, bool loop, float delay); + + /// Adds an animation to be played delay seconds after the current or last queued animation + /// for a track. If the track is empty, it is equivalent to calling setAnimation. + /// @param delay + /// Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation + /// duration of the previous track minus any mix duration plus the negative delay. + /// + /// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + /// after AnimationState.Dispose + TrackEntry *addAnimation(size_t trackIndex, Animation *animation, bool loop, float delay); + + /// Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration. + TrackEntry *setEmptyAnimation(size_t trackIndex, float mixDuration); + + /// Adds an empty animation to be played after the current or last queued animation for a track, and mixes to it over the + /// specified mix duration. + /// @return + /// A track entry to allow further customization of animation playback. References to the track entry must not be kept after AnimationState.Dispose. + /// + /// @param trackIndex Track number. + /// @param mixDuration Mix duration. + /// @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation + /// duration of the previous track minus any mix duration plus the negative delay. + TrackEntry *addEmptyAnimation(size_t trackIndex, float mixDuration, float delay); + + /// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration. + void setEmptyAnimations(float mixDuration); + + /// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing. + TrackEntry *getCurrent(size_t trackIndex); + + AnimationStateData *getData(); + + /// A list of tracks that have animations, which may contain NULLs. + Vector &getTracks(); + + float getTimeScale(); + + void setTimeScale(float inValue); + + void setListener(AnimationStateListener listener); + + void setListener(AnimationStateListenerObject *listener); + + void disableQueue(); + + void enableQueue(); + + private: + static const int Subsequent = 0; + static const int First = 1; + static const int HoldSubsequent = 2; + static const int HoldFirst = 3; + static const int HoldMix = 4; + + static const int Setup = 1; + static const int Current = 2; + + AnimationStateData *_data; + + Pool _trackEntryPool; + Vector _tracks; + Vector _events; + EventQueue *_queue; + + HashMap _propertyIDs; + bool _animationsChanged; + + AnimationStateListener _listener; + AnimationStateListenerObject *_listenerObject; + + int _unkeyedState; + + float _timeScale; + + static Animation *getEmptyAnimation(); + + static void + applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, MixBlend pose, + Vector &timelinesRotation, size_t i, bool firstFrame); + + void applyAttachmentTimeline(AttachmentTimeline *attachmentTimeline, Skeleton &skeleton, float animationTime, + MixBlend pose, bool firstFrame); + + /// Returns true when all mixing from entries are complete. + bool updateMixingFrom(TrackEntry *to, float delta); + + float applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBlend currentPose); + + void queueEvents(TrackEntry *entry, float animationTime); + + /// Sets the active TrackEntry for a given track number. + void setCurrent(size_t index, TrackEntry *current, bool interrupt); + + /// Removes the next entry and all entries after it for the specified entry. */ + void clearNext(TrackEntry *entry); + + TrackEntry *expandToIndex(size_t index); + + /// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values. + /// @param last May be NULL. + TrackEntry *newTrackEntry(size_t trackIndex, Animation *animation, bool loop, TrackEntry *last); + + void animationsChanged(); + + void computeHold(TrackEntry *entry); + + void setAttachment(Skeleton &skeleton, spine::Slot &slot, const String &attachmentName, bool attachments); + }; +} + +#endif /* Spine_AnimationState_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AnimationStateData.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AnimationStateData.h new file mode 100644 index 0000000..fe4eef9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AnimationStateData.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AnimationStateData_h +#define Spine_AnimationStateData_h + +#include +#include +#include + +#include + +namespace spine { + class SkeletonData; + + class Animation; + + /// Stores mix (crossfade) durations to be applied when AnimationState animations are changed. + class SP_API AnimationStateData : public SpineObject { + friend class AnimationState; + + public: + explicit AnimationStateData(SkeletonData *skeletonData); + + /// The SkeletonData to look up animations when they are specified by name. + SkeletonData *getSkeletonData(); + + /// The mix duration to use when no mix duration has been specifically defined between two animations. + float getDefaultMix(); + + void setDefaultMix(float inValue); + + /// Sets a mix duration by animation names. + void setMix(const String &fromName, const String &toName, float duration); + + /// Sets a mix duration when changing from the specified animation to the other. + /// See TrackEntry.MixDuration. + void setMix(Animation *from, Animation *to, float duration); + + /// The mix duration to use when changing from the specified animation to the other, + /// or the DefaultMix if no mix duration has been set. + float getMix(Animation *from, Animation *to); + + private: + class AnimationPair : public SpineObject { + public: + Animation *_a1; + Animation *_a2; + + explicit AnimationPair(Animation *a1 = NULL, Animation *a2 = NULL); + + bool operator==(const AnimationPair &other) const; + }; + + SkeletonData *_skeletonData; + float _defaultMix; + HashMap _animationToMixTime; + }; +} + +#endif /* Spine_AnimationStateData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Atlas.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Atlas.h new file mode 100644 index 0000000..62eb69d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Atlas.h @@ -0,0 +1,132 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Atlas_h +#define Spine_Atlas_h + +#include +#include +#include +#include +#include + +namespace spine { + enum Format { + Format_Alpha, + Format_Intensity, + Format_LuminanceAlpha, + Format_RGB565, + Format_RGBA4444, + Format_RGB888, + Format_RGBA8888 + }; + + enum TextureFilter { + TextureFilter_Unknown, + TextureFilter_Nearest, + TextureFilter_Linear, + TextureFilter_MipMap, + TextureFilter_MipMapNearestNearest, + TextureFilter_MipMapLinearNearest, + TextureFilter_MipMapNearestLinear, + TextureFilter_MipMapLinearLinear + }; + + enum TextureWrap { + TextureWrap_MirroredRepeat, + TextureWrap_ClampToEdge, + TextureWrap_Repeat + }; + + class SP_API AtlasPage : public SpineObject, public HasRendererObject { + public: + String name; + String texturePath; + Format format; + TextureFilter minFilter; + TextureFilter magFilter; + TextureWrap uWrap; + TextureWrap vWrap; + int width, height; + bool pma; + + explicit AtlasPage(const String &inName) : name(inName), format(Format_RGBA8888), + minFilter(TextureFilter_Nearest), + magFilter(TextureFilter_Nearest), uWrap(TextureWrap_ClampToEdge), + vWrap(TextureWrap_ClampToEdge), width(0), height(0), pma(false) { + } + }; + + class SP_API AtlasRegion : public SpineObject { + public: + AtlasPage *page; + String name; + int x, y, width, height; + float u, v, u2, v2; + float offsetX, offsetY; + int originalWidth, originalHeight; + int index; + int degrees; + Vector splits; + Vector pads; + Vector names; + Vector values; + }; + + class TextureLoader; + + class SP_API Atlas : public SpineObject { + public: + Atlas(const String &path, TextureLoader *textureLoader, bool createTexture = true); + + Atlas(const char *data, int length, const char *dir, TextureLoader *textureLoader, bool createTexture = true); + + ~Atlas(); + + void flipV(); + + /// Returns the first region found with the specified name. This method uses String comparison to find the region, so the result + /// should be cached rather than calling this method multiple times. + /// @return The region, or NULL. + AtlasRegion *findRegion(const String &name); + + Vector &getPages(); + + Vector &getRegions(); + + private: + Vector _pages; + Vector _regions; + TextureLoader *_textureLoader; + + void load(const char *begin, int length, const char *dir, bool createTexture); + }; +} + +#endif /* Spine_Atlas_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h new file mode 100644 index 0000000..e8a0a01 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AtlasAttachmentLoader_h +#define Spine_AtlasAttachmentLoader_h + +#include +#include +#include + + +namespace spine { + class Atlas; + + class AtlasRegion; + + /// An AttachmentLoader that configures attachments using texture regions from an Atlas. + /// See http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data about Loading Skeleton Data in the Spine Runtimes Guide. + class SP_API AtlasAttachmentLoader : public AttachmentLoader { + public: + RTTI_DECL + + explicit AtlasAttachmentLoader(Atlas *atlas); + + virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &name, const String &path); + + virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &name, const String &path); + + virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &skin, const String &name); + + virtual PathAttachment *newPathAttachment(Skin &skin, const String &name); + + virtual PointAttachment *newPointAttachment(Skin &skin, const String &name); + + virtual ClippingAttachment *newClippingAttachment(Skin &skin, const String &name); + + virtual void configureAttachment(Attachment *attachment); + + AtlasRegion *findRegion(const String &name); + + private: + Atlas *_atlas; + }; +} + +#endif /* Spine_AtlasAttachmentLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Attachment.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Attachment.h new file mode 100644 index 0000000..be4da41 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Attachment.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Attachment_h +#define Spine_Attachment_h + +#include +#include +#include + +namespace spine { + class SP_API Attachment : public SpineObject { + RTTI_DECL + + public: + explicit Attachment(const String &name); + + virtual ~Attachment(); + + const String &getName() const; + + virtual Attachment *copy() = 0; + + int getRefCount(); + + void reference(); + + void dereference(); + + private: + const String _name; + int _refCount; + }; +} + +#endif /* Spine_Attachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h new file mode 100644 index 0000000..1fb6819 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentLoader_h +#define Spine_AttachmentLoader_h + +#include +#include +#include + +namespace spine { + class Skin; + + class Attachment; + + class RegionAttachment; + + class MeshAttachment; + + class BoundingBoxAttachment; + + class PathAttachment; + + class PointAttachment; + + class ClippingAttachment; + + class SP_API AttachmentLoader : public SpineObject { + public: + RTTI_DECL + + AttachmentLoader(); + + virtual ~AttachmentLoader(); + + /// @return May be NULL to not load any attachment. + virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &name, const String &path) = 0; + + /// @return May be NULL to not load any attachment. + virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &name, const String &path) = 0; + + /// @return May be NULL to not load any attachment. + virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &skin, const String &name) = 0; + + /// @return May be NULL to not load any attachment + virtual PathAttachment *newPathAttachment(Skin &skin, const String &name) = 0; + + virtual PointAttachment *newPointAttachment(Skin &skin, const String &name) = 0; + + virtual ClippingAttachment *newClippingAttachment(Skin &skin, const String &name) = 0; + + virtual void configureAttachment(Attachment *attachment) = 0; + }; +} + +#endif /* Spine_AttachmentLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h new file mode 100644 index 0000000..9676ec6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentTimeline_h +#define Spine_AttachmentTimeline_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + + class Skeleton; + + class Slot; + + class Event; + + class SP_API AttachmentTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit AttachmentTimeline(size_t frameCount, int slotIndex); + + virtual ~AttachmentTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, const String &attachmentName); + + Vector &getAttachmentNames(); + + int getSlotIndex() { return _slotIndex; } + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + Vector _attachmentNames; + + void setAttachment(Skeleton &skeleton, Slot &slot, String *attachmentName); + }; +} + +#endif /* Spine_AttachmentTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AttachmentType.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AttachmentType.h new file mode 100644 index 0000000..bb62f9f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/AttachmentType.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentType_h +#define Spine_AttachmentType_h + +namespace spine { + enum AttachmentType { + AttachmentType_Region, + AttachmentType_Boundingbox, + AttachmentType_Mesh, + AttachmentType_Linkedmesh, + AttachmentType_Path, + AttachmentType_Point, + AttachmentType_Clipping + }; +} + +#endif /* Spine_AttachmentType_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/BlendMode.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/BlendMode.h new file mode 100644 index 0000000..708b9c1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/BlendMode.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BlendMode_h +#define Spine_BlendMode_h + +namespace spine { + enum BlendMode { + BlendMode_Normal = 0, + BlendMode_Additive, + BlendMode_Multiply, + BlendMode_Screen + }; +} + +#endif /* Spine_BlendMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Bone.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Bone.h new file mode 100644 index 0000000..7c53435 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Bone.h @@ -0,0 +1,272 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Bone_h +#define Spine_Bone_h + +#include +#include +#include + +namespace spine { + class BoneData; + + class Skeleton; + +/// Stores a bone's current pose. +/// +/// A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a +/// local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a +/// constraint or application code modifies the world transform after it was computed from the local transform. + class SP_API Bone : public Updatable { + friend class AnimationState; + + friend class RotateTimeline; + + friend class IkConstraint; + + friend class TransformConstraint; + + friend class VertexAttachment; + + friend class PathConstraint; + + friend class Skeleton; + + friend class RegionAttachment; + + friend class PointAttachment; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class ScaleTimeline; + + friend class ScaleXTimeline; + + friend class ScaleYTimeline; + + friend class ShearTimeline; + + friend class ShearXTimeline; + + friend class ShearYTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + RTTI_DECL + + public: + static void setYDown(bool inValue); + + static bool isYDown(); + + /// @param parent May be NULL. + Bone(BoneData &data, Skeleton &skeleton, Bone *parent = NULL); + + /// Same as updateWorldTransform. This method exists for Bone to implement Spine::Updatable. + virtual void update(); + + /// Computes the world transform using the parent bone and this bone's local transform. + void updateWorldTransform(); + + /// Computes the world transform using the parent bone and the specified local transform. + void + updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY); + + void setToSetupPose(); + + void worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY); + + void localToWorld(float localX, float localY, float &outWorldX, float &outWorldY); + + float worldToLocalRotation(float worldRotation); + + float localToWorldRotation(float localRotation); + + /// Rotates the world transform the specified amount and sets isAppliedValid to false. + /// @param degrees Degrees. + void rotateWorld(float degrees); + + float getWorldToLocalRotationX(); + + float getWorldToLocalRotationY(); + + BoneData &getData(); + + Skeleton &getSkeleton(); + + Bone *getParent(); + + Vector &getChildren(); + + /// The local X translation. + float getX(); + + void setX(float inValue); + + /// The local Y translation. + float getY(); + + void setY(float inValue); + + /// The local rotation. + float getRotation(); + + void setRotation(float inValue); + + /// The local scaleX. + float getScaleX(); + + void setScaleX(float inValue); + + /// The local scaleY. + float getScaleY(); + + void setScaleY(float inValue); + + /// The local shearX. + float getShearX(); + + void setShearX(float inValue); + + /// The local shearY. + float getShearY(); + + void setShearY(float inValue); + + /// The rotation, as calculated by any constraints. + float getAppliedRotation(); + + void setAppliedRotation(float inValue); + + /// The applied local x translation. + float getAX(); + + void setAX(float inValue); + + /// The applied local y translation. + float getAY(); + + void setAY(float inValue); + + /// The applied local scaleX. + float getAScaleX(); + + void setAScaleX(float inValue); + + /// The applied local scaleY. + float getAScaleY(); + + void setAScaleY(float inValue); + + /// The applied local shearX. + float getAShearX(); + + void setAShearX(float inValue); + + /// The applied local shearY. + float getAShearY(); + + void setAShearY(float inValue); + + float getA(); + + void setA(float inValue); + + float getB(); + + void setB(float inValue); + + float getC(); + + void setC(float inValue); + + float getD(); + + void setD(float inValue); + + float getWorldX(); + + void setWorldX(float inValue); + + float getWorldY(); + + void setWorldY(float inValue); + + float getWorldRotationX(); + + float getWorldRotationY(); + + /// Returns the magnitide (always positive) of the world scale X. + float getWorldScaleX(); + + /// Returns the magnitide (always positive) of the world scale Y. + float getWorldScaleY(); + + bool isActive(); + + void setActive(bool inValue); + + private: + static bool yDown; + + BoneData &_data; + Skeleton &_skeleton; + Bone *_parent; + Vector _children; + float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; + float _ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY; + float _a, _b, _worldX; + float _c, _d, _worldY; + bool _sorted; + bool _active; + + /// Computes the individual applied transform values from the world transform. This can be useful to perform processing using + /// the applied transform after the world transform has been modified directly (eg, by a constraint).. + /// + /// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. + void updateAppliedTransform(); + }; +} + +#endif /* Spine_Bone_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/BoneData.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/BoneData.h new file mode 100644 index 0000000..d2c6507 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -0,0 +1,140 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BoneData_h +#define Spine_BoneData_h + +#include +#include +#include +#include + +namespace spine { + class SP_API BoneData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + + friend class RotateTimeline; + + friend class ScaleTimeline; + + friend class ScaleXTimeline; + + friend class ScaleYTimeline; + + friend class ShearTimeline; + + friend class ShearXTimeline; + + friend class ShearYTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + public: + BoneData(int index, const String &name, BoneData *parent = NULL); + + /// The index of the bone in Skeleton.Bones + int getIndex(); + + /// The name of the bone, which is unique within the skeleton. + const String &getName(); + + /// May be NULL. + BoneData *getParent(); + + float getLength(); + + void setLength(float inValue); + + /// Local X translation. + float getX(); + + void setX(float inValue); + + /// Local Y translation. + float getY(); + + void setY(float inValue); + + /// Local rotation. + float getRotation(); + + void setRotation(float inValue); + + /// Local scaleX. + float getScaleX(); + + void setScaleX(float inValue); + + /// Local scaleY. + float getScaleY(); + + void setScaleY(float inValue); + + /// Local shearX. + float getShearX(); + + void setShearX(float inValue); + + /// Local shearY. + float getShearY(); + + void setShearY(float inValue); + + /// The transform mode for how parent world transforms affect this bone. + TransformMode getTransformMode(); + + void setTransformMode(TransformMode inValue); + + bool isSkinRequired(); + + void setSkinRequired(bool inValue); + + Color &getColor(); + + private: + const int _index; + const String _name; + BoneData *_parent; + float _length; + float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; + TransformMode _transformMode; + bool _skinRequired; + Color _color; + }; +} + +#endif /* Spine_BoneData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h new file mode 100644 index 0000000..fa2913f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BoundingBoxAttachment_h +#define Spine_BoundingBoxAttachment_h + +#include +#include +#include + +namespace spine { + /// Attachment that has a polygon for bounds checking. + class SP_API BoundingBoxAttachment : public VertexAttachment { + RTTI_DECL + + public: + explicit BoundingBoxAttachment(const String &name); + + Color &getColor(); + + virtual Attachment *copy(); + + private: + Color _color; + }; +} + +#endif /* Spine_BoundingBoxAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h new file mode 100644 index 0000000..05db2d2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ClippingAttachment_h +#define Spine_ClippingAttachment_h + +#include +#include + +namespace spine { + class SlotData; + + class SP_API ClippingAttachment : public VertexAttachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class SkeletonClipping; + + RTTI_DECL + + public: + explicit ClippingAttachment(const String &name); + + SlotData *getEndSlot(); + + void setEndSlot(SlotData *inValue); + + Color &getColor(); + + virtual Attachment *copy(); + + private: + SlotData *_endSlot; + Color _color; + }; +} + +#endif /* Spine_ClippingAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Color.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Color.h new file mode 100644 index 0000000..76822e5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Color.h @@ -0,0 +1,110 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_COLOR_H +#define SPINE_COLOR_H + +#include + +namespace spine { + class SP_API Color : public SpineObject { + public: + Color() : r(0), g(0), b(0), a(0) { + } + + Color(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) { + clamp(); + } + + inline Color &set(float _r, float _g, float _b, float _a) { + this->r = _r; + this->g = _g; + this->b = _b; + this->a = _a; + clamp(); + return *this; + } + + inline Color &set(float _r, float _g, float _b) { + this->r = _r; + this->g = _g; + this->b = _b; + clamp(); + return *this; + } + + inline Color &set(const Color &other) { + r = other.r; + g = other.g; + b = other.b; + a = other.a; + clamp(); + return *this; + } + + inline Color &add(float _r, float _g, float _b, float _a) { + this->r += _r; + this->g += _g; + this->b += _b; + this->a += _a; + clamp(); + return *this; + } + + inline Color &add(float _r, float _g, float _b) { + this->r += _r; + this->g += _g; + this->b += _b; + clamp(); + return *this; + } + + inline Color &add(const Color &other) { + r += other.r; + g += other.g; + b += other.b; + a += other.a; + clamp(); + return *this; + } + + inline Color &clamp() { + r = MathUtil::clamp(this->r, 0, 1); + g = MathUtil::clamp(this->g, 0, 1); + b = MathUtil::clamp(this->b, 0, 1); + a = MathUtil::clamp(this->a, 0, 1); + return *this; + } + + float r, g, b, a; + }; +} + + +#endif //SPINE_COLOR_H diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ColorTimeline.h new file mode 100644 index 0000000..ca41f4b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -0,0 +1,197 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ColorTimeline_h +#define Spine_ColorTimeline_h + +#include + +namespace spine { + class SP_API RGBATimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGBATimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, float r, float g, float b, float a); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + static const int ENTRIES = 5; + static const int R = 1; + static const int G = 2; + static const int B = 3; + static const int A = 4; + }; + + class SP_API RGBTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGBTimeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGBTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, float r, float g, float b); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + static const int ENTRIES = 4; + static const int R = 1; + static const int G = 2; + static const int B = 3; + }; + + class SP_API AlphaTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit AlphaTimeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~AlphaTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + }; + + class SP_API RGBA2Timeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGBA2Timeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGBA2Timeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + static const int ENTRIES = 8; + static const int R = 1; + static const int G = 2; + static const int B = 3; + static const int A = 4; + static const int R2 = 5; + static const int G2 = 6; + static const int B2 = 7; + }; + + class SP_API RGB2Timeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGB2Timeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGB2Timeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + static const int ENTRIES = 7; + static const int R = 1; + static const int G = 2; + static const int B = 3; + static const int R2 = 4; + static const int G2 = 5; + static const int B2 = 6; + }; +} + +#endif /* Spine_ColorTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ConstraintData.h new file mode 100644 index 0000000..7404072 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ConstraintData.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Constraint_h +#define Spine_Constraint_h + +#include +#include + +namespace spine { +/// The interface for all constraints. + class SP_API ConstraintData : public SpineObject { + + public: + ConstraintData(const String &name); + + virtual ~ConstraintData(); + + /// The IK constraint's name, which is unique within the skeleton. + const String &getName(); + + /// The ordinal for the order a skeleton's constraints will be applied. + size_t getOrder(); + + void setOrder(size_t inValue); + + /// Whether the constraint is only active for a specific skin. + bool isSkinRequired(); + + void setSkinRequired(bool inValue); + + private: + const String _name; + size_t _order; + bool _skinRequired; + }; +} + +#endif /* Spine_Constraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ContainerUtil.h new file mode 100644 index 0000000..fec59e9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ContainerUtil_h +#define Spine_ContainerUtil_h + +#include +#include +#include +#include +#include + +#include + +namespace spine { + class SP_API ContainerUtil : public SpineObject { + public: + /// Finds an item by comparing each item's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + template + static T *findWithName(Vector &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0; i < items.size(); ++i) { + T *item = items[i]; + if (item->getName() == name) { + return item; + } + } + + return NULL; + } + + /// @return -1 if the item was not found. + template + static int findIndexWithName(Vector &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0, len = items.size(); i < len; ++i) { + T *item = items[i]; + if (item->getName() == name) { + return static_cast(i); + } + } + + return -1; + } + + /// Finds an item by comparing each item's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + template + static T *findWithDataName(Vector &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0; i < items.size(); ++i) { + T *item = items[i]; + if (item->getData().getName() == name) { + return item; + } + } + + return NULL; + } + + /// @return -1 if the item was not found. + template + static int findIndexWithDataName(Vector &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0, len = items.size(); i < len; ++i) { + T *item = items[i]; + if (item->getData().getName() == name) { + return static_cast(i); + } + } + + return -1; + } + + template + static void cleanUpVectorOfPointers(Vector &items) { + for (int i = (int) items.size() - 1; i >= 0; i--) { + T *item = items[i]; + + delete item; + + items.removeAt(i); + } + } + + private: + // ctor, copy ctor, and assignment should be private in a Singleton + ContainerUtil(); + + ContainerUtil(const ContainerUtil &); + + ContainerUtil &operator=(const ContainerUtil &); + }; +} + +#endif /* Spine_ContainerUtil_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/CurveTimeline.h new file mode 100644 index 0000000..f4a9b86 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -0,0 +1,103 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_CurveTimeline_h +#define Spine_CurveTimeline_h + +#include +#include + +namespace spine { + /// Base class for frames that use an interpolation bezier curve. + class SP_API CurveTimeline : public Timeline { + RTTI_DECL + + public: + explicit CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount); + + virtual ~CurveTimeline(); + + void setLinear(size_t frame); + + void setStepped(size_t frame); + + virtual void + setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, + float cy2, float time2, float value2); + + float getBezierValue(float time, size_t frame, size_t valueOffset, size_t i); + + Vector &getCurves(); + + protected: + static const int LINEAR = 0; + static const int STEPPED = 1; + static const int BEZIER = 2; + static const int BEZIER_SIZE = 18; + + Vector _curves; // type, x, y, ... + }; + + class SP_API CurveTimeline1 : public CurveTimeline { + RTTI_DECL + + public: + explicit CurveTimeline1(size_t frameCount, size_t bezierCount); + + virtual ~CurveTimeline1(); + + void setFrame(size_t frame, float time, float value); + + float getCurveValue(float time); + + protected: + static const int ENTRIES = 2; + static const int VALUE = 1; + }; + + class SP_API CurveTimeline2 : public CurveTimeline { + RTTI_DECL + + public: + explicit CurveTimeline2(size_t frameCount, size_t bezierCount); + + virtual ~CurveTimeline2(); + + void setFrame(size_t frame, float time, float value1, float value2); + + float getCurveValue(float time); + + protected: + static const int ENTRIES = 3; + static const int VALUE1 = 1; + static const int VALUE2 = 2; + }; +} + +#endif /* Spine_CurveTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Debug.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Debug.h new file mode 100644 index 0000000..232d74b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Debug.h @@ -0,0 +1,131 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_LOG_H +#define SPINE_LOG_H + +#include +#include + +#include + +namespace spine { + + class SP_API DebugExtension : public SpineExtension { + struct Allocation { + void *address; + size_t size; + const char *fileName; + int line; + + Allocation() : address(NULL), size(0), fileName(NULL), line(0) { + } + + Allocation(void *a, size_t s, const char *f, int l) : address(a), size(s), fileName(f), line(l) { + } + }; + + public: + DebugExtension(SpineExtension *extension) : _extension(extension), _allocations(0), _reallocations(0), + _frees(0) { + } + + void reportLeaks() { + for (std::map::iterator it = _allocated.begin(); it != _allocated.end(); it++) { + printf("\"%s:%i (%zu bytes at %p)\n", it->second.fileName, it->second.line, it->second.size, + it->second.address); + } + printf("allocations: %zu, reallocations: %zu, frees: %zu\n", _allocations, _reallocations, _frees); + if (_allocated.empty()) printf("No leaks detected"); + } + + void clearAllocations() { + _allocated.clear(); + _usedMemory = 0; + } + + virtual void *_alloc(size_t size, const char *file, int line) { + void *result = _extension->_alloc(size, file, line); + _allocated[result] = Allocation(result, size, file, line); + _allocations++; + _usedMemory += size; + return result; + } + + virtual void *_calloc(size_t size, const char *file, int line) { + void *result = _extension->_calloc(size, file, line); + _allocated[result] = Allocation(result, size, file, line); + _allocations++; + _usedMemory += size; + return result; + } + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) { + if (_allocated.count(ptr)) _usedMemory -= _allocated[ptr].size; + _allocated.erase(ptr); + void *result = _extension->_realloc(ptr, size, file, line); + _reallocations++; + _allocated[result] = Allocation(result, size, file, line); + _usedMemory += size; + return result; + } + + virtual void _free(void *mem, const char *file, int line) { + if (_allocated.count(mem)) { + _extension->_free(mem, file, line); + _frees++; + _usedMemory -= _allocated[mem].size; + _allocated.erase(mem); + return; + } + + printf("%s:%i (address %p): Double free or not allocated through SpineExtension\n", file, line, mem); + _extension->_free(mem, file, line); + } + + virtual char *_readFile(const String &path, int *length) { + return _extension->_readFile(path, length); + } + + size_t getUsedMemory() { + return _usedMemory; + } + + private: + SpineExtension *_extension; + std::map _allocated; + size_t _allocations; + size_t _reallocations; + size_t _frees; + size_t _usedMemory; + }; +} + + +#endif //SPINE_LOG_H diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/DeformTimeline.h new file mode 100644 index 0000000..e43be91 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -0,0 +1,80 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DeformTimeline_h +#define Spine_DeformTimeline_h + +#include + +namespace spine { + class VertexAttachment; + + class SP_API DeformTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit DeformTimeline(size_t frameCount, size_t bezierCount, int slotIndex, VertexAttachment *attachment); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, Vector &vertices); + + Vector > &getVertices(); + + VertexAttachment *getAttachment(); + + void setAttachment(VertexAttachment *inValue); + + virtual void + setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, + float cy2, float time2, float value2); + + float getCurvePercent(float time, int frame); + + int getSlotIndex() { return _slotIndex; } + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + Vector > _vertices; + + VertexAttachment *_attachment; + }; +} + +#endif /* Spine_DeformTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h new file mode 100644 index 0000000..b78b90c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DrawOrderTimeline_h +#define Spine_DrawOrderTimeline_h + +#include + +namespace spine { + class SP_API DrawOrderTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit DrawOrderTimeline(size_t frameCount); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + /// @param drawOrder May be NULL to use bind pose draw order + void setFrame(size_t frame, float time, Vector &drawOrder); + + Vector > &getDrawOrders(); + + private: + Vector > _drawOrders; + }; +} + +#endif /* Spine_DrawOrderTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Event.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Event.h new file mode 100644 index 0000000..f8a7d77 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Event.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Event_h +#define Spine_Event_h + +#include +#include + +namespace spine { + class EventData; + +/// Stores the current pose values for an Event. + class SP_API Event : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + + public: + Event(float time, const EventData &data); + + const EventData &getData(); + + /// The animation time this event was keyed. + float getTime(); + + int getIntValue(); + + void setIntValue(int inValue); + + float getFloatValue(); + + void setFloatValue(float inValue); + + const String &getStringValue(); + + void setStringValue(const String &inValue); + + float getVolume(); + + void setVolume(float inValue); + + float getBalance(); + + void setBalance(float inValue); + + private: + const EventData &_data; + const float _time; + int _intValue; + float _floatValue; + String _stringValue; + float _volume; + float _balance; + }; +} + +#endif /* Spine_Event_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/EventData.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/EventData.h new file mode 100644 index 0000000..4e3d0eb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/EventData.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_EventData_h +#define Spine_EventData_h + +#include +#include + +namespace spine { +/// Stores the setup pose values for an Event. + class SP_API EventData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class Event; + + public: + explicit EventData(const String &name); + + /// The name of the event, which is unique within the skeleton. + const String &getName() const; + + int getIntValue() const; + + void setIntValue(int inValue); + + float getFloatValue() const; + + void setFloatValue(float inValue); + + const String &getStringValue() const; + + void setStringValue(const String &inValue); + + const String &getAudioPath() const; + + void setAudioPath(const String &inValue); + + float getVolume() const; + + void setVolume(float inValue); + + float getBalance() const; + + void setBalance(float inValue); + + private: + const String _name; + int _intValue; + float _floatValue; + String _stringValue; + String _audioPath; + float _volume; + float _balance; + }; +} + +#endif /* Spine_EventData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/EventTimeline.h new file mode 100644 index 0000000..f3d12fe --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_EventTimeline_h +#define Spine_EventTimeline_h + +#include + +namespace spine { + class SP_API EventTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit EventTimeline(size_t frameCount); + + ~EventTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(size_t frame, Event *event); + + Vector &getEvents(); + + private: + Vector _events; + }; +} + +#endif /* Spine_EventTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Extension.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Extension.h new file mode 100644 index 0000000..31d91da --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Extension.h @@ -0,0 +1,125 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Extension_h +#define Spine_Extension_h + + +#include +#include + +#define SP_UNUSED(x) (void)(x) + +namespace spine { + class String; + + class SP_API SpineExtension { + public: + template + static T *alloc(size_t num, const char *file, int line) { + return (T *) getInstance()->_alloc(sizeof(T) * num, file, line); + } + + template + static T *calloc(size_t num, const char *file, int line) { + return (T *) getInstance()->_calloc(sizeof(T) * num, file, line); + } + + template + static T *realloc(T *ptr, size_t num, const char *file, int line) { + return (T *) getInstance()->_realloc(ptr, sizeof(T) * num, file, line); + } + + template + static void free(T *ptr, const char *file, int line) { + getInstance()->_free((void *) ptr, file, line); + } + + template + static void beforeFree(T *ptr) { + getInstance()->_beforeFree((void *) ptr); + } + + static char *readFile(const String &path, int *length) { + return getInstance()->_readFile(path, length); + } + + static void setInstance(SpineExtension *inSpineExtension); + + static SpineExtension *getInstance(); + + virtual ~SpineExtension(); + + /// Implement this function to use your own memory allocator + virtual void *_alloc(size_t size, const char *file, int line) = 0; + + virtual void *_calloc(size_t size, const char *file, int line) = 0; + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) = 0; + + /// If you provide a spineAllocFunc, you should also provide a spineFreeFunc + virtual void _free(void *mem, const char *file, int line) = 0; + + virtual char *_readFile(const String &path, int *length) = 0; + + virtual void _beforeFree(void *ptr) { SP_UNUSED(ptr); } + + protected: + SpineExtension(); + + private: + static SpineExtension *_instance; + }; + + class SP_API DefaultSpineExtension : public SpineExtension { + public: + DefaultSpineExtension(); + + virtual ~DefaultSpineExtension(); + + protected: + virtual void *_alloc(size_t size, const char *file, int line) override; + + virtual void *_calloc(size_t size, const char *file, int line) override; + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) override; + + virtual void _free(void *mem, const char *file, int line) override; + + virtual char *_readFile(const String &path, int *length) override; + }; + +// This function is to be implemented by engine specific runtimes to provide +// the default extension for that engine. It is called the first time +// SpineExtension::getInstance() is called, when no instance has been set +// yet. + extern SpineExtension *getDefaultExtension(); +} + +#endif /* Spine_Extension_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/HasRendererObject.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/HasRendererObject.h new file mode 100644 index 0000000..d07648e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/HasRendererObject.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_HasRendererObject_h +#define Spine_HasRendererObject_h + +#include + +namespace spine { + + typedef void (*DisposeRendererObject)(void *rendererObject); + + class SP_API HasRendererObject { + public: + explicit HasRendererObject() : _rendererObject(0), _dispose(0) {}; + + virtual ~HasRendererObject() { + if (_dispose && _rendererObject) + _dispose(_rendererObject); + } + + void *getRendererObject() { return _rendererObject; } + + void setRendererObject(void *rendererObject, DisposeRendererObject dispose = 0) { + if (_dispose && _rendererObject && _rendererObject != rendererObject) + _dispose(_rendererObject); + + _rendererObject = rendererObject; + _dispose = dispose; + } + + private: + void *_rendererObject; + DisposeRendererObject _dispose; + }; + +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/HashMap.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/HashMap.h new file mode 100755 index 0000000..8b026aa --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -0,0 +1,198 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_HashMap_h +#define Spine_HashMap_h + +#include +#include +#include + +// Required for new with line number and file name in MSVC +#ifdef _MSC_VER +#pragma warning(disable:4291) +#endif + +namespace spine { + template + class SP_API HashMap : public SpineObject { + private: + class Entry; + + public: + class SP_API Pair { + public: + explicit Pair(K &k, V &v) : key(k), value(v) {} + + K &key; + V &value; + }; + + class SP_API Entries { + public: + friend class HashMap; + + explicit Entries(Entry *entry) : _entry(NULL), _hasChecked(false) { + _start.next = entry; + _entry = &_start; + } + + Pair next() { + assert(_entry); + assert(_hasChecked); + _entry = _entry->next; + Pair pair(_entry->_key, _entry->_value); + _hasChecked = false; + return pair; + } + + bool hasNext() { + _hasChecked = true; + return _entry->next; + } + + private: + bool _hasChecked; + Entry _start; + Entry *_entry; + }; + + HashMap() : + _head(NULL), + _size(0) { + } + + ~HashMap() { + clear(); + } + + void clear() { + for (Entry *entry = _head; entry != NULL;) { + Entry *next = entry->next; + delete entry; + entry = next; + } + _head = NULL; + _size = 0; + } + + size_t size() { + return _size; + } + + void put(const K &key, const V &value) { + Entry *entry = find(key); + if (entry) { + entry->_key = key; + entry->_value = value; + } else { + entry = new(__FILE__, __LINE__) Entry(); + entry->_key = key; + entry->_value = value; + + Entry *oldHead = _head; + + if (oldHead) { + _head = entry; + oldHead->prev = entry; + entry->next = oldHead; + } else { + _head = entry; + } + _size++; + } + } + + bool addAll(Vector &keys, const V &value) { + size_t oldSize = _size; + for (size_t i = 0; i < keys.size(); i++) { + put(keys[i], value); + } + return _size != oldSize; + } + + bool containsKey(const K &key) { + return find(key) != NULL; + } + + bool remove(const K &key) { + Entry *entry = find(key); + if (!entry) return false; + + Entry *prev = entry->prev; + Entry *next = entry->next; + + if (prev) prev->next = next; + else _head = next; + if (next) next->prev = entry->prev; + + delete entry; + _size--; + + return true; + } + + V operator[](const K &key) { + Entry *entry = find(key); + if (entry) return entry->_value; + else { + assert(false); + return 0; + } + } + + Entries getEntries() const { + return Entries(_head); + } + + private: + Entry *find(const K &key) { + for (Entry *entry = _head; entry != NULL; entry = entry->next) { + if (entry->_key == key) + return entry; + } + return NULL; + } + + class SP_API Entry : public SpineObject { + public: + K _key; + V _value; + Entry *next; + Entry *prev; + + Entry() : next(NULL), prev(NULL) {} + }; + + Entry *_head; + size_t _size; + }; +} + +#endif /* Spine_HashMap_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/IkConstraint.h new file mode 100644 index 0000000..93edacb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -0,0 +1,119 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraint_h +#define Spine_IkConstraint_h + +#include + +#include + +namespace spine { + class IkConstraintData; + + class Skeleton; + + class Bone; + + class SP_API IkConstraint : public Updatable { + friend class Skeleton; + + friend class IkConstraintTimeline; + + RTTI_DECL + + public: + /// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified + /// in the world coordinate system. + static void + apply(Bone &bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha); + + /// Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as + /// possible. The target is specified in the world coordinate system. + /// @param child A direct descendant of the parent bone. + static void + apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, bool uniform, + float softness, + float alpha); + + IkConstraint(IkConstraintData &data, Skeleton &skeleton); + + /// Applies the constraint to the constrained bones. + void apply(); + + virtual void update(); + + virtual int getOrder(); + + IkConstraintData &getData(); + + Vector &getBones(); + + Bone *getTarget(); + + void setTarget(Bone *inValue); + + int getBendDirection(); + + void setBendDirection(int inValue); + + bool getCompress(); + + void setCompress(bool inValue); + + bool getStretch(); + + void setStretch(bool inValue); + + float getMix(); + + void setMix(float inValue); + + float getSoftness(); + + void setSoftness(float inValue); + + bool isActive(); + + void setActive(bool inValue); + + private: + IkConstraintData &_data; + Vector _bones; + int _bendDirection; + bool _compress; + bool _stretch; + float _mix; + float _softness; + Bone *_target; + bool _active; + }; +} + +#endif /* Spine_IkConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/IkConstraintData.h new file mode 100644 index 0000000..9153eac --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -0,0 +1,100 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraintData_h +#define Spine_IkConstraintData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SP_API IkConstraintData : public ConstraintData { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class IkConstraint; + + friend class Skeleton; + + friend class IkConstraintTimeline; + + public: + explicit IkConstraintData(const String &name); + + /// The bones that are constrained by this IK Constraint. + Vector &getBones(); + + /// The bone that is the IK target. + BoneData *getTarget(); + + void setTarget(BoneData *inValue); + + /// Controls the bend direction of the IK bones, either 1 or -1. + int getBendDirection(); + + void setBendDirection(int inValue); + + bool getCompress(); + + void setCompress(bool inValue); + + bool getStretch(); + + void setStretch(bool inValue); + + bool getUniform(); + + void setUniform(bool inValue); + + float getMix(); + + void setMix(float inValue); + + float getSoftness(); + + void setSoftness(float inValue); + + private: + Vector _bones; + BoneData *_target; + int _bendDirection; + bool _compress; + bool _stretch; + bool _uniform; + float _mix; + float _softness; + }; +} + +#endif /* Spine_IkConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h new file mode 100644 index 0000000..3429fb3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraintTimeline_h +#define Spine_IkConstraintTimeline_h + +#include + +namespace spine { + + class SP_API IkConstraintTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit IkConstraintTimeline(size_t frameCount, size_t bezierCount, int ikConstraintIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time, mix and bend direction of the specified keyframe. + void setFrame(int frame, float time, float mix, float softness, int bendDirection, bool compress, bool stretch); + + int getIkConstraintIndex() { return _ikConstraintIndex; } + + void setIkConstraintIndex(int inValue) { _ikConstraintIndex = inValue; } + + private: + int _ikConstraintIndex; + + static const int ENTRIES = 6; + static const int MIX = 1; + static const int SOFTNESS = 2; + static const int BEND_DIRECTION = 3; + static const int COMPRESS = 4; + static const int STRETCH = 5; + }; +} + +#endif /* Spine_IkConstraintTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Json.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Json.h new file mode 100644 index 0000000..2d4de52 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Json.h @@ -0,0 +1,116 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Json_h +#define Spine_Json_h + +#include + +#ifndef SPINE_JSON_HAVE_PREV +/* spine doesn't use the "prev" link in the Json sibling lists. */ +#define SPINE_JSON_HAVE_PREV 0 +#endif + +namespace spine { + class SP_API Json : public SpineObject { + friend class SkeletonJson; + + public: + /* Json Types: */ + static const int JSON_FALSE; + static const int JSON_TRUE; + static const int JSON_NULL; + static const int JSON_NUMBER; + static const int JSON_STRING; + static const int JSON_ARRAY; + static const int JSON_OBJECT; + + /* Get item "string" from object. Case insensitive. */ + static Json *getItem(Json *object, const char *string); + + static Json *getItem(Json *object, int childIndex); + + static const char *getString(Json *object, const char *name, const char *defaultValue); + + static float getFloat(Json *object, const char *name, float defaultValue); + + static int getInt(Json *object, const char *name, int defaultValue); + + static bool getBoolean(Json *object, const char *name, bool defaultValue); + + /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when Json_create() returns 0. 0 when Json_create() succeeds. */ + static const char *getError(); + + /* Supply a block of JSON, and this returns a Json object you can interrogate. Call Json_dispose when finished. */ + explicit Json(const char *value); + + ~Json(); + + + private: + static const char *_error; + + Json *_next; +#if SPINE_JSON_HAVE_PREV + Json* _prev; /* next/prev allow you to walk array/object chains. Alternatively, use getSize/getItem */ +#endif + Json *_child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int _type; /* The type of the item, as above. */ + int _size; /* The number of children. */ + + const char *_valueString; /* The item's string, if type==JSON_STRING */ + int _valueInt; /* The item's number, if type==JSON_NUMBER */ + float _valueFloat; /* The item's number, if type==JSON_NUMBER */ + + const char *_name; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + + /* Utility to jump whitespace and cr/lf */ + static const char *skip(const char *inValue); + + /* Parser core - when encountering text, process appropriately. */ + static const char *parseValue(Json *item, const char *value); + + /* Parse the input text into an unescaped cstring, and populate item. */ + static const char *parseString(Json *item, const char *str); + + /* Parse the input text to generate a number, and populate the result into item. */ + static const char *parseNumber(Json *item, const char *num); + + /* Build an array from input text. */ + static const char *parseArray(Json *item, const char *value); + + /* Build an object from the text. */ + static const char *parseObject(Json *item, const char *value); + + static int json_strcasecmp(const char *s1, const char *s2); + }; +} + +#endif /* Spine_Json_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/LinkedMesh.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/LinkedMesh.h new file mode 100644 index 0000000..9647c07 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/LinkedMesh.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_LinkedMesh_h +#define Spine_LinkedMesh_h + +#include +#include + +namespace spine { + class MeshAttachment; + + class SP_API LinkedMesh : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + public: + LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, + bool inheritDeform); + + private: + MeshAttachment *_mesh; + String _skin; + size_t _slotIndex; + String _parent; + bool _inheritDeform; + }; +} + +#endif /* Spine_LinkedMesh_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Log.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Log.h new file mode 100644 index 0000000..9fa9f39 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Log.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_DEBUG_LOG_H +#define SPINE_DEBUG_LOG_H + +#include + +namespace spine { + SP_API void spDebug_printSkeletonData(SkeletonData *skeletonData); + + SP_API void spDebug_printAnimation(Animation *animation); + + SP_API void spDebug_printTimeline(Timeline *timeline); + + SP_API void spDebug_printBoneDatas(Vector &boneDatas); + + SP_API void spDebug_printBoneData(BoneData *boneData); + + SP_API void spDebug_printSkeleton(Skeleton *skeleton); + + SP_API void spDebug_printBones(Vector &bones); + + SP_API void spDebug_printBone(Bone *bone); + + SP_API void spDebug_printFloats(float *values, int numFloats); + + SP_API void spDebug_printFloats(Vector &values); +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/MathUtil.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/MathUtil.h new file mode 100644 index 0000000..ff07972 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MathUtil_h +#define Spine_MathUtil_h + +#include + +#include + +namespace spine { + + class SP_API MathUtil : public SpineObject { + private: + MathUtil(); + + public: + static const float Pi; + static const float Pi_2; + static const float Deg_Rad; + static const float Rad_Deg; + + template + static inline T min(T a, T b) { return a < b ? a : b; } + + template + static inline T max(T a, T b) { return a > b ? a : b; } + + static float sign(float val); + + static float clamp(float x, float lower, float upper); + + static float abs(float v); + + /// Returns the sine in radians from a lookup table. + static float sin(float radians); + + /// Returns the cosine in radians from a lookup table. + static float cos(float radians); + + /// Returns the sine in radians from a lookup table. + static float sinDeg(float degrees); + + /// Returns the cosine in radians from a lookup table. + static float cosDeg(float degrees); + + /// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 + /// degrees), largest error of 0.00488 radians (0.2796 degrees). + static float atan2(float y, float x); + + static float acos(float v); + + static float sqrt(float v); + + static float fmod(float a, float b); + + static bool isNan(float v); + + static float random(); + + static float randomTriangular(float min, float max); + + static float randomTriangular(float min, float max, float mode); + + static float pow(float a, float b); + }; + + struct SP_API Interpolation { + virtual float apply(float a) = 0; + + virtual float interpolate(float start, float end, float a) { + return start + (end - start) * apply(a); + } + + virtual ~Interpolation() {}; + }; + + struct SP_API PowInterpolation : public Interpolation { + PowInterpolation(int power) : power(power) { + } + + float apply(float a) { + if (a <= 0.5f) return MathUtil::pow(a * 2.0f, (float) power) / 2.0f; + return MathUtil::pow((a - 1.0f) * 2.0f, (float) power) / (power % 2 == 0 ? -2.0f : 2.0f) + 1.0f; + } + + int power; + }; + + struct SP_API PowOutInterpolation : public Interpolation { + PowOutInterpolation(int power) : power(power) { + } + + float apply(float a) { + return MathUtil::pow(a - 1, (float) power) * (power % 2 == 0 ? -1.0f : 1.0f) + 1.0f; + } + + int power; + }; + +} + +#endif /* Spine_MathUtil_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/MeshAttachment.h new file mode 100644 index 0000000..92eb44d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -0,0 +1,159 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MeshAttachment_h +#define Spine_MeshAttachment_h + +#include +#include +#include +#include + +namespace spine { + /// Attachment that displays a texture region using a mesh. + class SP_API MeshAttachment : public VertexAttachment, public HasRendererObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AtlasAttachmentLoader; + + RTTI_DECL + + public: + explicit MeshAttachment(const String &name); + + virtual ~MeshAttachment(); + + void updateUVs(); + + int getHullLength(); + + void setHullLength(int inValue); + + Vector &getRegionUVs(); + + /// The UV pair for each vertex, normalized within the entire texture. See also MeshAttachment::updateUVs + Vector &getUVs(); + + Vector &getTriangles(); + + Color &getColor(); + + const String &getPath(); + + void setPath(const String &inValue); + + float getRegionU(); + + void setRegionU(float inValue); + + float getRegionV(); + + void setRegionV(float inValue); + + float getRegionU2(); + + void setRegionU2(float inValue); + + float getRegionV2(); + + void setRegionV2(float inValue); + + int getRegionDegrees(); + + void setRegionDegrees(int inValue); + + float getRegionOffsetX(); + + void setRegionOffsetX(float inValue); + + // Pixels stripped from the bottom left, unrotated. + float getRegionOffsetY(); + + void setRegionOffsetY(float inValue); + + float getRegionWidth(); + + void setRegionWidth(float inValue); + + // Unrotated, stripped size. + float getRegionHeight(); + + void setRegionHeight(float inValue); + + float getRegionOriginalWidth(); + + void setRegionOriginalWidth(float inValue); + + // Unrotated, unstripped size. + float getRegionOriginalHeight(); + + void setRegionOriginalHeight(float inValue); + + MeshAttachment *getParentMesh(); + + void setParentMesh(MeshAttachment *inValue); + + // Nonessential. + Vector &getEdges(); + + float getWidth(); + + void setWidth(float inValue); + + float getHeight(); + + void setHeight(float inValue); + + virtual Attachment *copy(); + + MeshAttachment *newLinkedMesh(); + + private: + float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; + MeshAttachment *_parentMesh; + Vector _uvs; + Vector _regionUVs; + Vector _triangles; + Vector _edges; + String _path; + float _regionU; + float _regionV; + float _regionU2; + float _regionV2; + float _width; + float _height; + Color _color; + int _hullLength; + int _regionDegrees; + }; +} + +#endif /* Spine_MeshAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/MixBlend.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/MixBlend.h new file mode 100644 index 0000000..2aa403f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/MixBlend.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MixPose_h +#define Spine_MixPose_h + +namespace spine { + +/// Controls how a timeline is mixed with the setup or current pose. +/// See also Timeline::apply(Skeleton&, float, float, Vector&, float, Blend, MixDirection) + enum MixBlend { + MixBlend_Setup = 0, + MixBlend_First, + MixBlend_Replace, + MixBlend_Add + }; +} + +#endif /* Spine_MixPose_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/MixDirection.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/MixDirection.h new file mode 100644 index 0000000..5b09c2c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/MixDirection.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MixDirection_h +#define Spine_MixDirection_h + +namespace spine { + +/// Indicates whether a timeline's alpha is mixing out over time toward 0 (the setup or current pose) or mixing in toward 1 (the timeline's pose). +/// See also Timeline::apply(Skeleton&, float, float, Vector&, float, MixPose, MixDirection) + enum MixDirection { + MixDirection_In = 0, + MixDirection_Out + }; + +} + +#endif /* Spine_MixDirection_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathAttachment.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathAttachment.h new file mode 100644 index 0000000..6ab1e99 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathAttachment.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathAttachment_h +#define Spine_PathAttachment_h + +#include +#include + +namespace spine { + class SP_API PathAttachment : public VertexAttachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathAttachment(const String &name); + + /// The length in the setup pose from the start of the path to the end of each curve. + Vector &getLengths(); + + bool isClosed(); + + void setClosed(bool inValue); + + bool isConstantSpeed(); + + void setConstantSpeed(bool inValue); + + Color &getColor(); + + virtual Attachment *copy(); + + private: + Vector _lengths; + bool _closed; + bool _constantSpeed; + Color _color; + }; +} + +#endif /* Spine_PathAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraint.h new file mode 100644 index 0000000..3cd8a4a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -0,0 +1,134 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraint_h +#define Spine_PathConstraint_h + +#include + +#include + +namespace spine { + class PathConstraintData; + + class Skeleton; + + class PathAttachment; + + class Bone; + + class Slot; + + class SP_API PathConstraint : public Updatable { + friend class Skeleton; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + RTTI_DECL + + public: + PathConstraint(PathConstraintData &data, Skeleton &skeleton); + + /// Applies the constraint to the constrained bones. + void apply(); + + virtual void update(); + + virtual int getOrder(); + + float getPosition(); + + void setPosition(float inValue); + + float getSpacing(); + + void setSpacing(float inValue); + + float getMixRotate(); + + void setMixRotate(float inValue); + + float getMixX(); + + void setMixX(float inValue); + + float getMixY(); + + void setMixY(float inValue); + + Vector &getBones(); + + Slot *getTarget(); + + void setTarget(Slot *inValue); + + PathConstraintData &getData(); + + bool isActive(); + + void setActive(bool inValue); + + private: + static const float EPSILON; + static const int NONE; + static const int BEFORE; + static const int AFTER; + + PathConstraintData &_data; + Vector _bones; + Slot *_target; + float _position, _spacing; + float _mixRotate, _mixX, _mixY; + + Vector _spaces; + Vector _positions; + Vector _world; + Vector _curves; + Vector _lengths; + Vector _segments; + + bool _active; + + Vector &computeWorldPositions(PathAttachment &path, int spacesCount, bool tangents); + + static void addBeforePosition(float p, Vector &temp, int i, Vector &output, int o); + + static void addAfterPosition(float p, Vector &temp, int i, Vector &output, int o); + + static void + addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, + Vector &output, int o, bool tangents); + }; +} + +#endif /* Spine_PathConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraintData.h new file mode 100644 index 0000000..fffaa5a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -0,0 +1,118 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintData_h +#define Spine_PathConstraintData_h + +#include +#include +#include +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SlotData; + + class SP_API PathConstraintData : public ConstraintData { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class PathConstraint; + + friend class Skeleton; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + public: + explicit PathConstraintData(const String &name); + + Vector &getBones(); + + SlotData *getTarget(); + + void setTarget(SlotData *inValue); + + PositionMode getPositionMode(); + + void setPositionMode(PositionMode inValue); + + SpacingMode getSpacingMode(); + + void setSpacingMode(SpacingMode inValue); + + RotateMode getRotateMode(); + + void setRotateMode(RotateMode inValue); + + float getOffsetRotation(); + + void setOffsetRotation(float inValue); + + float getPosition(); + + void setPosition(float inValue); + + float getSpacing(); + + void setSpacing(float inValue); + + float getMixRotate(); + + void setMixRotate(float inValue); + + float getMixX(); + + void setMixX(float inValue); + + float getMixY(); + + void setMixY(float inValue); + + private: + Vector _bones; + SlotData *_target; + PositionMode _positionMode; + SpacingMode _spacingMode; + RotateMode _rotateMode; + float _offsetRotation; + float _position, _spacing; + float _mixRotate, _mixX, _mixY; + }; +} + +#endif /* Spine_PathConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h new file mode 100644 index 0000000..4e4e387 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -0,0 +1,69 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintMixTimeline_h +#define Spine_PathConstraintMixTimeline_h + +#include + +namespace spine { +#define SP_PATHCONSTRAINTMIXTIMELINE_ENTRIES 5 + + class SP_API PathConstraintMixTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathConstraintMixTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and mixes of the specified keyframe. + void setFrame(int frameIndex, float time, float mixRotate, float mixX, float mixY); + + int getPathConstraintIndex() { return _pathConstraintIndex; } + + void setPathConstraintIndex(int inValue) { _pathConstraintIndex = inValue; } + + private: + int _pathConstraintIndex; + + static const int ENTRIES = 4; + static const int ROTATE = 1; + static const int X = 2; + static const int Y = 2; + }; +} + +#endif /* Spine_PathConstraintMixTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h new file mode 100644 index 0000000..b2644e6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintPositionTimeline_h +#define Spine_PathConstraintPositionTimeline_h + +#include + +namespace spine { + + class SP_API PathConstraintPositionTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + static const int ENTRIES; + + explicit PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex); + + virtual ~PathConstraintPositionTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getPathConstraintIndex() { return _pathConstraintIndex; } + + void setPathConstraintIndex(int inValue) { _pathConstraintIndex = inValue; } + + protected: + int _pathConstraintIndex; + }; +} + +#endif /* Spine_PathConstraintPositionTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h new file mode 100644 index 0000000..b0990db --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintSpacingTimeline_h +#define Spine_PathConstraintSpacingTimeline_h + +#include + +namespace spine { + class SP_API PathConstraintSpacingTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathConstraintSpacingTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getPathConstraintIndex() { return _pathConstraintIndex; } + + void setPathConstraintIndex(int inValue) { _pathConstraintIndex = inValue; } + + protected: + int _pathConstraintIndex; + }; +} + +#endif /* Spine_PathConstraintSpacingTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PointAttachment.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PointAttachment.h new file mode 100644 index 0000000..940cd75 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PointAttachment.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PointAttachment_h +#define Spine_PointAttachment_h + +#include +#include + +namespace spine { + class Bone; + + /// An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be + /// used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a + /// skin. + /// + /// See http://esotericsoftware.com/spine-point-attachments for Point Attachments in the Spine User Guide. + /// + class SP_API PointAttachment : public Attachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PointAttachment(const String &name); + + void computeWorldPosition(Bone &bone, float &ox, float &oy); + + float computeWorldRotation(Bone &bone); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getRotation(); + + void setRotation(float inValue); + + Color &getColor(); + + virtual Attachment *copy(); + + private: + float _x, _y, _rotation; + Color _color; + }; +} + +#endif /* Spine_PointAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Pool.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Pool.h new file mode 100644 index 0000000..ebcdc79 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Pool.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Pool_h +#define Spine_Pool_h + +#include +#include +#include +#include + +namespace spine { + template + class SP_API Pool : public SpineObject { + public: + Pool() { + } + + ~Pool() { + ContainerUtil::cleanUpVectorOfPointers(_objects); + } + + T *obtain() { + if (_objects.size() > 0) { + T **object = &_objects[_objects.size() - 1]; + T *ret = *object; + _objects.removeAt(_objects.size() - 1); + + return ret; + } else { + T *ret = new(__FILE__, __LINE__) T(); + + return ret; + } + } + + void free(T *object) { + if (!_objects.contains(object)) { + _objects.add(object); + } + } + + private: + Vector _objects; + }; +} + +#endif /* Spine_Pool_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PositionMode.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PositionMode.h new file mode 100644 index 0000000..3d2b9b6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/PositionMode.h @@ -0,0 +1,40 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PositionMode_h +#define Spine_PositionMode_h + +namespace spine { + enum PositionMode { + PositionMode_Fixed = 0, + PositionMode_Percent + }; +} + +#endif /* Spine_PositionMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Property.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Property.h new file mode 100644 index 0000000..66b4c65 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Property.h @@ -0,0 +1,58 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Property_h +#define Spine_Property_h + +namespace spine { + typedef long long PropertyId; + enum Property { + Property_Rotate = 1 << 0, + Property_X = 1 << 1, + Property_Y = 1 << 2, + Property_ScaleX = 1 << 3, + Property_ScaleY = 1 << 4, + Property_ShearX = 1 << 5, + Property_ShearY = 1 << 6, + Property_Rgb = 1 << 7, + Property_Alpha = 1 << 8, + Property_Rgb2 = 1 << 9, + Property_Attachment = 1 << 10, + Property_Deform = 1 << 11, + Property_Event = 1 << 12, + Property_DrawOrder = 1 << 13, + Property_IkConstraint = 1 << 14, + Property_TransformConstraint = 1 << 15, + Property_PathConstraintPosition = 1 << 16, + Property_PathConstraintSpacing = 1 << 17, + Property_PathConstraintMix = 1 << 18 + }; +} + +#endif /* Spine_Property_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/RTTI.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/RTTI.h new file mode 100644 index 0000000..3ebd18e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/RTTI.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RTTI_h +#define Spine_RTTI_h + +#include + +namespace spine { + class SP_API RTTI { + public: + explicit RTTI(const char *className); + + RTTI(const char *className, const RTTI &baseRTTI); + + const char *getClassName() const; + + bool isExactly(const RTTI &rtti) const; + + bool instanceOf(const RTTI &rtti) const; + + private: + // Prevent copying + RTTI(const RTTI &obj); + + RTTI &operator=(const RTTI &obj); + + const char *_className; + const RTTI *_pBaseRTTI; + }; +} + +#define RTTI_DECL \ +public: \ +static const spine::RTTI rtti; \ +virtual const spine::RTTI& getRTTI() const; + +#define RTTI_IMPL_NOPARENT(name) \ +const spine::RTTI name::rtti(#name); \ +const spine::RTTI& name::getRTTI() const { return rtti; } + +#define RTTI_IMPL(name, parent) \ +const spine::RTTI name::rtti(#name, parent::rtti); \ +const spine::RTTI& name::getRTTI() const { return rtti; } + +#endif /* Spine_RTTI_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/RegionAttachment.h new file mode 100644 index 0000000..268fff8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -0,0 +1,157 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RegionAttachment_h +#define Spine_RegionAttachment_h + +#include +#include +#include + +#include + +#define NUM_UVS 8 + +namespace spine { + class Bone; + + /// Attachment that displays a texture region. + class SP_API RegionAttachment : public Attachment, public HasRendererObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AtlasAttachmentLoader; + + RTTI_DECL + + public: + explicit RegionAttachment(const String &name); + + void updateOffset(); + + void setUVs(float u, float v, float u2, float v2, float degrees); + + /// Transforms the attachment's four vertices to world coordinates. + /// @param bone The parent bone. + /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8. + /// @param offset The worldVertices index to begin writing values. + /// @param stride The number of worldVertices entries between the value pairs written. + void computeWorldVertices(Bone &bone, float *worldVertices, size_t offset, size_t stride = 2); + + void computeWorldVertices(Bone &bone, Vector &worldVertices, size_t offset, size_t stride = 2); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getRotation(); + + void setRotation(float inValue); + + float getScaleX(); + + void setScaleX(float inValue); + + float getScaleY(); + + void setScaleY(float inValue); + + float getWidth(); + + void setWidth(float inValue); + + float getHeight(); + + void setHeight(float inValue); + + Color &getColor(); + + const String &getPath(); + + void setPath(const String &inValue); + + float getRegionOffsetX(); + + void setRegionOffsetX(float inValue); + + float getRegionOffsetY(); + + void setRegionOffsetY(float inValue); + + float getRegionWidth(); + + void setRegionWidth(float inValue); + + float getRegionHeight(); + + void setRegionHeight(float inValue); + + float getRegionOriginalWidth(); + + void setRegionOriginalWidth(float inValue); + + float getRegionOriginalHeight(); + + void setRegionOriginalHeight(float inValue); + + Vector &getOffset(); + + Vector &getUVs(); + + virtual Attachment *copy(); + + private: + static const int BLX; + static const int BLY; + static const int ULX; + static const int ULY; + static const int URX; + static const int URY; + static const int BRX; + static const int BRY; + + float _x, _y, _rotation, _scaleX, _scaleY, _width, _height; + float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; + Vector _vertexOffset; + Vector _uvs; + String _path; + float _regionU; + float _regionV; + float _regionU2; + float _regionV2; + Color _color; + }; +} + +#endif /* Spine_RegionAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/RotateMode.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/RotateMode.h new file mode 100644 index 0000000..51ecafd --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/RotateMode.h @@ -0,0 +1,41 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RotateMode_h +#define Spine_RotateMode_h + +namespace spine { + enum RotateMode { + RotateMode_Tangent = 0, + RotateMode_Chain, + RotateMode_ChainScale + }; +} + +#endif /* Spine_RotateMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/RotateTimeline.h new file mode 100644 index 0000000..13f0581 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RotateTimeline_h +#define Spine_RotateTimeline_h + +#include + +namespace spine { + class SP_API RotateTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + + RTTI_DECL + + public: + explicit RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; +} + +#endif /* Spine_RotateTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h new file mode 100644 index 0000000..8d7b667 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -0,0 +1,109 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ScaleTimeline_h +#define Spine_ScaleTimeline_h + +#include + +namespace spine { + class SP_API ScaleTimeline : public CurveTimeline2 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ScaleTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API ScaleXTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ScaleXTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API ScaleYTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ScaleYTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; +} + +#endif /* Spine_ScaleTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ShearTimeline.h new file mode 100644 index 0000000..45c5262 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -0,0 +1,109 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ShearTimeline_h +#define Spine_ShearTimeline_h + +#include + +namespace spine { + class SP_API ShearTimeline : public CurveTimeline2 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ShearTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API ShearXTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ShearXTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API ShearYTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ShearYTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; +} + +#endif /* Spine_ShearTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Skeleton.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Skeleton.h new file mode 100644 index 0000000..2bfa8b2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -0,0 +1,260 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Skeleton_h +#define Spine_Skeleton_h + +#include +#include +#include +#include +#include + +namespace spine { + class SkeletonData; + + class Bone; + + class Updatable; + + class Slot; + + class IkConstraint; + + class PathConstraint; + + class TransformConstraint; + + class Skin; + + class Attachment; + + class SP_API Skeleton : public SpineObject { + friend class AnimationState; + + friend class SkeletonBounds; + + friend class SkeletonClipping; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class ScaleTimeline; + + friend class ScaleXTimeline; + + friend class ScaleYTimeline; + + friend class ShearTimeline; + + friend class ShearXTimeline; + + friend class ShearYTimeline; + + friend class TransformConstraintTimeline; + + friend class RotateTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + friend class TwoColorTimeline; + + public: + explicit Skeleton(SkeletonData *skeletonData); + + ~Skeleton(); + + /// Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added + /// or removed. + void updateCache(); + + void printUpdateCache(); + + /// Updates the world transform for each bone and applies constraints. + void updateWorldTransform(); + + void updateWorldTransform(Bone *parent); + + /// Sets the bones, constraints, and slots to their setup pose values. + void setToSetupPose(); + + /// Sets the bones and constraints to their setup pose values. + void setBonesToSetupPose(); + + void setSlotsToSetupPose(); + + /// @return May be NULL. + Bone *findBone(const String &boneName); + + /// @return May be NULL. + Slot *findSlot(const String &slotName); + + /// Sets a skin by name (see setSkin). + void setSkin(const String &skinName); + + /// Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. + /// If there was no old skin, each slot's setup mode attachment is attached from the new skin. + /// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling + /// See Skeleton::setSlotsToSetupPose() + /// Also, often AnimationState::apply(Skeleton&) is called before the next time the + /// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. + /// @param newSkin May be NULL. + void setSkin(Skin *newSkin); + + /// @return May be NULL. + Attachment *getAttachment(const String &slotName, const String &attachmentName); + + /// @return May be NULL. + Attachment *getAttachment(int slotIndex, const String &attachmentName); + + /// @param attachmentName May be empty. + void setAttachment(const String &slotName, const String &attachmentName); + + /// @return May be NULL. + IkConstraint *findIkConstraint(const String &constraintName); + + /// @return May be NULL. + TransformConstraint *findTransformConstraint(const String &constraintName); + + /// @return May be NULL. + PathConstraint *findPathConstraint(const String &constraintName); + + void update(float delta); + + /// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. + /// @param outX The horizontal distance between the skeleton origin and the left side of the AABB. + /// @param outY The vertical distance between the skeleton origin and the bottom side of the AABB. + /// @param outWidth The width of the AABB + /// @param outHeight The height of the AABB. + /// @param outVertexBuffer Reference to hold a Vector of floats. This method will assign it with new floats as needed. + void getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector &outVertexBuffer); + + Bone *getRootBone(); + + SkeletonData *getData(); + + Vector &getBones(); + + Vector &getUpdateCacheList(); + + Vector &getSlots(); + + Vector &getDrawOrder(); + + Vector &getIkConstraints(); + + Vector &getPathConstraints(); + + Vector &getTransformConstraints(); + + Skin *getSkin(); + + Color &getColor(); + + float getTime(); + + void setTime(float inValue); + + void setPosition(float x, float y); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getScaleX(); + + void setScaleX(float inValue); + + float getScaleY(); + + void setScaleY(float inValue); + + private: + SkeletonData *_data; + Vector _bones; + Vector _slots; + Vector _drawOrder; + Vector _ikConstraints; + Vector _transformConstraints; + Vector _pathConstraints; + Vector _updateCache; + Skin *_skin; + Color _color; + float _time; + float _scaleX, _scaleY; + float _x, _y; + + void sortIkConstraint(IkConstraint *constraint); + + void sortPathConstraint(PathConstraint *constraint); + + void sortTransformConstraint(TransformConstraint *constraint); + + void sortPathConstraintAttachment(Skin *skin, size_t slotIndex, Bone &slotBone); + + void sortPathConstraintAttachment(Attachment *attachment, Bone &slotBone); + + void sortBone(Bone *bone); + + static void sortReset(Vector &bones); + }; +} + +#endif /* Spine_Skeleton_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h new file mode 100644 index 0000000..9e0d4e8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -0,0 +1,161 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonBinary_h +#define Spine_SkeletonBinary_h + +#include +#include +#include +#include +#include + +namespace spine { + class SkeletonData; + + class Atlas; + + class AttachmentLoader; + + class LinkedMesh; + + class Skin; + + class Attachment; + + class VertexAttachment; + + class Animation; + + class Timeline; + + class CurveTimeline; + + class CurveTimeline1; + + class CurveTimeline2; + + class SP_API SkeletonBinary : public SpineObject { + public: + static const int BONE_ROTATE = 0; + static const int BONE_TRANSLATE = 1; + static const int BONE_TRANSLATEX = 2; + static const int BONE_TRANSLATEY = 3; + static const int BONE_SCALE = 4; + static const int BONE_SCALEX = 5; + static const int BONE_SCALEY = 6; + static const int BONE_SHEAR = 7; + static const int BONE_SHEARX = 8; + static const int BONE_SHEARY = 9; + + static const int SLOT_ATTACHMENT = 0; + static const int SLOT_RGBA = 1; + static const int SLOT_RGB = 2; + static const int SLOT_RGBA2 = 3; + static const int SLOT_RGB2 = 4; + static const int SLOT_ALPHA = 5; + + static const int PATH_POSITION = 0; + static const int PATH_SPACING = 1; + static const int PATH_MIX = 2; + + static const int CURVE_LINEAR = 0; + static const int CURVE_STEPPED = 1; + static const int CURVE_BEZIER = 2; + + explicit SkeletonBinary(Atlas *atlasArray); + + explicit SkeletonBinary(AttachmentLoader *attachmentLoader, bool ownsLoader = false); + + ~SkeletonBinary(); + + SkeletonData *readSkeletonData(const unsigned char *binary, int length); + + SkeletonData *readSkeletonDataFile(const String &path); + + void setScale(float scale) { _scale = scale; } + + String &getError() { return _error; } + + private: + struct DataInput : public SpineObject { + const unsigned char *cursor; + const unsigned char *end; + }; + + AttachmentLoader *_attachmentLoader; + Vector _linkedMeshes; + String _error; + float _scale; + const bool _ownsLoader; + + void setError(const char *value1, const char *value2); + + char *readString(DataInput *input); + + char *readStringRef(DataInput *input, SkeletonData *skeletonData); + + float readFloat(DataInput *input); + + unsigned char readByte(DataInput *input); + + signed char readSByte(DataInput *input); + + bool readBoolean(DataInput *input); + + int readInt(DataInput *input); + + void readColor(DataInput *input, Color &color); + + int readVarint(DataInput *input, bool optimizePositive); + + Skin *readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential); + + Attachment *readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName, + SkeletonData *skeletonData, bool nonessential); + + void readVertices(DataInput *input, VertexAttachment *attachment, int vertexCount); + + void readFloatArray(DataInput *input, int n, float scale, Vector &array); + + void readShortArray(DataInput *input, Vector &array); + + Animation *readAnimation(const String &name, DataInput *input, SkeletonData *skeletonData); + + void + setBezier(DataInput *input, CurveTimeline *timeline, int bezier, int frame, int value, float time1, float time2, + float value1, float value2, float scale); + + Timeline *readTimeline(DataInput *input, CurveTimeline1 *timeline, float scale); + + Timeline *readTimeline2(DataInput *input, CurveTimeline2 *timeline, float scale); + }; +} + +#endif /* Spine_SkeletonBinary_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h new file mode 100644 index 0000000..5d38df0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h @@ -0,0 +1,110 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonBounds_h +#define Spine_SkeletonBounds_h + +#include +#include +#include + +namespace spine { + class Skeleton; + + class BoundingBoxAttachment; + + class Polygon; + + /// Collects each BoundingBoxAttachment that is visible and computes the world vertices for its polygon. + /// The polygon vertices are provided along with convenience methods for doing hit detection. + class SP_API SkeletonBounds : public SpineObject { + public: + SkeletonBounds(); + + ~SkeletonBounds(); + + /// Clears any previous polygons, finds all visible bounding box attachments, + /// and computes the world vertices for each bounding box's polygon. + /// @param skeleton The skeleton. + /// @param updateAabb + /// If true, the axis aligned bounding box containing all the polygons is computed. + /// If false, the SkeletonBounds AABB methods will always return true. + /// + void update(Skeleton &skeleton, bool updateAabb); + + /// Returns true if the axis aligned bounding box contains the point. + bool aabbcontainsPoint(float x, float y); + + /// Returns true if the axis aligned bounding box intersects the line segment. + bool aabbintersectsSegment(float x1, float y1, float x2, float y2); + + /// Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. + bool aabbIntersectsSkeleton(SkeletonBounds bounds); + + /// Returns true if the polygon contains the point. + bool containsPoint(Polygon *polygon, float x, float y); + + /// Returns the first bounding box attachment that contains the point, or NULL. When doing many checks, it is usually more + /// efficient to only call this method if {@link #aabbcontainsPoint(float, float)} returns true. + BoundingBoxAttachment *containsPoint(float x, float y); + + /// Returns the first bounding box attachment that contains the line segment, or NULL. When doing many checks, it is usually + /// more efficient to only call this method if {@link #aabbintersectsSegment(float, float, float, float)} returns true. + BoundingBoxAttachment *intersectsSegment(float x1, float y1, float x2, float y2); + + /// Returns true if the polygon contains the line segment. + bool intersectsSegment(Polygon *polygon, float x1, float y1, float x2, float y2); + + Polygon *getPolygon(BoundingBoxAttachment *attachment); + + float getWidth(); + + float getHeight(); + + private: + Pool _polygonPool; + Vector _boundingBoxes; + Vector _polygons; + float _minX, _minY, _maxX, _maxY; + + void aabbCompute(); + }; + + class Polygon : public SpineObject { + public: + Vector _vertices; + int _count; + + Polygon() : _count(0) { + _vertices.ensureCapacity(16); + } + }; +} + +#endif /* Spine_SkeletonBounds_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h new file mode 100644 index 0000000..e6b0dcc --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h @@ -0,0 +1,85 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonClipping_h +#define Spine_SkeletonClipping_h + +#include +#include + +namespace spine { + class Slot; + + class ClippingAttachment; + + class SP_API SkeletonClipping : public SpineObject { + public: + SkeletonClipping(); + + size_t clipStart(Slot &slot, ClippingAttachment *clip); + + void clipEnd(Slot &slot); + + void clipEnd(); + + void + clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength, float *uvs, size_t stride); + + void + clipTriangles(Vector &vertices, Vector &triangles, Vector &uvs, size_t stride); + + bool isClipping(); + + Vector &getClippedVertices(); + + Vector &getClippedTriangles(); + + Vector &getClippedUVs(); + + private: + Triangulator _triangulator; + Vector _clippingPolygon; + Vector _clipOutput; + Vector _clippedVertices; + Vector _clippedTriangles; + Vector _clippedUVs; + Vector _scratch; + ClippingAttachment *_clipAttachment; + Vector *> *_clippingPolygons; + + /** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping + * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */ + bool clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector *clippingArea, + Vector *output); + + static void makeClockwise(Vector &polygon); + }; +} + +#endif /* Spine_SkeletonClipping_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonData.h new file mode 100644 index 0000000..e64f65b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonData.h @@ -0,0 +1,182 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonData_h +#define Spine_SkeletonData_h + +#include +#include + +namespace spine { + class BoneData; + + class SlotData; + + class Skin; + + class EventData; + + class Animation; + + class IkConstraintData; + + class TransformConstraintData; + + class PathConstraintData; + +/// Stores the setup pose and all of the stateless data for a skeleton. + class SP_API SkeletonData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class Skeleton; + + public: + SkeletonData(); + + ~SkeletonData(); + + /// Finds a bone by comparing each bone's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + BoneData *findBone(const String &boneName); + + /// @return May be NULL. + SlotData *findSlot(const String &slotName); + + /// @return May be NULL. + Skin *findSkin(const String &skinName); + + /// @return May be NULL. + spine::EventData *findEvent(const String &eventDataName); + + /// @return May be NULL. + Animation *findAnimation(const String &animationName); + + /// @return May be NULL. + IkConstraintData *findIkConstraint(const String &constraintName); + + /// @return May be NULL. + TransformConstraintData *findTransformConstraint(const String &constraintName); + + /// @return May be NULL. + PathConstraintData *findPathConstraint(const String &constraintName); + + const String &getName(); + + void setName(const String &inValue); + + /// The skeleton's bones, sorted parent first. The root bone is always the first bone. + Vector &getBones(); + + Vector &getSlots(); + + /// All skins, including the default skin. + Vector &getSkins(); + + /// The skeleton's default skin. + /// By default this skin contains all attachments that were not in a skin in Spine. + /// @return May be NULL. + Skin *getDefaultSkin(); + + void setDefaultSkin(Skin *inValue); + + Vector &getEvents(); + + Vector &getAnimations(); + + Vector &getIkConstraints(); + + Vector &getTransformConstraints(); + + Vector &getPathConstraints(); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getWidth(); + + void setWidth(float inValue); + + float getHeight(); + + void setHeight(float inValue); + + /// The Spine version used to export this data, or NULL. + const String &getVersion(); + + void setVersion(const String &inValue); + + const String &getHash(); + + void setHash(const String &inValue); + + const String &getImagesPath(); + + void setImagesPath(const String &inValue); + + const String &getAudioPath(); + + void setAudioPath(const String &inValue); + + /// The dopesheet FPS in Spine. Available only when nonessential data was exported. + float getFps(); + + void setFps(float inValue); + + private: + String _name; + Vector _bones; // Ordered parents first + Vector _slots; // Setup pose draw order. + Vector _skins; + Skin *_defaultSkin; + Vector _events; + Vector _animations; + Vector _ikConstraints; + Vector _transformConstraints; + Vector _pathConstraints; + float _x, _y, _width, _height; + String _version; + String _hash; + Vector _strings; + + // Nonessential. + float _fps; + String _imagesPath; + String _audioPath; + }; +} + +#endif /* Spine_SkeletonData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonJson.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonJson.h new file mode 100644 index 0000000..ce2932b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SkeletonJson.h @@ -0,0 +1,110 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonJson_h +#define Spine_SkeletonJson_h + +#include +#include +#include + +namespace spine { + class Timeline; + + class CurveTimeline; + + class CurveTimeline1; + + class CurveTimeline2; + + class VertexAttachment; + + class Animation; + + class Json; + + class SkeletonData; + + class Atlas; + + class AttachmentLoader; + + class LinkedMesh; + + class String; + + class SP_API SkeletonJson : public SpineObject { + public: + explicit SkeletonJson(Atlas *atlas); + + explicit SkeletonJson(AttachmentLoader *attachmentLoader, bool ownsLoader = false); + + ~SkeletonJson(); + + SkeletonData *readSkeletonDataFile(const String &path); + + SkeletonData *readSkeletonData(const char *json); + + void setScale(float scale) { _scale = scale; } + + String &getError() { return _error; } + + private: + AttachmentLoader *_attachmentLoader; + Vector _linkedMeshes; + float _scale; + const bool _ownsLoader; + String _error; + + static void + setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1, + float cy1, + float cx2, float cy2, float time2, float value2); + + static int + readCurve(Json *curve, CurveTimeline *timeline, int bezier, int frame, int value, float time1, float time2, + float value1, float value2, float scale); + + static Timeline *readTimeline(Json *keyMap, CurveTimeline1 *timeline, float defaultValue, float scale); + + static Timeline * + readTimeline(Json *keyMap, CurveTimeline2 *timeline, const char *name1, const char *name2, float defaultValue, + float scale); + + Animation *readAnimation(Json *root, SkeletonData *skeletonData); + + void readVertices(Json *attachmentMap, VertexAttachment *attachment, size_t verticesLength); + + void setError(Json *root, const String &value1, const String &value2); + + int findSlotIndex(SkeletonData *skeletonData, const String &slotName, Vector timelines); + }; +} + +#endif /* Spine_SkeletonJson_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Skin.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Skin.h new file mode 100644 index 0000000..364ee2d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Skin.h @@ -0,0 +1,167 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Skin_h +#define Spine_Skin_h + +#include +#include + +namespace spine { + class Attachment; + + class Skeleton; + + class BoneData; + + class ConstraintData; + +/// Stores attachments by slot index and attachment name. +/// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and +/// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide. + class SP_API Skin : public SpineObject { + friend class Skeleton; + + public: + class SP_API AttachmentMap : public SpineObject { + friend class Skin; + + public: + struct SP_API Entry { + size_t _slotIndex; + String _name; + Attachment *_attachment; + + Entry(size_t slotIndex, const String &name, Attachment *attachment) : + _slotIndex(slotIndex), + _name(name), + _attachment(attachment) { + } + }; + + class SP_API Entries { + friend class AttachmentMap; + + public: + bool hasNext() { + while (true) { + if (_slotIndex >= _buckets.size()) return false; + if (_bucketIndex >= _buckets[_slotIndex].size()) { + _bucketIndex = 0; + ++_slotIndex; + continue; + }; + return true; + } + } + + Entry &next() { + Entry &result = _buckets[_slotIndex][_bucketIndex]; + ++_bucketIndex; + return result; + } + + protected: + Entries(Vector > &buckets) : _buckets(buckets), _slotIndex(0), _bucketIndex(0) { + } + + private: + Vector > &_buckets; + size_t _slotIndex; + size_t _bucketIndex; + }; + + void put(size_t slotIndex, const String &attachmentName, Attachment *attachment); + + Attachment *get(size_t slotIndex, const String &attachmentName); + + void remove(size_t slotIndex, const String &attachmentName); + + Entries getEntries(); + + protected: + AttachmentMap(); + + private: + + int findInBucket(Vector &, const String &attachmentName); + + Vector > _buckets; + }; + + explicit Skin(const String &name); + + ~Skin(); + + /// Adds an attachment to the skin for the specified slot index and name. + /// If the name already exists for the slot, the previous value is replaced. + void setAttachment(size_t slotIndex, const String &name, Attachment *attachment); + + /// Returns the attachment for the specified slot index and name, or NULL. + Attachment *getAttachment(size_t slotIndex, const String &name); + + // Removes the attachment from the skin. + void removeAttachment(size_t slotIndex, const String &name); + + /// Finds the skin keys for a given slot. The results are added to the passed array of names. + /// @param slotIndex The target slotIndex. To find the slot index, use SkeletonData::findSlot and SlotData::getIndex. + /// @param names Found skin key names will be added to this array. + void findNamesForSlot(size_t slotIndex, Vector &names); + + /// Finds the attachments for a given slot. The results are added to the passed array of Attachments. + /// @param slotIndex The target slotIndex. To find the slot index, use SkeletonData::findSlot and SlotData::getIndex. + /// @param attachments Found Attachments will be added to this array. + void findAttachmentsForSlot(size_t slotIndex, Vector &attachments); + + const String &getName(); + + /// Adds all attachments, bones, and constraints from the specified skin to this skin. + void addSkin(Skin *other); + + /// Adds all attachments, bones, and constraints from the specified skin to this skin. Attachments are deep copied. + void copySkin(Skin *other); + + AttachmentMap::Entries getAttachments(); + + Vector &getBones(); + + Vector &getConstraints(); + + private: + const String _name; + AttachmentMap _attachments; + Vector _bones; + Vector _constraints; + + /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. + void attachAll(Skeleton &skeleton, Skin &oldSkin); + }; +} + +#endif /* Spine_Skin_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Slot.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Slot.h new file mode 100644 index 0000000..7346e6f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Slot.h @@ -0,0 +1,137 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Slot_h +#define Spine_Slot_h + +#include +#include +#include + +namespace spine { + class SlotData; + + class Bone; + + class Skeleton; + + class Attachment; + + class SP_API Slot : public SpineObject { + friend class VertexAttachment; + + friend class Skeleton; + + friend class SkeletonBounds; + + friend class SkeletonClipping; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TwoColorTimeline; + + public: + Slot(SlotData &data, Bone &bone); + + void setToSetupPose(); + + SlotData &getData(); + + Bone &getBone(); + + Skeleton &getSkeleton(); + + Color &getColor(); + + Color &getDarkColor(); + + bool hasDarkColor(); + + /// May be NULL. + Attachment *getAttachment(); + + void setAttachment(Attachment *inValue); + + int getAttachmentState(); + + void setAttachmentState(int state); + + float getAttachmentTime(); + + void setAttachmentTime(float inValue); + + Vector &getDeform(); + + private: + SlotData &_data; + Bone &_bone; + Skeleton &_skeleton; + Color _color; + Color _darkColor; + bool _hasDarkColor; + Attachment *_attachment; + int _attachmentState; + float _attachmentTime; + Vector _deform; + }; +} + +#endif /* Spine_Slot_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SlotData.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SlotData.h new file mode 100644 index 0000000..7d227d5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SlotData_h +#define Spine_SlotData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SP_API SlotData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TwoColorTimeline; + + public: + SlotData(int index, const String &name, BoneData &boneData); + + int getIndex(); + + const String &getName(); + + BoneData &getBoneData(); + + Color &getColor(); + + Color &getDarkColor(); + + bool hasDarkColor(); + + void setHasDarkColor(bool inValue); + + /// May be empty. + const String &getAttachmentName(); + + void setAttachmentName(const String &inValue); + + BlendMode getBlendMode(); + + void setBlendMode(BlendMode inValue); + + private: + const int _index; + String _name; + BoneData &_boneData; + Color _color; + Color _darkColor; + + bool _hasDarkColor; + String _attachmentName; + BlendMode _blendMode; + }; +} + +#endif /* Spine_SlotData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SpacingMode.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SpacingMode.h new file mode 100644 index 0000000..c329a19 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SpacingMode.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SpacingMode_h +#define Spine_SpacingMode_h + +namespace spine { + enum SpacingMode { + SpacingMode_Length = 0, + SpacingMode_Fixed, + SpacingMode_Percent, + SpacingMode_Proportional + }; +} + +#endif /* Spine_SpacingMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SpineObject.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SpineObject.h new file mode 100644 index 0000000..b636e4a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SpineObject.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Object_h +#define Spine_Object_h + +#include +#include + +#include + +namespace spine { + class String; + + class SP_API SpineObject { + public: + void *operator new(size_t sz); + + void *operator new(size_t sz, const char *file, int line); + + void *operator new(size_t sz, void *ptr); + + void operator delete(void *p, const char *file, int line); + + void operator delete(void *p, void *mem); + + void operator delete(void *p); + + virtual ~SpineObject(); + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SpineString.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SpineString.h new file mode 100644 index 0000000..442ea20 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/SpineString.h @@ -0,0 +1,212 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_STRING_H +#define SPINE_STRING_H + +#include +#include + +#include +#include + +// Required for sprintf on MSVC +#ifdef _MSC_VER +#pragma warning(disable:4996) +#endif + +namespace spine { + class SP_API String : public SpineObject { + public: + String() : _length(0), _buffer(NULL) { + } + + String(const char *chars, bool own = false) { + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + if (!own) { + _buffer = SpineExtension::calloc(_length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, chars, _length + 1); + } else { + _buffer = (char *) chars; + } + } + } + + String(const String &other) { + if (!other._buffer) { + _length = 0; + _buffer = NULL; + } else { + _length = other._length; + _buffer = SpineExtension::calloc(other._length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, other._buffer, other._length + 1); + } + } + + size_t length() const { + return _length; + } + + bool isEmpty() const { + return _length == 0; + } + + const char *buffer() const { + return _buffer; + } + + void own(const String &other) { + if (this == &other) return; + if (_buffer) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + _length = other._length; + _buffer = other._buffer; + other._length = 0; + other._buffer = NULL; + } + + void own(const char *chars) { + if (_buffer == chars) return; + if (_buffer) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + _buffer = (char *) chars; + } + } + + void unown() { + _length = 0; + _buffer = NULL; + } + + String &operator=(const String &other) { + if (this == &other) return *this; + if (_buffer) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + if (!other._buffer) { + _length = 0; + _buffer = NULL; + } else { + _length = other._length; + _buffer = SpineExtension::calloc(other._length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, other._buffer, other._length + 1); + } + return *this; + } + + String &operator=(const char *chars) { + if (_buffer == chars) return *this; + if (_buffer) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + _buffer = SpineExtension::calloc(_length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, chars, _length + 1); + } + return *this; + } + + String &append(const char *chars) { + size_t len = strlen(chars); + size_t thisLen = _length; + _length = _length + len; + bool same = chars == _buffer; + _buffer = SpineExtension::realloc(_buffer, _length + 1, __FILE__, __LINE__); + memcpy((void *) (_buffer + thisLen), (void *) (same ? _buffer : chars), len + 1); + return *this; + } + + String &append(const String &other) { + size_t len = other.length(); + size_t thisLen = _length; + _length = _length + len; + bool same = other._buffer == _buffer; + _buffer = SpineExtension::realloc(_buffer, _length + 1, __FILE__, __LINE__); + memcpy((void *) (_buffer + thisLen), (void *) (same ? _buffer : other._buffer), len + 1); + return *this; + } + + String &append(int other) { + char str[100]; + sprintf(str, "%i", other); + append(str); + return *this; + } + + String &append(float other) { + char str[100]; + sprintf(str, "%f", other); + append(str); + return *this; + } + + friend bool operator==(const String &a, const String &b) { + if (a._buffer == b._buffer) return true; + if (a._length != b._length) return false; + if (a._buffer && b._buffer) { + return strcmp(a._buffer, b._buffer) == 0; + } else { + return false; + } + } + + friend bool operator!=(const String &a, const String &b) { + return !(a == b); + } + + ~String() { + if (_buffer) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + } + + private: + mutable size_t _length; + mutable char *_buffer; + }; +} + + +#endif //SPINE_STRING_H diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TextureLoader.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TextureLoader.h new file mode 100644 index 0000000..66c59fa --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TextureLoader.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TextureLoader_h +#define Spine_TextureLoader_h + +#include +#include + +namespace spine { + class AtlasPage; + + class SP_API TextureLoader : public SpineObject { + public: + TextureLoader(); + + virtual ~TextureLoader(); + + virtual void load(AtlasPage &page, const String &path) = 0; + + virtual void unload(void *texture) = 0; + }; +} + +#endif /* Spine_TextureLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Timeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Timeline.h new file mode 100644 index 0000000..8ead35b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Timeline_h +#define Spine_Timeline_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + class Skeleton; + + class Event; + + class SP_API Timeline : public SpineObject { + RTTI_DECL + + public: + Timeline(size_t frameCount, size_t frameEntries); + + virtual ~Timeline(); + + /// Sets the value(s) for the specified time. + /// @param skeleton The skeleton the timeline is being applied to. This provides access to the bones, slots, and other skeleton components the timeline may change. + /// @param lastTime lastTime The time this timeline was last applied. Timelines such as EventTimeline trigger only at specific times rather than every frame. In that case, the timeline triggers everything between lastTime (exclusive) and time (inclusive). + /// @param time The time within the animation. Most timelines find the key before and the key after this time so they can interpolate between the keys. + /// @param pEvents If any events are fired, they are added to this array. Can be NULL to ignore firing events or if the timeline does not fire events. May be NULL. + /// @param alpha alpha 0 applies the current or setup pose value (depending on pose parameter). 1 applies the timeline + /// value. Between 0 and 1 applies a value between the current or setup pose and the timeline value. By adjusting alpha over + /// time, an animation can be mixed in or out. alpha can also be useful to apply animations on top of each other (layered). + /// @param blend Controls how mixing is applied when alpha is than 1. + /// @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions such as DrawOrderTimeline and AttachmentTimeline. + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction) = 0; + + size_t getFrameEntries(); + + size_t getFrameCount(); + + Vector &getFrames(); + + float getDuration(); + + virtual Vector &getPropertyIds(); + + protected: + void setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount); + + Vector _propertyIds; + Vector _frames; + size_t _frameEntries; + }; +} + +#endif /* Spine_Timeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TransformConstraint.h new file mode 100644 index 0000000..123140e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraint_h +#define Spine_TransformConstraint_h + +#include + +#include + +namespace spine { + class TransformConstraintData; + + class Skeleton; + + class Bone; + + class SP_API TransformConstraint : public Updatable { + friend class Skeleton; + + friend class TransformConstraintTimeline; + + RTTI_DECL + + public: + TransformConstraint(TransformConstraintData &data, Skeleton &skeleton); + + virtual void update(); + + virtual int getOrder(); + + TransformConstraintData &getData(); + + Vector &getBones(); + + Bone *getTarget(); + + void setTarget(Bone *inValue); + + float getMixRotate(); + + void setMixRotate(float inValue); + + float getMixX(); + + void setMixX(float inValue); + + float getMixY(); + + void setMixY(float inValue); + + float getMixScaleX(); + + void setMixScaleX(float inValue); + + float getMixScaleY(); + + void setMixScaleY(float inValue); + + float getMixShearY(); + + void setMixShearY(float inValue); + + bool isActive(); + + void setActive(bool inValue); + + private: + TransformConstraintData &_data; + Vector _bones; + Bone *_target; + float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY; + bool _active; + + void applyAbsoluteWorld(); + + void applyRelativeWorld(); + + void applyAbsoluteLocal(); + + void applyRelativeLocal(); + }; +} + +#endif /* Spine_TransformConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h new file mode 100644 index 0000000..cc5c686 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -0,0 +1,96 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraintData_h +#define Spine_TransformConstraintData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SP_API TransformConstraintData : public ConstraintData { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class TransformConstraint; + + friend class Skeleton; + + friend class TransformConstraintTimeline; + + public: + explicit TransformConstraintData(const String &name); + + Vector &getBones(); + + BoneData *getTarget(); + + float getMixRotate(); + + float getMixX(); + + float getMixY(); + + float getMixScaleX(); + + float getMixScaleY(); + + float getMixShearY(); + + float getOffsetRotation(); + + float getOffsetX(); + + float getOffsetY(); + + float getOffsetScaleX(); + + float getOffsetScaleY(); + + float getOffsetShearY(); + + bool isRelative(); + + bool isLocal(); + + private: + Vector _bones; + BoneData *_target; + float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY; + float _offsetRotation, _offsetX, _offsetY, _offsetScaleX, _offsetScaleY, _offsetShearY; + bool _relative, _local; + }; +} + +#endif /* Spine_TransformConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h new file mode 100644 index 0000000..517eb44 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraintTimeline_h +#define Spine_TransformConstraintTimeline_h + +#include + +namespace spine { + + class SP_API TransformConstraintTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TransformConstraintTimeline(size_t frameCount, size_t bezierCount, int transformConstraintIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + void setFrame(size_t frameIndex, float time, float mixRotate, float mixX, float mixY, float mixScaleX, + float mixScaleY, float mixShearY); + + int getTransformConstraintIndex() { return _transformConstraintIndex; } + + void setTransformConstraintIndex(int inValue) { _transformConstraintIndex = inValue; } + + private: + int _transformConstraintIndex; + + static const int ENTRIES = 7; + static const int ROTATE = 1; + static const int X = 2; + static const int Y = 3; + static const int SCALEX = 4; + static const int SCALEY = 5; + static const int SHEARY = 6; + }; +} + +#endif /* Spine_TransformConstraintTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TransformMode.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TransformMode.h new file mode 100644 index 0000000..c4da701 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TransformMode.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformMode_h +#define Spine_TransformMode_h + +namespace spine { + enum TransformMode { + TransformMode_Normal = 0, + TransformMode_OnlyTranslation, + TransformMode_NoRotationOrReflection, + TransformMode_NoScale, + TransformMode_NoScaleOrReflection + }; +} + +#endif /* Spine_TransformMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h new file mode 100644 index 0000000..e5134ce --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TranslateTimeline_h +#define Spine_TranslateTimeline_h + +#include + +#include +#include + +namespace spine { + + class SP_API TranslateTimeline : public CurveTimeline2 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~TranslateTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API TranslateXTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~TranslateXTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API TranslateYTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~TranslateYTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; +} + +#endif /* Spine_TranslateTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Triangulator.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Triangulator.h new file mode 100644 index 0000000..af77fa5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Triangulator.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Triangulator_h +#define Spine_Triangulator_h + +#include +#include + +namespace spine { + class SP_API Triangulator : public SpineObject { + public: + ~Triangulator(); + + Vector &triangulate(Vector &vertices); + + Vector* > & + decompose(Vector + &vertices, + Vector &triangles + ); + + private: + Vector* > + _convexPolygons; + Vector* > + _convexPolygonsIndices; + + Vector _indices; + Vector _isConcaveArray; + Vector _triangles; + + Pool > _polygonPool; + Pool > _polygonIndicesPool; + + static bool isConcave(int index, int vertexCount, Vector &vertices, Vector &indices); + + static bool positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y); + + static int winding(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y); + }; +} + +#endif /* Spine_Triangulator_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Updatable.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Updatable.h new file mode 100644 index 0000000..5cfe1b7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Updatable.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Updatable_h +#define Spine_Updatable_h + +#include +#include + +namespace spine { + class SP_API Updatable : public SpineObject { + RTTI_DECL + + public: + Updatable(); + + virtual ~Updatable(); + + virtual void update() = 0; + + virtual bool isActive() = 0; + + virtual void setActive(bool inValue) = 0; + }; +} + +#endif /* Spine_Updatable_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Vector.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Vector.h new file mode 100644 index 0000000..ba5771b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Vector.h @@ -0,0 +1,222 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Vector_h +#define Spine_Vector_h + +#include +#include +#include +#include + +namespace spine { + template + class SP_API Vector : public SpineObject { + public: + Vector() : _size(0), _capacity(0), _buffer(NULL) { + } + + Vector(const Vector &inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL) { + if (_capacity > 0) { + _buffer = allocate(_capacity); + for (size_t i = 0; i < _size; ++i) { + construct(_buffer + i, inVector._buffer[i]); + } + } + } + + ~Vector() { + clear(); + deallocate(_buffer); + } + + inline void clear() { + for (size_t i = 0; i < _size; ++i) { + destroy(_buffer + (_size - 1 - i)); + } + + _size = 0; + } + + inline size_t getCapacity() const { + return _capacity; + } + + inline size_t size() const { + return _size; + } + + inline void setSize(size_t newSize, const T &defaultValue) { + assert(newSize >= 0); + size_t oldSize = _size; + _size = newSize; + if (_capacity < newSize) { + _capacity = (int) (_size * 1.75f); + if (_capacity < 8) _capacity = 8; + _buffer = spine::SpineExtension::realloc(_buffer, _capacity, __FILE__, __LINE__); + } + if (oldSize < _size) { + for (size_t i = oldSize; i < _size; i++) { + construct(_buffer + i, defaultValue); + } + } + } + + inline void ensureCapacity(size_t newCapacity = 0) { + if (_capacity >= newCapacity) return; + _capacity = newCapacity; + _buffer = SpineExtension::realloc(_buffer, newCapacity, __FILE__, __LINE__); + } + + inline void add(const T &inValue) { + if (_size == _capacity) { + // inValue might reference an element in this buffer + // When we reallocate, the reference becomes invalid. + // We thus need to create a defensive copy before + // reallocating. + T valueCopy = inValue; + _capacity = (int) (_size * 1.75f); + if (_capacity < 8) _capacity = 8; + _buffer = spine::SpineExtension::realloc(_buffer, _capacity, __FILE__, __LINE__); + construct(_buffer + _size++, valueCopy); + } else { + construct(_buffer + _size++, inValue); + } + } + + inline void addAll(Vector &inValue) { + ensureCapacity(this->size() + inValue.size()); + for (size_t i = 0; i < inValue.size(); i++) { + add(inValue[i]); + } + } + + inline void clearAndAddAll(Vector &inValue) { + this->clear(); + this->addAll(inValue); + } + + inline void removeAt(size_t inIndex) { + assert(inIndex < _size); + + --_size; + + if (inIndex != _size) { + for (size_t i = inIndex; i < _size; ++i) { + T tmp(_buffer[i]); + _buffer[i] = _buffer[i + 1]; + _buffer[i + 1] = tmp; + } + } + + destroy(_buffer + _size); + } + + inline bool contains(const T &inValue) { + for (size_t i = 0; i < _size; ++i) { + if (_buffer[i] == inValue) { + return true; + } + } + + return false; + } + + inline int indexOf(const T &inValue) { + for (size_t i = 0; i < _size; ++i) { + if (_buffer[i] == inValue) { + return (int) i; + } + } + + return -1; + } + + inline T &operator[](size_t inIndex) { + assert(inIndex < _size); + + return _buffer[inIndex]; + } + + inline friend bool operator==(Vector &lhs, Vector &rhs) { + if (lhs.size() != rhs.size()) { + return false; + } + + for (size_t i = 0, n = lhs.size(); i < n; ++i) { + if (lhs[i] != rhs[i]) { + return false; + } + } + + return true; + } + + inline friend bool operator!=(Vector &lhs, Vector &rhs) { + return !(lhs == rhs); + } + + inline T *buffer() { + return _buffer; + } + + private: + size_t _size; + size_t _capacity; + T *_buffer; + + inline T *allocate(size_t n) { + assert(n > 0); + + T *ptr = SpineExtension::calloc(n, __FILE__, __LINE__); + + assert(ptr); + + return ptr; + } + + inline void deallocate(T *buffer) { + if (_buffer) { + SpineExtension::free(buffer, __FILE__, __LINE__); + } + } + + inline void construct(T *buffer, const T &val) { + new(buffer) T(val); + } + + inline void destroy(T *buffer) { + buffer->~T(); + } + + // Vector &operator=(const Vector &inVector) {}; + }; +} + +#endif /* Spine_Vector_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/VertexAttachment.h new file mode 100644 index 0000000..a8d4a21 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_VertexAttachment_h +#define Spine_VertexAttachment_h + +#include + +#include + +namespace spine { + class Slot; + + /// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices. + class SP_API VertexAttachment : public Attachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class DeformTimeline; + + RTTI_DECL + + public: + explicit VertexAttachment(const String &name); + + virtual ~VertexAttachment(); + + void computeWorldVertices(Slot &slot, float *worldVertices); + + void computeWorldVertices(Slot &slot, Vector &worldVertices); + + /// Transforms local vertices to world coordinates. + /// @param start The index of the first Vertices value to transform. Each vertex has 2 values, x and y. + /// @param count The number of world vertex values to output. Must be less than or equal to WorldVerticesLength - start. + /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + count. + /// @param offset The worldVertices index to begin writing values. + /// @param stride The number of worldVertices entries between the value pairs written. + void computeWorldVertices(Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride = 2); + + void computeWorldVertices(Slot &slot, size_t start, size_t count, Vector &worldVertices, size_t offset, + size_t stride = 2); + + /// Gets a unique ID for this attachment. + int getId(); + + Vector &getBones(); + + Vector &getVertices(); + + size_t getWorldVerticesLength(); + + void setWorldVerticesLength(size_t inValue); + + VertexAttachment *getDeformAttachment(); + + void setDeformAttachment(VertexAttachment *attachment); + + void copyTo(VertexAttachment *other); + + protected: + Vector _bones; + Vector _vertices; + size_t _worldVerticesLength; + VertexAttachment *_deformAttachment; + + private: + const int _id; + + static int getNextID(); + }; +} + +#endif /* Spine_VertexAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/VertexEffect.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/VertexEffect.h new file mode 100644 index 0000000..6ed7be9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/VertexEffect.h @@ -0,0 +1,120 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_VertexEffect_h +#define Spine_VertexEffect_h + +#include +#include + +namespace spine { + + class Skeleton; + + class Color; + + class SP_API VertexEffect : public SpineObject { + public: + virtual void begin(Skeleton &skeleton) = 0; + + virtual void transform(float &x, float &y, float &u, float &v, Color &light, Color &dark) = 0; + + virtual void end() = 0; + }; + + class SP_API JitterVertexEffect : public VertexEffect { + public: + JitterVertexEffect(float jitterX, float jitterY); + + void begin(Skeleton &skeleton); + + void transform(float &x, float &y, float &u, float &v, Color &light, Color &dark); + + void end(); + + void setJitterX(float jitterX); + + float getJitterX(); + + void setJitterY(float jitterY); + + float getJitterY(); + + protected: + float _jitterX; + float _jitterY; + }; + + class SP_API SwirlVertexEffect : public VertexEffect { + public: + SwirlVertexEffect(float radius, Interpolation &interpolation); + + void begin(Skeleton &skeleton); + + void transform(float &x, float &y, float &u, float &v, Color &light, Color &dark); + + void end(); + + void setCenterX(float centerX); + + float getCenterX(); + + void setCenterY(float centerY); + + float getCenterY(); + + void setRadius(float radius); + + float getRadius(); + + void setAngle(float angle); + + float getAngle(); + + void setWorldX(float worldX); + + float getWorldX(); + + void setWorldY(float worldY); + + float getWorldY(); + + protected: + float _centerX; + float _centerY; + float _radius; + float _angle; + float _worldX; + float _worldY; + + Interpolation &_interpolation; + }; +} + +#endif /* Spine_VertexEffect_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Vertices.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Vertices.h new file mode 100644 index 0000000..21d3f18 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/Vertices.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Vertices_h +#define Spine_Vertices_h + +#include + +namespace spine { + class SP_API Vertices : public SpineObject { + public: + Vector _bones; + Vector _vertices; + }; +} + +#endif /* Spine_Vertices_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/dll.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/dll.h new file mode 100644 index 0000000..2fe0160 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/dll.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SHAREDLIB_H +#define SPINE_SHAREDLIB_H + +#ifdef _WIN32 +#define DLLIMPORT __declspec(dllimport) +#define DLLEXPORT __declspec(dllexport) +#else +#ifndef DLLIMPORT +#define DLLIMPORT +#endif +#ifndef DLLEXPORT +#define DLLEXPORT +#endif +#endif + +#ifdef SPINEPLUGIN_API +#define SP_API SPINEPLUGIN_API +#else +#define SP_API +#endif + +#endif /* SPINE_SHAREDLIB_H */ diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/spine.h b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/spine.h new file mode 100644 index 0000000..901a786 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/include/spine/spine.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SPINE_H_ +#define SPINE_SPINE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Animation.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Animation.cpp new file mode 100644 index 0000000..4320dfb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Animation.cpp @@ -0,0 +1,111 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include +#include + +#include + +#include + +using namespace spine; + +Animation::Animation(const String &name, Vector &timelines, float duration) : _timelines(timelines), + _timelineIds(), + _duration(duration), + _name(name) { + assert(_name.length() > 0); + for (size_t i = 0; i < timelines.size(); i++) { + Vector propertyIds = timelines[i]->getPropertyIds(); + for (size_t ii = 0; ii < propertyIds.size(); ii++) + _timelineIds.put(propertyIds[ii], true); + } +} + +bool Animation::hasTimeline(Vector ids) { + for (size_t i = 0; i < ids.size(); i++) { + if (_timelineIds.containsKey(ids[i])) return true; + } + return false; +} + +Animation::~Animation() { + ContainerUtil::cleanUpVectorOfPointers(_timelines); +} + +void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + if (loop && _duration != 0) { + time = MathUtil::fmod(time, _duration); + if (lastTime > 0) { + lastTime = MathUtil::fmod(lastTime, _duration); + } + } + + for (size_t i = 0, n = _timelines.size(); i < n; ++i) { + _timelines[i]->apply(skeleton, lastTime, time, pEvents, alpha, blend, direction); + } +} + +const String &Animation::getName() { + return _name; +} + +Vector &Animation::getTimelines() { + return _timelines; +} + +float Animation::getDuration() { + return _duration; +} + +void Animation::setDuration(float inValue) { + _duration = inValue; +} + +int Animation::search(Vector &frames, float target) { + size_t n = (int) frames.size(); + for (size_t i = 1; i < n; i++) { + if (frames[i] > target) return i - 1; + } + return n - 1; +} + +int Animation::search(Vector &frames, float target, int step) { + size_t n = frames.size(); + for (size_t i = step; i < n; i += step) + if (frames[i] > target) return i - step; + return n - step; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AnimationState.cpp new file mode 100644 index 0000000..ab12494 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -0,0 +1,1053 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +void dummyOnAnimationEventFunc(AnimationState *state, spine::EventType type, TrackEntry *entry, Event *event = NULL) { + SP_UNUSED(state); + SP_UNUSED(type); + SP_UNUSED(entry); + SP_UNUSED(event); +} + +TrackEntry::TrackEntry() : _animation(NULL), _previous(NULL), _next(NULL), _mixingFrom(NULL), _mixingTo(0), + _trackIndex(0), _loop(false), _holdPrevious(false), _reverse(false), + _eventThreshold(0), _attachmentThreshold(0), _drawOrderThreshold(0), _animationStart(0), + _animationEnd(0), _animationLast(0), _nextAnimationLast(0), _delay(0), _trackTime(0), + _trackLast(0), _nextTrackLast(0), _trackEnd(0), _timeScale(1.0f), _alpha(0), _mixTime(0), + _mixDuration(0), _interruptAlpha(0), _totalAlpha(0), _mixBlend(MixBlend_Replace), + _listener(dummyOnAnimationEventFunc), _listenerObject(NULL) { +} + +TrackEntry::~TrackEntry() {} + +int TrackEntry::getTrackIndex() { return _trackIndex; } + +Animation *TrackEntry::getAnimation() { return _animation; } + +TrackEntry *TrackEntry::getPrevious() { return _previous; } + +bool TrackEntry::getLoop() { return _loop; } + +void TrackEntry::setLoop(bool inValue) { _loop = inValue; } + +bool TrackEntry::getHoldPrevious() { return _holdPrevious; } + +void TrackEntry::setHoldPrevious(bool inValue) { _holdPrevious = inValue; } + +bool TrackEntry::getReverse() { return _reverse; } + +void TrackEntry::setReverse(bool inValue) { _reverse = inValue; } + +float TrackEntry::getDelay() { return _delay; } + +void TrackEntry::setDelay(float inValue) { _delay = inValue; } + +float TrackEntry::getTrackTime() { return _trackTime; } + +void TrackEntry::setTrackTime(float inValue) { _trackTime = inValue; } + +float TrackEntry::getTrackEnd() { return _trackEnd; } + +void TrackEntry::setTrackEnd(float inValue) { _trackEnd = inValue; } + +float TrackEntry::getAnimationStart() { return _animationStart; } + +void TrackEntry::setAnimationStart(float inValue) { _animationStart = inValue; } + +float TrackEntry::getAnimationEnd() { return _animationEnd; } + +void TrackEntry::setAnimationEnd(float inValue) { _animationEnd = inValue; } + +float TrackEntry::getAnimationLast() { return _animationLast; } + +void TrackEntry::setAnimationLast(float inValue) { + _animationLast = inValue; + _nextAnimationLast = inValue; +} + +float TrackEntry::getAnimationTime() { + if (_loop) { + float duration = _animationEnd - _animationStart; + if (duration == 0) return _animationStart; + return MathUtil::fmod(_trackTime, duration) + _animationStart; + } + + return MathUtil::min(_trackTime + _animationStart, _animationEnd); +} + +float TrackEntry::getTimeScale() { return _timeScale; } + +void TrackEntry::setTimeScale(float inValue) { _timeScale = inValue; } + +float TrackEntry::getAlpha() { return _alpha; } + +void TrackEntry::setAlpha(float inValue) { _alpha = inValue; } + +float TrackEntry::getEventThreshold() { return _eventThreshold; } + +void TrackEntry::setEventThreshold(float inValue) { _eventThreshold = inValue; } + +float TrackEntry::getAttachmentThreshold() { return _attachmentThreshold; } + +void TrackEntry::setAttachmentThreshold(float inValue) { _attachmentThreshold = inValue; } + +float TrackEntry::getDrawOrderThreshold() { return _drawOrderThreshold; } + +void TrackEntry::setDrawOrderThreshold(float inValue) { _drawOrderThreshold = inValue; } + +TrackEntry *TrackEntry::getNext() { return _next; } + +bool TrackEntry::isComplete() { + return _trackTime >= _animationEnd - _animationStart; +} + +float TrackEntry::getMixTime() { return _mixTime; } + +void TrackEntry::setMixTime(float inValue) { _mixTime = inValue; } + +float TrackEntry::getMixDuration() { return _mixDuration; } + +void TrackEntry::setMixDuration(float inValue) { _mixDuration = inValue; } + +TrackEntry *TrackEntry::getMixingFrom() { return _mixingFrom; } + +TrackEntry *TrackEntry::getMixingTo() { return _mixingTo; } + +void TrackEntry::setMixBlend(MixBlend blend) { _mixBlend = blend; } + +MixBlend TrackEntry::getMixBlend() { return _mixBlend; } + +void TrackEntry::resetRotationDirections() { + _timelinesRotation.clear(); +} + +void TrackEntry::setListener(AnimationStateListener inValue) { + _listener = inValue; + _listenerObject = NULL; +} + +void TrackEntry::setListener(AnimationStateListenerObject *inValue) { + _listener = dummyOnAnimationEventFunc; + _listenerObject = inValue; +} + +void TrackEntry::reset() { + _animation = NULL; + _previous = NULL; + _next = NULL; + _mixingFrom = NULL; + _mixingTo = NULL; + + setRendererObject(NULL); + + _timelineMode.clear(); + _timelineHoldMix.clear(); + _timelinesRotation.clear(); + + _listener = dummyOnAnimationEventFunc; + _listenerObject = NULL; +} + +float TrackEntry::getTrackComplete() { + float duration = _animationEnd - _animationStart; + if (duration != 0) { + if (_loop) return duration * (1 + (int) (_trackTime / duration));// Completion of next loop. + if (_trackTime < duration) return duration; // Before duration. + } + return _trackTime;// Next update. +} + +EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry *trackEntry, Event *event) : _type(eventType), + _entry(trackEntry), + _event(event) { +} + +EventQueue *EventQueue::newEventQueue(AnimationState &state, Pool &trackEntryPool) { + return new (__FILE__, __LINE__) EventQueue(state, trackEntryPool); +} + +EventQueueEntry EventQueue::newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event) { + return EventQueueEntry(eventType, entry, event); +} + +EventQueue::EventQueue(AnimationState &state, Pool &trackEntryPool) : _state(state), + _trackEntryPool(trackEntryPool), + _drainDisabled(false) { +} + +EventQueue::~EventQueue() { +} + +void EventQueue::start(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Start, entry)); + _state._animationsChanged = true; +} + +void EventQueue::interrupt(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Interrupt, entry)); +} + +void EventQueue::end(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_End, entry)); + _state._animationsChanged = true; +} + +void EventQueue::dispose(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Dispose, entry)); +} + +void EventQueue::complete(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Complete, entry)); +} + +void EventQueue::event(TrackEntry *entry, Event *event) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Event, entry, event)); +} + +/// Raises all events in the queue and drains the queue. +void EventQueue::drain() { + if (_drainDisabled) { + return; + } + + _drainDisabled = true; + + AnimationState &state = _state; + + // Don't cache _eventQueueEntries.size() so callbacks can queue their own events (eg, call setAnimation in AnimationState_Complete). + for (size_t i = 0; i < _eventQueueEntries.size(); ++i) { + EventQueueEntry queueEntry = _eventQueueEntries[i]; + TrackEntry *trackEntry = queueEntry._entry; + + switch (queueEntry._type) { + case EventType_Start: + case EventType_Interrupt: + case EventType_Complete: + if (!trackEntry->_listenerObject) trackEntry->_listener(&state, queueEntry._type, trackEntry, NULL); + else + trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + if (!state._listenerObject) state._listener(&state, queueEntry._type, trackEntry, NULL); + else + state._listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + break; + case EventType_End: + if (!trackEntry->_listenerObject) trackEntry->_listener(&state, queueEntry._type, trackEntry, NULL); + else + trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + if (!state._listenerObject) state._listener(&state, queueEntry._type, trackEntry, NULL); + else + state._listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + /* Fall through. */ + case EventType_Dispose: + if (!trackEntry->_listenerObject) trackEntry->_listener(&state, EventType_Dispose, trackEntry, NULL); + else + trackEntry->_listenerObject->callback(&state, EventType_Dispose, trackEntry, NULL); + if (!state._listenerObject) state._listener(&state, EventType_Dispose, trackEntry, NULL); + else + state._listenerObject->callback(&state, EventType_Dispose, trackEntry, NULL); + + trackEntry->reset(); + _trackEntryPool.free(trackEntry); + break; + case EventType_Event: + if (!trackEntry->_listenerObject) + trackEntry->_listener(&state, queueEntry._type, trackEntry, queueEntry._event); + else + trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, queueEntry._event); + if (!state._listenerObject) state._listener(&state, queueEntry._type, trackEntry, queueEntry._event); + else + state._listenerObject->callback(&state, queueEntry._type, trackEntry, queueEntry._event); + break; + } + } + _eventQueueEntries.clear(); + + _drainDisabled = false; +} + +AnimationState::AnimationState(AnimationStateData *data) : _data(data), + _queue(EventQueue::newEventQueue(*this, _trackEntryPool)), + _animationsChanged(false), + _listener(dummyOnAnimationEventFunc), + _listenerObject(NULL), + _unkeyedState(0), + _timeScale(1) { +} + +AnimationState::~AnimationState() { + for (size_t i = 0; i < _tracks.size(); i++) { + TrackEntry *entry = _tracks[i]; + if (entry) { + TrackEntry *from = entry->_mixingFrom; + while (from) { + TrackEntry *curr = from; + from = curr->_mixingFrom; + delete curr; + } + TrackEntry *next = entry->_next; + while (next) { + TrackEntry *curr = next; + next = curr->_next; + delete curr; + } + delete entry; + } + } + delete _queue; +} + +void AnimationState::update(float delta) { + delta *= _timeScale; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *currentP = _tracks[i]; + if (currentP == NULL) { + continue; + } + + TrackEntry ¤t = *currentP; + + current._animationLast = current._nextAnimationLast; + current._trackLast = current._nextTrackLast; + + float currentDelta = delta * current._timeScale; + + if (current._delay > 0) { + current._delay -= currentDelta; + if (current._delay > 0) { + continue; + } + currentDelta = -current._delay; + current._delay = 0; + } + + TrackEntry *next = current._next; + if (next != NULL) { + // When the next entry's delay is passed, change to the next entry, preserving leftover time. + float nextTime = current._trackLast - next->_delay; + if (nextTime >= 0) { + next->_delay = 0; + next->_trackTime += + current._timeScale == 0 ? 0 : (nextTime / current._timeScale + delta) * next->_timeScale; + current._trackTime += currentDelta; + setCurrent(i, next, true); + while (next->_mixingFrom != NULL) { + next->_mixTime += delta; + next = next->_mixingFrom; + } + continue; + } + } else if (current._trackLast >= current._trackEnd && current._mixingFrom == NULL) { + // clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. + _tracks[i] = NULL; + + _queue->end(currentP); + clearNext(currentP); + continue; + } + + if (current._mixingFrom != NULL && updateMixingFrom(currentP, delta)) { + // End mixing from entries once all have completed. + TrackEntry *from = current._mixingFrom; + current._mixingFrom = NULL; + if (from != NULL) from->_mixingTo = NULL; + while (from != NULL) { + _queue->end(from); + from = from->_mixingFrom; + } + } + + current._trackTime += currentDelta; + } + + _queue->drain(); +} + +bool AnimationState::apply(Skeleton &skeleton) { + if (_animationsChanged) { + animationsChanged(); + } + + bool applied = false; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *currentP = _tracks[i]; + if (currentP == NULL || currentP->_delay > 0) { + continue; + } + + TrackEntry ¤t = *currentP; + + applied = true; + MixBlend blend = i == 0 ? MixBlend_First : current._mixBlend; + + // apply mixing from entries first. + float mix = current._alpha; + if (current._mixingFrom != NULL) { + mix *= applyMixingFrom(currentP, skeleton, blend); + } else if (current._trackTime >= current._trackEnd && current._next == NULL) { + mix = 0;// Set to setup pose the last time the entry will be applied. + } + + // apply current entry. + float animationLast = current._animationLast, animationTime = current.getAnimationTime(); + float applyTime = animationTime; + Vector *applyEvents = &_events; + if (current._reverse) { + applyTime = current._animation->getDuration() - applyTime; + applyEvents = NULL; + } + size_t timelineCount = current._animation->_timelines.size(); + Vector &timelines = current._animation->_timelines; + if ((i == 0 && mix == 1) || blend == MixBlend_Add) { + for (size_t ii = 0; ii < timelineCount; ++ii) { + Timeline *timeline = timelines[ii]; + if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) + applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, blend, + true); + else + timeline->apply(skeleton, animationLast, applyTime, applyEvents, mix, blend, MixDirection_In); + } + } else { + Vector &timelineMode = current._timelineMode; + + bool firstFrame = current._timelinesRotation.size() != timelines.size() << 1; + if (firstFrame) current._timelinesRotation.setSize(timelines.size() << 1, 0); + Vector &timelinesRotation = current._timelinesRotation; + + for (size_t ii = 0; ii < timelineCount; ++ii) { + Timeline *timeline = timelines[ii]; + assert(timeline); + + MixBlend timelineBlend = timelineMode[ii] == Subsequent ? blend : MixBlend_Setup; + + if (timeline->getRTTI().isExactly(RotateTimeline::rtti)) + applyRotateTimeline(static_cast(timeline), skeleton, applyTime, mix, + timelineBlend, timelinesRotation, ii << 1, firstFrame); + else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) + applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, + timelineBlend, true); + else + timeline->apply(skeleton, animationLast, applyTime, applyEvents, mix, timelineBlend, + MixDirection_In); + } + } + + queueEvents(currentP, animationTime); + _events.clear(); + current._nextAnimationLast = animationTime; + current._nextTrackLast = current._trackTime; + } + + int setupState = _unkeyedState + Setup; + Vector &slots = skeleton.getSlots(); + for (int i = 0, n = slots.size(); i < n; i++) { + Slot *slot = slots[i]; + if (slot->getAttachmentState() == setupState) { + const String &attachmentName = slot->getData().getAttachmentName(); + slot->setAttachment(attachmentName.isEmpty() ? NULL : skeleton.getAttachment(slot->getData().getIndex(), attachmentName)); + } + } + _unkeyedState += 2; + + _queue->drain(); + return applied; +} + +void AnimationState::clearTracks() { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) + clearTrack(i); + _tracks.clear(); + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); +} + +void AnimationState::clearTrack(size_t trackIndex) { + if (trackIndex >= _tracks.size()) return; + + TrackEntry *current = _tracks[trackIndex]; + if (current == NULL) return; + + _queue->end(current); + + clearNext(current); + + TrackEntry *entry = current; + while (true) { + TrackEntry *from = entry->_mixingFrom; + if (from == NULL) break; + + _queue->end(from); + entry->_mixingFrom = NULL; + entry->_mixingTo = NULL; + entry = from; + } + + _tracks[current->_trackIndex] = NULL; + + _queue->drain(); +} + +TrackEntry *AnimationState::setAnimation(size_t trackIndex, const String &animationName, bool loop) { + Animation *animation = _data->_skeletonData->findAnimation(animationName); + assert(animation != NULL); + return setAnimation(trackIndex, animation, loop); +} + +TrackEntry *AnimationState::setAnimation(size_t trackIndex, Animation *animation, bool loop) { + assert(animation != NULL); + + bool interrupt = true; + TrackEntry *current = expandToIndex(trackIndex); + if (current != NULL) { + if (current->_nextTrackLast == -1) { + // Don't mix from an entry that was never applied. + _tracks[trackIndex] = current->_mixingFrom; + _queue->interrupt(current); + _queue->end(current); + clearNext(current); + current = current->_mixingFrom; + interrupt = false; + } else { + clearNext(current); + } + } + + TrackEntry *entry = newTrackEntry(trackIndex, animation, loop, current); + setCurrent(trackIndex, entry, interrupt); + _queue->drain(); + + return entry; +} + +TrackEntry *AnimationState::addAnimation(size_t trackIndex, const String &animationName, bool loop, float delay) { + Animation *animation = _data->_skeletonData->findAnimation(animationName); + assert(animation != NULL); + return addAnimation(trackIndex, animation, loop, delay); +} + +TrackEntry *AnimationState::addAnimation(size_t trackIndex, Animation *animation, bool loop, float delay) { + assert(animation != NULL); + + TrackEntry *last = expandToIndex(trackIndex); + if (last != NULL) { + while (last->_next != NULL) + last = last->_next; + } + + TrackEntry *entry = newTrackEntry(trackIndex, animation, loop, last); + + if (last == NULL) { + setCurrent(trackIndex, entry, true); + _queue->drain(); + } else { + last->_next = entry; + entry->_previous = last; + if (delay <= 0) delay += last->getTrackComplete() - entry->_mixDuration; + } + + entry->_delay = delay; + return entry; +} + +TrackEntry *AnimationState::setEmptyAnimation(size_t trackIndex, float mixDuration) { + TrackEntry *entry = setAnimation(trackIndex, AnimationState::getEmptyAnimation(), false); + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; +} + +TrackEntry *AnimationState::addEmptyAnimation(size_t trackIndex, float mixDuration, float delay) { + TrackEntry *entry = addAnimation(trackIndex, AnimationState::getEmptyAnimation(), false, delay); + if (delay <= 0) entry->_delay += entry->_mixDuration - mixDuration; + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; +} + +void AnimationState::setEmptyAnimations(float mixDuration) { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *current = _tracks[i]; + if (current != NULL) { + setEmptyAnimation(i, mixDuration); + } + } + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); +} + +TrackEntry *AnimationState::getCurrent(size_t trackIndex) { + return trackIndex >= _tracks.size() ? NULL : _tracks[trackIndex]; +} + +AnimationStateData *AnimationState::getData() { + return _data; +} + +Vector &AnimationState::getTracks() { + return _tracks; +} + +float AnimationState::getTimeScale() { + return _timeScale; +} + +void AnimationState::setTimeScale(float inValue) { + _timeScale = inValue; +} + +void AnimationState::setListener(AnimationStateListener inValue) { + _listener = inValue; + _listenerObject = NULL; +} + +void AnimationState::setListener(AnimationStateListenerObject *inValue) { + _listener = dummyOnAnimationEventFunc; + _listenerObject = inValue; +} + +void AnimationState::disableQueue() { + _queue->_drainDisabled = true; +} + +void AnimationState::enableQueue() { + _queue->_drainDisabled = false; +} + +Animation *AnimationState::getEmptyAnimation() { + static Vector timelines; + static Animation ret(String(""), timelines, 0); + return &ret; +} + +void AnimationState::applyAttachmentTimeline(AttachmentTimeline *attachmentTimeline, Skeleton &skeleton, float time, + MixBlend blend, bool attachments) { + Slot *slot = skeleton.getSlots()[attachmentTimeline->getSlotIndex()]; + if (!slot->getBone().isActive()) return; + + Vector &frames = attachmentTimeline->getFrames(); + if (time < frames[0]) { + if (blend == MixBlend_Setup || blend == MixBlend_First) + setAttachment(skeleton, *slot, slot->getData().getAttachmentName(), attachments); + } else { + setAttachment(skeleton, *slot, attachmentTimeline->getAttachmentNames()[Animation::search(frames, time)], + attachments); + } + + /* If an attachment wasn't set (ie before the first frame or attachments is false), set the setup attachment later.*/ + if (slot->getAttachmentState() <= _unkeyedState) slot->setAttachmentState(_unkeyedState + Setup); +} + + +void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, + MixBlend blend, Vector &timelinesRotation, size_t i, bool firstFrame) { + if (firstFrame) timelinesRotation[i] = 0; + + if (alpha == 1) { + rotateTimeline->apply(skeleton, 0, time, NULL, 1, blend, MixDirection_In); + return; + } + + Bone *bone = skeleton._bones[rotateTimeline->_boneIndex]; + if (!bone->isActive()) return; + Vector &frames = rotateTimeline->_frames; + float r1, r2; + if (time < frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_rotation = bone->_data._rotation; + default: + return; + case MixBlend_First: + r1 = bone->_rotation; + r2 = bone->_data._rotation; + } + } else { + r1 = blend == MixBlend_Setup ? bone->_data._rotation : bone->_rotation; + r2 = bone->_data._rotation + rotateTimeline->getCurveValue(time); + } + + // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. + float total, diff = r2 - r1; + diff -= (16384 - (int) (16384.499999999996 - diff / 360)) * 360; + if (diff == 0) { + total = timelinesRotation[i]; + } else { + float lastTotal, lastDiff; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } else { + lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops. + lastDiff = timelinesRotation[i + 1];// Difference between bones. + } + + bool current = diff > 0, dir = lastTotal >= 0; + // Detect cross at 0 (not 180). + if (MathUtil::sign(lastDiff) != MathUtil::sign(diff) && MathUtil::abs(lastDiff) <= 90) { + // A cross after a 360 rotation is a loop. + if (MathUtil::abs(lastTotal) > 180) lastTotal += 360 * MathUtil::sign(lastTotal); + dir = current; + } + + total = diff + lastTotal - MathUtil::fmod(lastTotal, 360);// Store loops as part of lastTotal. + if (dir != current) { + total += 360 * MathUtil::sign(lastTotal); + } + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + bone->_rotation = r1 + total * alpha; +} + +bool AnimationState::updateMixingFrom(TrackEntry *to, float delta) { + TrackEntry *from = to->_mixingFrom; + if (from == NULL) { + return true; + } + + bool finished = updateMixingFrom(from, delta); + + from->_animationLast = from->_nextAnimationLast; + from->_trackLast = from->_nextTrackLast; + + // Require mixTime > 0 to ensure the mixing from entry was applied at least once. + if (to->_mixTime > 0 && to->_mixTime >= to->_mixDuration) { + // Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). + if (from->_totalAlpha == 0 || to->_mixDuration == 0) { + to->_mixingFrom = from->_mixingFrom; + if (from->_mixingFrom != NULL) from->_mixingFrom->_mixingTo = to; + to->_interruptAlpha = from->_interruptAlpha; + _queue->end(from); + } + return finished; + } + + from->_trackTime += delta * from->_timeScale; + to->_mixTime += delta; + + return false; +} + +float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBlend blend) { + TrackEntry *from = to->_mixingFrom; + if (from->_mixingFrom != NULL) applyMixingFrom(from, skeleton, blend); + + float mix; + if (to->_mixDuration == 0) { + // Single frame mix to undo mixingFrom changes. + mix = 1; + if (blend == MixBlend_First) blend = MixBlend_Setup; + } else { + mix = to->_mixTime / to->_mixDuration; + if (mix > 1) { + mix = 1; + } + if (blend != MixBlend_First) blend = from->_mixBlend; + } + + bool attachments = mix < from->_attachmentThreshold, drawOrder = mix < from->_drawOrderThreshold; + Vector &timelines = from->_animation->_timelines; + size_t timelineCount = timelines.size(); + float alphaHold = from->_alpha * to->_interruptAlpha, alphaMix = alphaHold * (1 - mix); + float animationLast = from->_animationLast, animationTime = from->getAnimationTime(); + float applyTime = animationTime; + Vector *events = NULL; + if (from->_reverse) { + applyTime = from->_animation->_duration - applyTime; + } else { + if (mix < from->_eventThreshold) events = &_events; + } + + if (blend == MixBlend_Add) { + for (size_t i = 0; i < timelineCount; i++) + timelines[i]->apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection_Out); + } else { + Vector &timelineMode = from->_timelineMode; + Vector &timelineHoldMix = from->_timelineHoldMix; + + bool firstFrame = from->_timelinesRotation.size() != timelines.size() << 1; + if (firstFrame) from->_timelinesRotation.setSize(timelines.size() << 1, 0); + + Vector &timelinesRotation = from->_timelinesRotation; + + from->_totalAlpha = 0; + for (size_t i = 0; i < timelineCount; i++) { + Timeline *timeline = timelines[i]; + MixDirection direction = MixDirection_Out; + MixBlend timelineBlend; + float alpha; + switch (timelineMode[i]) { + case Subsequent: + if (!drawOrder && (timeline->getRTTI().isExactly(DrawOrderTimeline::rtti))) continue; + timelineBlend = blend; + alpha = alphaMix; + break; + case First: + timelineBlend = MixBlend_Setup; + alpha = alphaMix; + break; + case HoldSubsequent: + timelineBlend = blend; + alpha = alphaHold; + break; + case HoldFirst: + timelineBlend = MixBlend_Setup; + alpha = alphaHold; + break; + default: + timelineBlend = MixBlend_Setup; + TrackEntry *holdMix = timelineHoldMix[i]; + alpha = alphaHold * MathUtil::max(0.0f, 1.0f - holdMix->_mixTime / holdMix->_mixDuration); + break; + } + from->_totalAlpha += alpha; + if ((timeline->getRTTI().isExactly(RotateTimeline::rtti))) { + applyRotateTimeline((RotateTimeline *) timeline, skeleton, applyTime, alpha, timelineBlend, + timelinesRotation, i << 1, firstFrame); + } else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) { + applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, timelineBlend, + attachments); + } else { + if (drawOrder && timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) && + timelineBlend == MixBlend_Setup) + direction = MixDirection_In; + timeline->apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction); + } + } + } + + if (to->_mixDuration > 0) { + queueEvents(from, animationTime); + } + + _events.clear(); + from->_nextAnimationLast = animationTime; + from->_nextTrackLast = from->_trackTime; + + return mix; +} + +void AnimationState::setAttachment(Skeleton &skeleton, Slot &slot, const String &attachmentName, bool attachments) { + slot.setAttachment( + attachmentName.isEmpty() ? NULL : skeleton.getAttachment(slot.getData().getIndex(), attachmentName)); + if (attachments) slot.setAttachmentState(_unkeyedState + Current); +} + +void AnimationState::queueEvents(TrackEntry *entry, float animationTime) { + float animationStart = entry->_animationStart, animationEnd = entry->_animationEnd; + float duration = animationEnd - animationStart; + float trackLastWrapped = MathUtil::fmod(entry->_trackLast, duration); + + // Queue events before complete. + size_t i = 0, n = _events.size(); + for (; i < n; ++i) { + Event *e = _events[i]; + if (e->_time < trackLastWrapped) break; + if (e->_time > animationEnd) continue;// Discard events outside animation start/end. + _queue->event(entry, e); + } + + // Queue complete if completed a loop iteration or the animation. + bool complete = false; + if (entry->_loop) + complete = duration == 0 || (trackLastWrapped > MathUtil::fmod(entry->_trackTime, duration)); + else + complete = animationTime >= animationEnd && entry->_animationLast < animationEnd; + if (complete) _queue->complete(entry); + + // Queue events after complete. + for (; i < n; ++i) { + Event *e = _events[i]; + if (e->_time < animationStart) continue;// Discard events outside animation start/end. + _queue->event(entry, e); + } +} + +void AnimationState::setCurrent(size_t index, TrackEntry *current, bool interrupt) { + TrackEntry *from = expandToIndex(index); + _tracks[index] = current; + current->_previous = NULL; + + if (from != NULL) { + if (interrupt) _queue->interrupt(from); + + current->_mixingFrom = from; + from->_mixingTo = current; + current->_mixTime = 0; + + // Store interrupted mix percentage. + if (from->_mixingFrom != NULL && from->_mixDuration > 0) { + current->_interruptAlpha *= MathUtil::min(1.0f, from->_mixTime / from->_mixDuration); + } + + from->_timelinesRotation.clear();// Reset rotation for mixing out, in case entry was mixed in. + } + + _queue->start(current);// triggers animationsChanged +} + +TrackEntry *AnimationState::expandToIndex(size_t index) { + if (index < _tracks.size()) return _tracks[index]; + while (index >= _tracks.size()) + _tracks.add(NULL); + return NULL; +} + +TrackEntry *AnimationState::newTrackEntry(size_t trackIndex, Animation *animation, bool loop, TrackEntry *last) { + TrackEntry *entryP = _trackEntryPool.obtain();// Pooling + TrackEntry &entry = *entryP; + + entry._trackIndex = trackIndex; + entry._animation = animation; + entry._loop = loop; + entry._holdPrevious = 0; + + entry._eventThreshold = 0; + entry._attachmentThreshold = 0; + entry._drawOrderThreshold = 0; + + entry._animationStart = 0; + entry._animationEnd = animation->getDuration(); + entry._animationLast = -1; + entry._nextAnimationLast = -1; + + entry._delay = 0; + entry._trackTime = 0; + entry._trackLast = -1; + entry._nextTrackLast = -1;// nextTrackLast == -1 signifies a TrackEntry that wasn't applied yet. + entry._trackEnd = FLT_MAX;// loop ? float.MaxValue : animation.Duration; + entry._timeScale = 1; + + entry._alpha = 1; + entry._interruptAlpha = 1; + entry._mixTime = 0; + entry._mixDuration = (last == NULL) ? 0 : _data->getMix(last->_animation, animation); + entry._mixBlend = MixBlend_Replace; + + return entryP; +} + +void AnimationState::clearNext(TrackEntry *entry) { + TrackEntry *next = entry->_next; + while (next != NULL) { + _queue->dispose(next); + next = next->_next; + } + entry->_next = NULL; +} + +void AnimationState::animationsChanged() { + _animationsChanged = false; + + _propertyIDs.clear(); + + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *entry = _tracks[i]; + if (!entry) continue; + + while (entry->_mixingFrom != NULL) + entry = entry->_mixingFrom; + + do { + if (entry->_mixingTo == NULL || entry->_mixBlend != MixBlend_Add) computeHold(entry); + entry = entry->_mixingTo; + } while (entry != NULL); + } +} + +void AnimationState::computeHold(TrackEntry *entry) { + TrackEntry *to = entry->_mixingTo; + Vector &timelines = entry->_animation->_timelines; + size_t timelinesCount = timelines.size(); + Vector &timelineMode = entry->_timelineMode; + timelineMode.setSize(timelinesCount, 0); + Vector &timelineHoldMix = entry->_timelineHoldMix; + timelineHoldMix.setSize(timelinesCount, 0); + + if (to != NULL && to->_holdPrevious) { + for (size_t i = 0; i < timelinesCount; i++) { + timelineMode[i] = _propertyIDs.addAll(timelines[i]->getPropertyIds(), true) ? HoldFirst : HoldSubsequent; + } + return; + } + + // outer: + size_t i = 0; +continue_outer: + for (; i < timelinesCount; ++i) { + Timeline *timeline = timelines[i]; + Vector &ids = timeline->getPropertyIds(); + if (!_propertyIDs.addAll(ids, true)) { + timelineMode[i] = Subsequent; + } else { + if (to == NULL || timeline->getRTTI().isExactly(AttachmentTimeline::rtti) || + timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) || + timeline->getRTTI().isExactly(EventTimeline::rtti) || !to->_animation->hasTimeline(ids)) { + timelineMode[i] = First; + } else { + for (TrackEntry *next = to->_mixingTo; next != NULL; next = next->_mixingTo) { + if (next->_animation->hasTimeline(ids)) continue; + if (next->_mixDuration > 0) { + timelineMode[i] = HoldMix; + timelineHoldMix[i] = next; + i++; + goto continue_outer;// continue outer; + } + break; + } + timelineMode[i] = HoldFirst; + } + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp new file mode 100644 index 0000000..b6e0447 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp @@ -0,0 +1,85 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include + +using namespace spine; + +AnimationStateData::AnimationStateData(SkeletonData *skeletonData) : _skeletonData(skeletonData), _defaultMix(0) { +} + +void AnimationStateData::setMix(const String &fromName, const String &toName, float duration) { + Animation *from = _skeletonData->findAnimation(fromName); + Animation *to = _skeletonData->findAnimation(toName); + + setMix(from, to, duration); +} + +void AnimationStateData::setMix(Animation *from, Animation *to, float duration) { + assert(from != NULL); + assert(to != NULL); + + AnimationPair key(from, to); + _animationToMixTime.put(key, duration); +} + +float AnimationStateData::getMix(Animation *from, Animation *to) { + assert(from != NULL); + assert(to != NULL); + + AnimationPair key(from, to); + + if (_animationToMixTime.containsKey(key)) return _animationToMixTime[key]; + return _defaultMix; +} + +SkeletonData *AnimationStateData::getSkeletonData() { + return _skeletonData; +} + +float AnimationStateData::getDefaultMix() { + return _defaultMix; +} + +void AnimationStateData::setDefaultMix(float inValue) { + _defaultMix = inValue; +} + +AnimationStateData::AnimationPair::AnimationPair(Animation *a1, Animation *a2) : _a1(a1), _a2(a2) { +} + +bool AnimationStateData::AnimationPair::operator==(const AnimationPair &other) const { + return _a1->_name == other._a1->_name && _a2->_name == other._a2->_name; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Atlas.cpp new file mode 100644 index 0000000..19a7ced --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -0,0 +1,356 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include + +#include + +using namespace spine; + +Atlas::Atlas(const String &path, TextureLoader *textureLoader, bool createTexture) : _textureLoader(textureLoader) { + int dirLength; + char *dir; + int length; + const char *data; + + /* Get directory from atlas path. */ + const char *lastForwardSlash = strrchr(path.buffer(), '/'); + const char *lastBackwardSlash = strrchr(path.buffer(), '\\'); + const char *lastSlash = lastForwardSlash > lastBackwardSlash ? lastForwardSlash : lastBackwardSlash; + if (lastSlash == path) lastSlash++; /* Never drop starting slash. */ + dirLength = (int) (lastSlash ? lastSlash - path.buffer() : 0); + dir = SpineExtension::calloc(dirLength + 1, __FILE__, __LINE__); + memcpy(dir, path.buffer(), dirLength); + dir[dirLength] = '\0'; + + data = SpineExtension::readFile(path, &length); + if (data) { + load(data, length, dir, createTexture); + } + + SpineExtension::free(data, __FILE__, __LINE__); + SpineExtension::free(dir, __FILE__, __LINE__); +} + +Atlas::Atlas(const char *data, int length, const char *dir, TextureLoader *textureLoader, bool createTexture) + : _textureLoader( + textureLoader) { + load(data, length, dir, createTexture); +} + +Atlas::~Atlas() { + if (_textureLoader) { + for (size_t i = 0, n = _pages.size(); i < n; ++i) { + _textureLoader->unload(_pages[i]->getRendererObject()); + } + } + ContainerUtil::cleanUpVectorOfPointers(_pages); + ContainerUtil::cleanUpVectorOfPointers(_regions); +} + +void Atlas::flipV() { + for (size_t i = 0, n = _regions.size(); i < n; ++i) { + AtlasRegion *regionP = _regions[i]; + AtlasRegion ®ion = *regionP; + region.v = 1 - region.v; + region.v2 = 1 - region.v2; + } +} + +AtlasRegion *Atlas::findRegion(const String &name) { + for (size_t i = 0, n = _regions.size(); i < n; ++i) + if (_regions[i]->name == name) return _regions[i]; + return NULL; +} + +Vector &Atlas::getPages() { + return _pages; +} + +Vector &Atlas::getRegions() { + return _regions; +} + +struct SimpleString { + char *start; + char *end; + int length; + + SimpleString trim() { + while (isspace((unsigned char) *start) && start < end) + start++; + if (start == end) { + length = end - start; + return *this; + } + end--; + while (((unsigned char) *end == '\r') && end >= start) + end--; + end++; + length = end - start; + return *this; + } + + int indexOf(char needle) { + char *c = start; + while (c < end) { + if (*c == needle) return c - start; + c++; + } + return -1; + } + + int indexOf(char needle, int at) { + char *c = start + at; + while (c < end) { + if (*c == needle) return c - start; + c++; + } + return -1; + } + + SimpleString substr(int s, int e) { + e = s + e; + SimpleString result; + result.start = start + s; + result.end = start + e; + result.length = e - s; + return result; + } + + SimpleString substr(int s) { + SimpleString result; + result.start = start + s; + result.end = end; + result.length = result.end - result.start; + return result; + } + + bool equals(const char *str) { + int otherLen = strlen(str); + if (length != otherLen) return false; + for (int i = 0; i < length; i++) { + if (start[i] != str[i]) return false; + } + return true; + } + + char *copy() { + char *string = SpineExtension::calloc(length + 1, __FILE__, __LINE__); + memcpy(string, start, length); + string[length] = '\0'; + return string; + } + + int toInt() { + return (int) strtol(start, &end, 10); + } +}; + +struct AtlasInput { + const char *start; + const char *end; + char *index; + int length; + SimpleString line; + + AtlasInput(const char *data, int length) : start(data), end(data + length), index((char *) data), length(length) {} + + SimpleString *readLine() { + if (index >= end) return 0; + line.start = index; + while (index < end && *index != '\n') + index++; + line.end = index; + if (index != end) index++; + line = line.trim(); + line.length = end - start; + return &line; + } + + static int readEntry(SimpleString entry[5], SimpleString *line) { + if (line == NULL) return 0; + line->trim(); + if (line->length == 0) return 0; + + int colon = line->indexOf(':'); + if (colon == -1) return 0; + entry[0] = line->substr(0, colon).trim(); + for (int i = 1, lastMatch = colon + 1;; i++) { + int comma = line->indexOf(',', lastMatch); + if (comma == -1) { + entry[i] = line->substr(lastMatch).trim(); + return i; + } + entry[i] = line->substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + if (i == 4) return 4; + } + } +}; + +int indexOf(const char **array, int count, SimpleString *str) { + for (int i = 0; i < count; i++) + if (str->equals(array[i])) return i; + return 0; +} + +void Atlas::load(const char *begin, int length, const char *dir, bool createTexture) { + static const char *formatNames[] = {"", "Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888", + "RGBA8888"}; + static const char *textureFilterNames[] = {"", "Nearest", "Linear", "MipMap", "MipMapNearestNearest", + "MipMapLinearNearest", + "MipMapNearestLinear", "MipMapLinearLinear"}; + + int dirLength = (int) strlen(dir); + int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\'; + AtlasInput reader(begin, length); + SimpleString entry[5]; + AtlasPage *page = NULL; + + SimpleString *line = reader.readLine(); + while (line != NULL && line->length == 0) + line = reader.readLine(); + + while (true) { + if (line == NULL || line->length == 0) break; + if (reader.readEntry(entry, line) == 0) break; + line = reader.readLine(); + } + + while (true) { + if (line == NULL) break; + if (line->trim().length == 0) { + page = NULL; + line = reader.readLine(); + } else if (page == NULL) { + char *name = line->copy(); + char *path = SpineExtension::calloc(dirLength + needsSlash + strlen(name) + 1, __FILE__, __LINE__); + memcpy(path, dir, dirLength); + if (needsSlash) path[dirLength] = '/'; + strcpy(path + dirLength + needsSlash, name); + page = new (__FILE__, __LINE__) AtlasPage(String(name, true)); + + while (true) { + line = reader.readLine(); + if (reader.readEntry(entry, line) == 0) break; + if (entry[0].equals("size")) { + page->width = entry[1].toInt(); + page->height = entry[2].toInt(); + } else if (entry[0].equals("format")) { + page->format = (Format) indexOf(formatNames, 8, &entry[1]); + } else if (entry[0].equals("filter")) { + page->minFilter = (TextureFilter) indexOf(textureFilterNames, 8, &entry[1]); + page->magFilter = (TextureFilter) indexOf(textureFilterNames, 8, &entry[2]); + } else if (entry[0].equals("repeat")) { + page->uWrap = TextureWrap_ClampToEdge; + page->vWrap = TextureWrap_ClampToEdge; + if (entry[1].indexOf('x') != -1) page->uWrap = TextureWrap_Repeat; + if (entry[1].indexOf('y') != -1) page->vWrap = TextureWrap_Repeat; + } else if (entry[0].equals("pma")) { + page->pma = entry[1].equals("true"); + } + } + + if (createTexture) { + if (_textureLoader) _textureLoader->load(*page, String(path)); + SpineExtension::free(path, __FILE__, __LINE__); + } else { + page->texturePath = String(path, true); + } + _pages.add(page); + } else { + AtlasRegion *region = new (__FILE__, __LINE__) AtlasRegion(); + region->page = page; + region->name = String(line->copy(), true); + while (true) { + line = reader.readLine(); + int count = reader.readEntry(entry, line); + if (count == 0) break; + if (entry[0].equals("xy")) { + region->x = entry[1].toInt(); + region->y = entry[2].toInt(); + } else if (entry[0].equals("size")) { + region->width = entry[1].toInt(); + region->height = entry[2].toInt(); + } else if (entry[0].equals("bounds")) { + region->x = entry[1].toInt(); + region->y = entry[2].toInt(); + region->width = entry[3].toInt(); + region->height = entry[4].toInt(); + } else if (entry[0].equals("offset")) { + region->offsetX = entry[1].toInt(); + region->offsetY = entry[2].toInt(); + } else if (entry[0].equals("orig")) { + region->originalWidth = entry[1].toInt(); + region->originalHeight = entry[2].toInt(); + } else if (entry[0].equals("offsets")) { + region->offsetX = entry[1].toInt(); + region->offsetY = entry[2].toInt(); + region->originalWidth = entry[3].toInt(); + region->originalHeight = entry[4].toInt(); + } else if (entry[0].equals("rotate")) { + if (entry[1].equals("true")) { + region->degrees = 90; + } else if (!entry[1].equals("false")) { + region->degrees = entry[1].toInt(); + } + } else if (entry[0].equals("index")) { + region->index = entry[1].toInt(); + } else { + region->names.add(String(entry[0].copy())); + for (int i = 0; i < count; i++) { + region->values.add(entry[i + 1].toInt()); + } + } + } + if (region->originalWidth == 0 && region->originalHeight == 0) { + region->originalWidth = region->width; + region->originalHeight = region->height; + } + + region->u = (float) region->x / page->width; + region->v = (float) region->y / page->height; + if (region->degrees == 90) { + region->u2 = (float) (region->x + region->height) / page->width; + region->v2 = (float) (region->y + region->width) / page->height; + } else { + region->u2 = (float) (region->x + region->width) / page->width; + region->v2 = (float) (region->y + region->height) / page->height; + } + _regions.add(region); + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp new file mode 100644 index 0000000..473d379 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp @@ -0,0 +1,128 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace spine { + RTTI_IMPL(AtlasAttachmentLoader, AttachmentLoader) + + AtlasAttachmentLoader::AtlasAttachmentLoader(Atlas *atlas) : AttachmentLoader(), _atlas(atlas) { + } + + RegionAttachment *AtlasAttachmentLoader::newRegionAttachment(Skin &skin, const String &name, const String &path) { + SP_UNUSED(skin); + + AtlasRegion *regionP = findRegion(path); + if (!regionP) return NULL; + + AtlasRegion ®ion = *regionP; + + RegionAttachment *attachmentP = new (__FILE__, __LINE__) RegionAttachment(name); + + RegionAttachment &attachment = *attachmentP; + attachment.setRendererObject(regionP); + attachment.setUVs(region.u, region.v, region.u2, region.v2, region.degrees); + attachment._regionOffsetX = region.offsetX; + attachment._regionOffsetY = region.offsetY; + attachment._regionWidth = (float) region.width; + attachment._regionHeight = (float) region.height; + attachment._regionOriginalWidth = (float) region.originalWidth; + attachment._regionOriginalHeight = (float) region.originalHeight; + return attachmentP; + } + + MeshAttachment *AtlasAttachmentLoader::newMeshAttachment(Skin &skin, const String &name, const String &path) { + SP_UNUSED(skin); + + AtlasRegion *regionP = findRegion(path); + if (!regionP) return NULL; + + AtlasRegion ®ion = *regionP; + + MeshAttachment *attachmentP = new (__FILE__, __LINE__) MeshAttachment(name); + + MeshAttachment &attachment = *attachmentP; + attachment.setRendererObject(regionP); + attachment._regionU = region.u; + attachment._regionV = region.v; + attachment._regionU2 = region.u2; + attachment._regionV2 = region.v2; + attachment._regionDegrees = region.degrees; + attachment._regionOffsetX = region.offsetX; + attachment._regionOffsetY = region.offsetY; + attachment._regionWidth = (float) region.width; + attachment._regionHeight = (float) region.height; + attachment._regionOriginalWidth = (float) region.originalWidth; + attachment._regionOriginalHeight = (float) region.originalHeight; + + return attachmentP; + } + + BoundingBoxAttachment *AtlasAttachmentLoader::newBoundingBoxAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new (__FILE__, __LINE__) BoundingBoxAttachment(name); + } + + PathAttachment *AtlasAttachmentLoader::newPathAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new (__FILE__, __LINE__) PathAttachment(name); + } + + PointAttachment *AtlasAttachmentLoader::newPointAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new (__FILE__, __LINE__) PointAttachment(name); + } + + ClippingAttachment *AtlasAttachmentLoader::newClippingAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new (__FILE__, __LINE__) ClippingAttachment(name); + } + + void AtlasAttachmentLoader::configureAttachment(Attachment *attachment) { + SP_UNUSED(attachment); + } + + AtlasRegion *AtlasAttachmentLoader::findRegion(const String &name) { + return _atlas->findRegion(name); + } + +}// namespace spine diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Attachment.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Attachment.cpp new file mode 100644 index 0000000..fd83f2f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Attachment.cpp @@ -0,0 +1,63 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(Attachment) + +Attachment::Attachment(const String &name) : _name(name), _refCount(0) { + assert(_name.length() > 0); +} + +Attachment::~Attachment() { +} + +const String &Attachment::getName() const { + return _name; +} + +int Attachment::getRefCount() { + return _refCount; +} + +void Attachment::reference() { + _refCount++; +} + +void Attachment::dereference() { + _refCount--; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp new file mode 100644 index 0000000..856ef8c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp @@ -0,0 +1,52 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(AttachmentLoader) + +AttachmentLoader::AttachmentLoader() { +} + +AttachmentLoader::~AttachmentLoader() { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp new file mode 100644 index 0000000..dae0546 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -0,0 +1,104 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(AttachmentTimeline, Timeline) + +AttachmentTimeline::AttachmentTimeline(size_t frameCount, int slotIndex) : Timeline(frameCount, 1), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Attachment << 32) | slotIndex}; + setPropertyIds(ids, 1); + + _attachmentNames.ensureCapacity(frameCount); + for (size_t i = 0; i < frameCount; ++i) { + _attachmentNames.add(String()); + } +} + +AttachmentTimeline::~AttachmentTimeline() {} + +void AttachmentTimeline::setAttachment(Skeleton &skeleton, Slot &slot, String *attachmentName) { + slot.setAttachment(attachmentName == NULL || attachmentName->isEmpty() ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName)); +} + +void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(alpha); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (direction == MixDirection_Out) { + if (blend == MixBlend_Setup) setAttachment(skeleton, *slot, &slot->_data._attachmentName); + return; + } + + if (time < _frames[0]) { + // Time is before first frame. + if (blend == MixBlend_Setup || blend == MixBlend_First) { + setAttachment(skeleton, *slot, &slot->_data._attachmentName); + } + return; + } + + if (time < _frames[0]) { + if (blend == MixBlend_Setup || blend == MixBlend_First) + setAttachment(skeleton, *slot, &slot->_data._attachmentName); + return; + } + + setAttachment(skeleton, *slot, &_attachmentNames[Animation::search(_frames, time)]); +} + +void AttachmentTimeline::setFrame(int frame, float time, const String &attachmentName) { + _frames[frame] = time; + _attachmentNames[frame] = attachmentName; +} + +Vector &AttachmentTimeline::getAttachmentNames() { + return _attachmentNames; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Bone.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Bone.cpp new file mode 100644 index 0000000..c886d0a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -0,0 +1,539 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL(Bone, Updatable) + +bool Bone::yDown = false; + +void Bone::setYDown(bool inValue) { + yDown = inValue; +} + +bool Bone::isYDown() { + return yDown; +} + +Bone::Bone(BoneData &data, Skeleton &skeleton, Bone *parent) : Updatable(), + _data(data), + _skeleton(skeleton), + _parent(parent), + _x(0), + _y(0), + _rotation(0), + _scaleX(0), + _scaleY(0), + _shearX(0), + _shearY(0), + _ax(0), + _ay(0), + _arotation(0), + _ascaleX(0), + _ascaleY(0), + _ashearX(0), + _ashearY(0), + _a(1), + _b(0), + _worldX(0), + _c(0), + _d(1), + _worldY(0), + _sorted(false), + _active(false) { + setToSetupPose(); +} + +void Bone::update() { + updateWorldTransform(_ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY); +} + +void Bone::updateWorldTransform() { + updateWorldTransform(_x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY); +} + +void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { + float cosine, sine; + float pa, pb, pc, pd; + Bone *parent = _parent; + + _ax = x; + _ay = y; + _arotation = rotation; + _ascaleX = scaleX; + _ascaleY = scaleY; + _ashearX = shearX; + _ashearY = shearY; + + if (!parent) { /* Root bone. */ + float rotationY = rotation + 90 + shearY; + float sx = _skeleton.getScaleX(); + float sy = _skeleton.getScaleY(); + _a = MathUtil::cosDeg(rotation + shearX) * scaleX * sx; + _b = MathUtil::cosDeg(rotationY) * scaleY * sx; + _c = MathUtil::sinDeg(rotation + shearX) * scaleX * sy; + _d = MathUtil::sinDeg(rotationY) * scaleY * sy; + _worldX = x * sx + _skeleton.getX(); + _worldY = y * sy + _skeleton.getY(); + return; + } + + pa = parent->_a; + pb = parent->_b; + pc = parent->_c; + pd = parent->_d; + + _worldX = pa * x + pb * y + parent->_worldX; + _worldY = pc * x + pd * y + parent->_worldY; + + switch (_data.getTransformMode()) { + case TransformMode_Normal: { + float rotationY = rotation + 90 + shearY; + float la = MathUtil::cosDeg(rotation + shearX) * scaleX; + float lb = MathUtil::cosDeg(rotationY) * scaleY; + float lc = MathUtil::sinDeg(rotation + shearX) * scaleX; + float ld = MathUtil::sinDeg(rotationY) * scaleY; + _a = pa * la + pb * lc; + _b = pa * lb + pb * ld; + _c = pc * la + pd * lc; + _d = pc * lb + pd * ld; + return; + } + case TransformMode_OnlyTranslation: { + float rotationY = rotation + 90 + shearY; + _a = MathUtil::cosDeg(rotation + shearX) * scaleX; + _b = MathUtil::cosDeg(rotationY) * scaleY; + _c = MathUtil::sinDeg(rotation + shearX) * scaleX; + _d = MathUtil::sinDeg(rotationY) * scaleY; + break; + } + case TransformMode_NoRotationOrReflection: { + float s = pa * pa + pc * pc; + float prx, rx, ry, la, lb, lc, ld; + if (s > 0.0001f) { + s = MathUtil::abs(pa * pd - pb * pc) / s; + pa /= _skeleton.getScaleX(); + pc /= _skeleton.getScaleY(); + pb = pc * s; + pd = pa * s; + prx = MathUtil::atan2(pc, pa) * MathUtil::Rad_Deg; + } else { + pa = 0; + pc = 0; + prx = 90 - MathUtil::atan2(pd, pb) * MathUtil::Rad_Deg; + } + rx = rotation + shearX - prx; + ry = rotation + shearY - prx + 90; + la = MathUtil::cosDeg(rx) * scaleX; + lb = MathUtil::cosDeg(ry) * scaleY; + lc = MathUtil::sinDeg(rx) * scaleX; + ld = MathUtil::sinDeg(ry) * scaleY; + _a = pa * la - pb * lc; + _b = pa * lb - pb * ld; + _c = pc * la + pd * lc; + _d = pc * lb + pd * ld; + break; + } + case TransformMode_NoScale: + case TransformMode_NoScaleOrReflection: { + float za, zc, s; + float r, zb, zd, la, lb, lc, ld; + cosine = MathUtil::cosDeg(rotation); + sine = MathUtil::sinDeg(rotation); + za = (pa * cosine + pb * sine) / _skeleton.getScaleX(); + zc = (pc * cosine + pd * sine) / _skeleton.getScaleY(); + s = MathUtil::sqrt(za * za + zc * zc); + if (s > 0.00001f) s = 1 / s; + za *= s; + zc *= s; + s = MathUtil::sqrt(za * za + zc * zc); + if (_data.getTransformMode() == TransformMode_NoScale && + (pa * pd - pb * pc < 0) != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0)) + s = -s; + r = MathUtil::Pi / 2 + MathUtil::atan2(zc, za); + zb = MathUtil::cos(r) * s; + zd = MathUtil::sin(r) * s; + la = MathUtil::cosDeg(shearX) * scaleX; + lb = MathUtil::cosDeg(90 + shearY) * scaleY; + lc = MathUtil::sinDeg(shearX) * scaleX; + ld = MathUtil::sinDeg(90 + shearY) * scaleY; + _a = za * la + zb * lc; + _b = za * lb + zb * ld; + _c = zc * la + zd * lc; + _d = zc * lb + zd * ld; + break; + } + } + _a *= _skeleton.getScaleX(); + _b *= _skeleton.getScaleX(); + _c *= _skeleton.getScaleY(); + _d *= _skeleton.getScaleY(); +} + +void Bone::setToSetupPose() { + BoneData &data = _data; + _x = data.getX(); + _y = data.getY(); + _rotation = data.getRotation(); + _scaleX = data.getScaleX(); + _scaleY = data.getScaleY(); + _shearX = data.getShearX(); + _shearY = data.getShearY(); +} + +void Bone::worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY) { + float a = _a; + float b = _b; + float c = _c; + float d = _d; + + float invDet = 1 / (a * d - b * c); + float x = worldX - _worldX; + float y = worldY - _worldY; + + outLocalX = (x * d * invDet - y * b * invDet); + outLocalY = (y * a * invDet - x * c * invDet); +} + +void Bone::localToWorld(float localX, float localY, float &outWorldX, float &outWorldY) { + outWorldX = localX * _a + localY * _b + _worldX; + outWorldY = localX * _c + localY * _d + _worldY; +} + +float Bone::worldToLocalRotation(float worldRotation) { + float sin = MathUtil::sinDeg(worldRotation); + float cos = MathUtil::cosDeg(worldRotation); + + return MathUtil::atan2(_a * sin - _c * cos, _d * cos - _b * sin) * MathUtil::Rad_Deg + this->_rotation - + this->_shearX; +} + +float Bone::localToWorldRotation(float localRotation) { + localRotation -= this->_rotation - this->_shearX; + float sin = MathUtil::sinDeg(localRotation); + float cos = MathUtil::cosDeg(localRotation); + + return MathUtil::atan2(cos * _c + sin * _d, cos * _a + sin * _b) * MathUtil::Rad_Deg; +} + +void Bone::rotateWorld(float degrees) { + float a = _a; + float b = _b; + float c = _c; + float d = _d; + + float cos = MathUtil::cosDeg(degrees); + float sin = MathUtil::sinDeg(degrees); + + _a = cos * a - sin * c; + _b = cos * b - sin * d; + _c = sin * a + cos * c; + _d = sin * b + cos * d; +} + +float Bone::getWorldToLocalRotationX() { + Bone *parent = _parent; + if (!parent) { + return _arotation; + } + + float pa = parent->_a; + float pb = parent->_b; + float pc = parent->_c; + float pd = parent->_d; + float a = _a; + float c = _c; + + return MathUtil::atan2(pa * c - pc * a, pd * a - pb * c) * MathUtil::Rad_Deg; +} + +float Bone::getWorldToLocalRotationY() { + Bone *parent = _parent; + if (!parent) { + return _arotation; + } + + float pa = parent->_a; + float pb = parent->_b; + float pc = parent->_c; + float pd = parent->_d; + float b = _b; + float d = _d; + + return MathUtil::atan2(pa * d - pc * b, pd * b - pb * d) * MathUtil::Rad_Deg; +} + +BoneData &Bone::getData() { + return _data; +} + +Skeleton &Bone::getSkeleton() { + return _skeleton; +} + +Bone *Bone::getParent() { + return _parent; +} + +Vector &Bone::getChildren() { + return _children; +} + +float Bone::getX() { + return _x; +} + +void Bone::setX(float inValue) { + _x = inValue; +} + +float Bone::getY() { + return _y; +} + +void Bone::setY(float inValue) { + _y = inValue; +} + +float Bone::getRotation() { + return _rotation; +} + +void Bone::setRotation(float inValue) { + _rotation = inValue; +} + +float Bone::getScaleX() { + return _scaleX; +} + +void Bone::setScaleX(float inValue) { + _scaleX = inValue; +} + +float Bone::getScaleY() { + return _scaleY; +} + +void Bone::setScaleY(float inValue) { + _scaleY = inValue; +} + +float Bone::getShearX() { + return _shearX; +} + +void Bone::setShearX(float inValue) { + _shearX = inValue; +} + +float Bone::getShearY() { + return _shearY; +} + +void Bone::setShearY(float inValue) { + _shearY = inValue; +} + +float Bone::getAppliedRotation() { + return _arotation; +} + +void Bone::setAppliedRotation(float inValue) { + _arotation = inValue; +} + +float Bone::getAX() { + return _ax; +} + +void Bone::setAX(float inValue) { + _ax = inValue; +} + +float Bone::getAY() { + return _ay; +} + +void Bone::setAY(float inValue) { + _ay = inValue; +} + +float Bone::getAScaleX() { + return _ascaleX; +} + +void Bone::setAScaleX(float inValue) { + _ascaleX = inValue; +} + +float Bone::getAScaleY() { + return _ascaleY; +} + +void Bone::setAScaleY(float inValue) { + _ascaleY = inValue; +} + +float Bone::getAShearX() { + return _ashearX; +} + +void Bone::setAShearX(float inValue) { + _ashearX = inValue; +} + +float Bone::getAShearY() { + return _ashearY; +} + +void Bone::setAShearY(float inValue) { + _ashearY = inValue; +} + +float Bone::getA() { + return _a; +} + +void Bone::setA(float inValue) { + _a = inValue; +} + +float Bone::getB() { + return _b; +} + +void Bone::setB(float inValue) { + _b = inValue; +} + +float Bone::getC() { + return _c; +} + +void Bone::setC(float inValue) { + _c = inValue; +} + +float Bone::getD() { + return _d; +} + +void Bone::setD(float inValue) { + _d = inValue; +} + +float Bone::getWorldX() { + return _worldX; +} + +void Bone::setWorldX(float inValue) { + _worldX = inValue; +} + +float Bone::getWorldY() { + return _worldY; +} + +void Bone::setWorldY(float inValue) { + _worldY = inValue; +} + +float Bone::getWorldRotationX() { + return MathUtil::atan2(_c, _a) * MathUtil::Rad_Deg; +} + +float Bone::getWorldRotationY() { + return MathUtil::atan2(_d, _b) * MathUtil::Rad_Deg; +} + +float Bone::getWorldScaleX() { + return MathUtil::sqrt(_a * _a + _c * _c); +} + +float Bone::getWorldScaleY() { + return MathUtil::sqrt(_b * _b + _d * _d); +} + +void Bone::updateAppliedTransform() { + Bone *parent = _parent; + if (!parent) { + _ax = _worldX - _skeleton.getX(); + _ay = _worldY - _skeleton.getY(); + _arotation = MathUtil::atan2(_c, _a) * MathUtil::Rad_Deg; + _ascaleX = MathUtil::sqrt(_a * _a + _c * _c); + _ascaleY = MathUtil::sqrt(_b * _b + _d * _d); + _ashearX = 0; + _ashearY = MathUtil::atan2(_a * _b + _c * _d, _a * _d - _b * _c) * MathUtil::Rad_Deg; + } else { + float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d; + float pid = 1 / (pa * pd - pb * pc); + float dx = _worldX - parent->_worldX, dy = _worldY - parent->_worldY; + float ia = pid * pd; + float id = pid * pa; + float ib = pid * pb; + float ic = pid * pc; + float ra = ia * _a - ib * _c; + float rb = ia * _b - ib * _d; + float rc = id * _c - ic * _a; + float rd = id * _d - ic * _b; + _ax = (dx * pd * pid - dy * pb * pid); + _ay = (dy * pa * pid - dx * pc * pid); + _ashearX = 0; + _ascaleX = MathUtil::sqrt(ra * ra + rc * rc); + if (_ascaleX > 0.0001f) { + float det = ra * rd - rb * rc; + _ascaleY = det / _ascaleX; + _ashearY = MathUtil::atan2(ra * rb + rc * rd, det) * MathUtil::Rad_Deg; + _arotation = MathUtil::atan2(rc, ra) * MathUtil::Rad_Deg; + } else { + _ascaleX = 0; + _ascaleY = MathUtil::sqrt(rb * rb + rd * rd); + _ashearY = 0; + _arotation = 90 - MathUtil::atan2(rd, rb) * MathUtil::Rad_Deg; + } + } +} + +bool Bone::isActive() { + return _active; +} + +void Bone::setActive(bool inValue) { + _active = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/BoneData.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/BoneData.cpp new file mode 100644 index 0000000..560461a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/BoneData.cpp @@ -0,0 +1,152 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +BoneData::BoneData(int index, const String &name, BoneData *parent) : _index(index), + _name(name), + _parent(parent), + _length(0), + _x(0), + _y(0), + _rotation(0), + _scaleX(1), + _scaleY(1), + _shearX(0), + _shearY(0), + _transformMode(TransformMode_Normal), + _skinRequired(false), + _color() { + assert(index >= 0); + assert(_name.length() > 0); +} + +int BoneData::getIndex() { + return _index; +} + +const String &BoneData::getName() { + return _name; +} + +BoneData *BoneData::getParent() { + return _parent; +} + +float BoneData::getLength() { + return _length; +} + +void BoneData::setLength(float inValue) { + _length = inValue; +} + +float BoneData::getX() { + return _x; +} + +void BoneData::setX(float inValue) { + _x = inValue; +} + +float BoneData::getY() { + return _y; +} + +void BoneData::setY(float inValue) { + _y = inValue; +} + +float BoneData::getRotation() { + return _rotation; +} + +void BoneData::setRotation(float inValue) { + _rotation = inValue; +} + +float BoneData::getScaleX() { + return _scaleX; +} + +void BoneData::setScaleX(float inValue) { + _scaleX = inValue; +} + +float BoneData::getScaleY() { + return _scaleY; +} + +void BoneData::setScaleY(float inValue) { + _scaleY = inValue; +} + +float BoneData::getShearX() { + return _shearX; +} + +void BoneData::setShearX(float inValue) { + _shearX = inValue; +} + +float BoneData::getShearY() { + return _shearY; +} + +void BoneData::setShearY(float inValue) { + _shearY = inValue; +} + +TransformMode BoneData::getTransformMode() { + return _transformMode; +} + +void BoneData::setTransformMode(TransformMode inValue) { + _transformMode = inValue; +} + +bool BoneData::isSkinRequired() { + return _skinRequired; +} + +void BoneData::setSkinRequired(bool inValue) { + _skinRequired = inValue; +} + +Color &BoneData::getColor() { + return _color; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp new file mode 100644 index 0000000..dfdb561 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +using namespace spine; + +RTTI_IMPL(BoundingBoxAttachment, VertexAttachment) + +BoundingBoxAttachment::BoundingBoxAttachment(const String &name) : VertexAttachment(name), _color() { +} + +Color &BoundingBoxAttachment::getColor() { + return _color; +} + +Attachment *BoundingBoxAttachment::copy() { + BoundingBoxAttachment *copy = new (__FILE__, __LINE__) BoundingBoxAttachment(getName()); + copyTo(copy); + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp new file mode 100644 index 0000000..5f10ec0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp @@ -0,0 +1,62 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +RTTI_IMPL(ClippingAttachment, VertexAttachment) + +ClippingAttachment::ClippingAttachment(const String &name) : VertexAttachment(name), _endSlot(NULL), _color() { +} + +SlotData *ClippingAttachment::getEndSlot() { + return _endSlot; +} + +void ClippingAttachment::setEndSlot(SlotData *inValue) { + _endSlot = inValue; +} + +Color &ClippingAttachment::getColor() { + return _color; +} + +Attachment *ClippingAttachment::copy() { + ClippingAttachment *copy = new (__FILE__, __LINE__) ClippingAttachment(getName()); + copyTo(copy); + copy->_endSlot = _endSlot; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp new file mode 100644 index 0000000..bfb9f8a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -0,0 +1,497 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(RGBATimeline, CurveTimeline) + +RGBATimeline::RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount, + RGBATimeline::ENTRIES, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, + ((PropertyId) Property_Alpha << 32) | slotIndex}; + setPropertyIds(ids, 2); +} + +RGBATimeline::~RGBATimeline() { +} + +void RGBATimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) { + Color &color = slot->_color, &setup = slot->_data._color; + switch (blend) { + case MixBlend_Setup: + color.set(setup); + return; + case MixBlend_First: + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, + (setup.a - color.a) * alpha); + default: { + } + } + return; + } + + float r = 0, g = 0, b = 0, a = 0; + int i = Animation::search(_frames, time, RGBATimeline::ENTRIES); + int curveType = (int) _curves[i / RGBATimeline::ENTRIES]; + switch (curveType) { + case RGBATimeline::LINEAR: { + float before = _frames[i]; + r = _frames[i + RGBATimeline::R]; + g = _frames[i + RGBATimeline::G]; + b = _frames[i + RGBATimeline::B]; + a = _frames[i + RGBATimeline::A]; + float t = (time - before) / (_frames[i + RGBATimeline::ENTRIES] - before); + r += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::R] - r) * t; + g += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::G] - g) * t; + b += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::B] - b) * t; + a += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::A] - a) * t; + break; + } + case RGBATimeline::STEPPED: { + r = _frames[i + RGBATimeline::R]; + g = _frames[i + RGBATimeline::G]; + b = _frames[i + RGBATimeline::B]; + a = _frames[i + RGBATimeline::A]; + break; + } + default: { + r = getBezierValue(time, i, RGBATimeline::R, curveType - RGBATimeline::BEZIER); + g = getBezierValue(time, i, RGBATimeline::G, + curveType + RGBATimeline::BEZIER_SIZE - RGBATimeline::BEZIER); + b = getBezierValue(time, i, RGBATimeline::B, + curveType + RGBATimeline::BEZIER_SIZE * 2 - RGBATimeline::BEZIER); + a = getBezierValue(time, i, RGBATimeline::A, + curveType + RGBATimeline::BEZIER_SIZE * 3 - RGBATimeline::BEZIER); + } + } + Color &color = slot->_color; + if (alpha == 1) + color.set(r, g, b, a); + else { + if (blend == MixBlend_Setup) color.set(slot->_data._color); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } +} + +void RGBATimeline::setFrame(int frame, float time, float r, float g, float b, float a) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; + _frames[frame + A] = a; +} + +RTTI_IMPL(RGBTimeline, CurveTimeline) + +RGBTimeline::RGBTimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount, + RGBTimeline::ENTRIES, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex}; + setPropertyIds(ids, 1); +} + +RGBTimeline::~RGBTimeline() { +} + +void RGBTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) { + Color &color = slot->_color, &setup = slot->_data._color; + switch (blend) { + case MixBlend_Setup: + color.set(setup); + return; + case MixBlend_First: + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, + (setup.a - color.a) * alpha); + default: { + } + } + return; + } + + float r = 0, g = 0, b = 0; + int i = Animation::search(_frames, time, RGBTimeline::ENTRIES); + int curveType = (int) _curves[i / RGBTimeline::ENTRIES]; + switch (curveType) { + case RGBTimeline::LINEAR: { + float before = _frames[i]; + r = _frames[i + RGBTimeline::R]; + g = _frames[i + RGBTimeline::G]; + b = _frames[i + RGBTimeline::B]; + float t = (time - before) / (_frames[i + RGBTimeline::ENTRIES] - before); + r += (_frames[i + RGBTimeline::ENTRIES + RGBTimeline::R] - r) * t; + g += (_frames[i + RGBTimeline::ENTRIES + RGBTimeline::G] - g) * t; + b += (_frames[i + RGBTimeline::ENTRIES + RGBTimeline::B] - b) * t; + break; + } + case RGBTimeline::STEPPED: { + r = _frames[i + RGBTimeline::R]; + g = _frames[i + RGBTimeline::G]; + b = _frames[i + RGBTimeline::B]; + break; + } + default: { + r = getBezierValue(time, i, RGBTimeline::R, curveType - RGBTimeline::BEZIER); + g = getBezierValue(time, i, RGBTimeline::G, + curveType + RGBTimeline::BEZIER_SIZE - RGBTimeline::BEZIER); + b = getBezierValue(time, i, RGBTimeline::B, + curveType + RGBTimeline::BEZIER_SIZE * 2 - RGBTimeline::BEZIER); + } + } + Color &color = slot->_color; + if (alpha == 1) + color.set(r, g, b); + else { + Color &setup = slot->_data._color; + if (blend == MixBlend_Setup) color.set(setup.r, setup.g, setup.b); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha); + } +} + +void RGBTimeline::setFrame(int frame, float time, float r, float g, float b) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; +} + +RTTI_IMPL(AlphaTimeline, CurveTimeline1) + +AlphaTimeline::AlphaTimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline1(frameCount, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Alpha << 32) | slotIndex}; + setPropertyIds(ids, 1); +} + +AlphaTimeline::~AlphaTimeline() { +} + +void AlphaTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) {// Time is before first frame. + Color &color = slot->_color, &setup = slot->_data._color; + switch (blend) { + case MixBlend_Setup: + color.a = setup.a; + return; + case MixBlend_First: + color.a += (setup.a - color.a) * alpha; + default: { + } + } + return; + } + + float a = getCurveValue(time); + if (alpha == 1) + slot->_color.a = a; + else { + if (blend == MixBlend_Setup) slot->_color.a = slot->_data._color.a; + slot->_color.a += (a - slot->_color.a) * alpha; + } +} + +RTTI_IMPL(RGBA2Timeline, CurveTimeline) + +RGBA2Timeline::RGBA2Timeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount, + RGBA2Timeline::ENTRIES, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, + ((PropertyId) Property_Alpha << 32) | slotIndex, + ((PropertyId) Property_Rgb2 << 32) | slotIndex}; + setPropertyIds(ids, 3); +} + +RGBA2Timeline::~RGBA2Timeline() { +} + +void RGBA2Timeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) { + Color &light = slot->_color, &dark = slot->_darkColor, &setupLight = slot->_data._color, &setupDark = slot->_data._darkColor; + switch (blend) { + case MixBlend_Setup: + light.set(setupLight); + dark.set(setupDark.r, setupDark.g, setupDark.b); + return; + case MixBlend_First: + light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, + (setupLight.b - light.b) * alpha, + (setupLight.a - light.a) * alpha); + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + default: { + } + } + return; + } + + float r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + int i = Animation::search(_frames, time, RGBA2Timeline::ENTRIES); + int curveType = (int) _curves[i / RGBA2Timeline::ENTRIES]; + switch (curveType) { + case RGBA2Timeline::LINEAR: { + float before = _frames[i]; + r = _frames[i + RGBA2Timeline::R]; + g = _frames[i + RGBA2Timeline::G]; + b = _frames[i + RGBA2Timeline::B]; + a = _frames[i + RGBA2Timeline::A]; + r2 = _frames[i + RGBA2Timeline::R2]; + g2 = _frames[i + RGBA2Timeline::G2]; + b2 = _frames[i + RGBA2Timeline::B2]; + float t = (time - before) / (_frames[i + RGBA2Timeline::ENTRIES] - before); + r += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::R] - r) * t; + g += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::G] - g) * t; + b += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::B] - b) * t; + a += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::A] - a) * t; + r2 += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::R2] - r2) * t; + g2 += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::G2] - g2) * t; + b2 += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::B2] - b2) * t; + break; + } + case RGBA2Timeline::STEPPED: { + r = _frames[i + RGBA2Timeline::R]; + g = _frames[i + RGBA2Timeline::G]; + b = _frames[i + RGBA2Timeline::B]; + a = _frames[i + RGBA2Timeline::A]; + r2 = _frames[i + RGBA2Timeline::R2]; + g2 = _frames[i + RGBA2Timeline::G2]; + b2 = _frames[i + RGBA2Timeline::B2]; + break; + } + default: { + r = getBezierValue(time, i, RGBA2Timeline::R, curveType - RGBA2Timeline::BEZIER); + g = getBezierValue(time, i, RGBA2Timeline::G, + curveType + RGBA2Timeline::BEZIER_SIZE - RGBA2Timeline::BEZIER); + b = getBezierValue(time, i, RGBA2Timeline::B, + curveType + RGBA2Timeline::BEZIER_SIZE * 2 - RGBA2Timeline::BEZIER); + a = getBezierValue(time, i, RGBA2Timeline::A, + curveType + RGBA2Timeline::BEZIER_SIZE * 3 - RGBA2Timeline::BEZIER); + r2 = getBezierValue(time, i, RGBA2Timeline::R2, + curveType + RGBA2Timeline::BEZIER_SIZE * 4 - RGBA2Timeline::BEZIER); + g2 = getBezierValue(time, i, RGBA2Timeline::G2, + curveType + RGBA2Timeline::BEZIER_SIZE * 5 - RGBA2Timeline::BEZIER); + b2 = getBezierValue(time, i, RGBA2Timeline::B2, + curveType + RGBA2Timeline::BEZIER_SIZE * 6 - RGBA2Timeline::BEZIER); + } + } + Color &light = slot->_color, &dark = slot->_darkColor; + if (alpha == 1) { + light.set(r, g, b, a); + dark.set(r2, g2, b2); + } else { + if (blend == MixBlend_Setup) { + light.set(slot->_data._color); + dark.set(slot->_data._darkColor); + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } +} + +void RGBA2Timeline::setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; + _frames[frame + A] = a; + _frames[frame + R2] = r2; + _frames[frame + G2] = g2; + _frames[frame + B2] = b2; +} + +RTTI_IMPL(RGB2Timeline, CurveTimeline) + +RGB2Timeline::RGB2Timeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount, + RGB2Timeline::ENTRIES, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, + ((PropertyId) Property_Rgb2 << 32) | slotIndex}; + setPropertyIds(ids, 2); +} + +RGB2Timeline::~RGB2Timeline() { +} + +void RGB2Timeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) { + Color &light = slot->_color, &dark = slot->_darkColor, &setupLight = slot->_data._color, &setupDark = slot->_data._darkColor; + switch (blend) { + case MixBlend_Setup: + light.set(setupLight.r, setupLight.g, setupLight.b); + dark.set(setupDark.r, setupDark.g, setupDark.b); + return; + case MixBlend_First: + light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, + (setupLight.b - light.b) * alpha); + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + default: { + } + } + return; + } + + float r = 0, g = 0, b = 0, r2 = 0, g2 = 0, b2 = 0; + int i = Animation::search(_frames, time, RGB2Timeline::ENTRIES); + int curveType = (int) _curves[i / RGB2Timeline::ENTRIES]; + switch (curveType) { + case RGB2Timeline::LINEAR: { + float before = _frames[i]; + r = _frames[i + RGB2Timeline::R]; + g = _frames[i + RGB2Timeline::G]; + b = _frames[i + RGB2Timeline::B]; + r2 = _frames[i + RGB2Timeline::R2]; + g2 = _frames[i + RGB2Timeline::G2]; + b2 = _frames[i + RGB2Timeline::B2]; + float t = (time - before) / (_frames[i + RGB2Timeline::ENTRIES] - before); + r += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::R] - r) * t; + g += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::G] - g) * t; + b += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::B] - b) * t; + r2 += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::R2] - r2) * t; + g2 += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::G2] - g2) * t; + b2 += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::B2] - b2) * t; + break; + } + case RGB2Timeline::STEPPED: { + r = _frames[i + RGB2Timeline::R]; + g = _frames[i + RGB2Timeline::G]; + b = _frames[i + RGB2Timeline::B]; + r2 = _frames[i + RGB2Timeline::R2]; + g2 = _frames[i + RGB2Timeline::G2]; + b2 = _frames[i + RGB2Timeline::B2]; + break; + } + default: { + r = getBezierValue(time, i, RGB2Timeline::R, curveType - RGB2Timeline::BEZIER); + g = getBezierValue(time, i, RGB2Timeline::G, + curveType + RGB2Timeline::BEZIER_SIZE - RGB2Timeline::BEZIER); + b = getBezierValue(time, i, RGB2Timeline::B, + curveType + RGB2Timeline::BEZIER_SIZE * 2 - RGB2Timeline::BEZIER); + r2 = getBezierValue(time, i, RGB2Timeline::R2, + curveType + RGB2Timeline::BEZIER_SIZE * 4 - RGB2Timeline::BEZIER); + g2 = getBezierValue(time, i, RGB2Timeline::G2, + curveType + RGB2Timeline::BEZIER_SIZE * 5 - RGB2Timeline::BEZIER); + b2 = getBezierValue(time, i, RGB2Timeline::B2, + curveType + RGB2Timeline::BEZIER_SIZE * 6 - RGB2Timeline::BEZIER); + } + } + Color &light = slot->_color, &dark = slot->_darkColor; + if (alpha == 1) { + light.set(r, g, b); + dark.set(r2, g2, b2); + } else { + if (blend == MixBlend_Setup) { + light.set(slot->_data._color.r, slot->_data._color.g, slot->_data._color.b); + dark.set(slot->_data._darkColor); + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha); + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } +} + +void RGB2Timeline::setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; + _frames[frame + R2] = r2; + _frames[frame + G2] = g2; + _frames[frame + B2] = b2; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp new file mode 100644 index 0000000..aa08894 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp @@ -0,0 +1,62 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +using namespace spine; + +ConstraintData::ConstraintData(const String &name) : _name(name), _order(0), _skinRequired(false) { +} + +ConstraintData::~ConstraintData() { +} + +const String &ConstraintData::getName() { + return _name; +} + +size_t ConstraintData::getOrder() { + return _order; +} + +void ConstraintData::setOrder(size_t inValue) { + _order = inValue; +} + +bool ConstraintData::isSkinRequired() { + return _skinRequired; +} + +void ConstraintData::setSkinRequired(bool inValue) { + _skinRequired = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp new file mode 100644 index 0000000..cbba790 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp @@ -0,0 +1,154 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +RTTI_IMPL(CurveTimeline, Timeline) + +CurveTimeline::CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount) : Timeline(frameCount, + frameEntries) { + _curves.setSize(frameCount + bezierCount * BEZIER_SIZE, 0); + _curves[frameCount - 1] = STEPPED; +} + +CurveTimeline::~CurveTimeline() { +} + +void CurveTimeline::setLinear(size_t frame) { + _curves[frame] = LINEAR; +} + +void CurveTimeline::setStepped(size_t frame) { + _curves[frame] = STEPPED; +} + +void CurveTimeline::setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, + float cx2, float cy2, float time2, float value2) { + size_t i = getFrameCount() + bezier * BEZIER_SIZE; + if (value == 0) _curves[frame] = BEZIER + i; + float tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03; + float dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 0.006; + float ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + float dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667; + float x = time1 + dx, y = value1 + dy; + for (size_t n = i + BEZIER_SIZE; i < n; i += 2) { + _curves[i] = x; + _curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } +} + +float CurveTimeline::getBezierValue(float time, size_t frameIndex, size_t valueOffset, size_t i) { + if (_curves[i] > time) { + float x = _frames[frameIndex], y = _frames[frameIndex + valueOffset]; + return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y); + } + size_t n = i + BEZIER_SIZE; + for (i += 2; i < n; i += 2) { + if (_curves[i] >= time) { + float x = _curves[i - 2], y = _curves[i - 1]; + return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y); + } + } + frameIndex += getFrameEntries(); + float x = _curves[n - 2], y = _curves[n - 1]; + return y + (time - x) / (_frames[frameIndex] - x) * (_frames[frameIndex + valueOffset] - y); +} + +Vector &CurveTimeline::getCurves() { + return _curves; +} + +RTTI_IMPL(CurveTimeline1, CurveTimeline) + +CurveTimeline1::CurveTimeline1(size_t frameCount, size_t bezierCount) : CurveTimeline(frameCount, + CurveTimeline1::ENTRIES, + bezierCount) { +} + +CurveTimeline1::~CurveTimeline1() { +} + +void CurveTimeline1::setFrame(size_t frame, float time, float value) { + frame <<= 1; + _frames[frame] = time; + _frames[frame + CurveTimeline1::VALUE] = value; +} + +float CurveTimeline1::getCurveValue(float time) { + int i = _frames.size() - 2; + for (int ii = 2; ii <= i; ii += 2) { + if (_frames[ii] > time) { + i = ii - 2; + break; + } + } + + int curveType = (int) _curves[i >> 1]; + switch (curveType) { + case CurveTimeline::LINEAR: { + float before = _frames[i], value = _frames[i + CurveTimeline1::VALUE]; + return value + (time - before) / (_frames[i + CurveTimeline1::ENTRIES] - before) * + (_frames[i + CurveTimeline1::ENTRIES + CurveTimeline1::VALUE] - value); + } + case CurveTimeline::STEPPED: + return _frames[i + CurveTimeline1::VALUE]; + } + return getBezierValue(time, i, CurveTimeline1::VALUE, curveType - CurveTimeline1::BEZIER); +} + +RTTI_IMPL(CurveTimeline2, CurveTimeline) + +CurveTimeline2::CurveTimeline2(size_t frameCount, size_t bezierCount) : CurveTimeline(frameCount, + CurveTimeline2::ENTRIES, + bezierCount) { +} + +CurveTimeline2::~CurveTimeline2() { +} + +void CurveTimeline2::setFrame(size_t frame, float time, float value1, float value2) { + frame *= CurveTimeline2::ENTRIES; + _frames[frame] = time; + _frames[frame + CurveTimeline2::VALUE1] = value1; + _frames[frame + CurveTimeline2::VALUE2] = value2; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp new file mode 100644 index 0000000..ba4c430 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -0,0 +1,332 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(DeformTimeline, CurveTimeline) + +DeformTimeline::DeformTimeline(size_t frameCount, size_t bezierCount, int slotIndex, VertexAttachment *attachment) + : CurveTimeline(frameCount, 1, bezierCount), _slotIndex(slotIndex), _attachment(attachment) { + PropertyId ids[] = {((PropertyId) Property_Deform << 32) | ((slotIndex << 16 | attachment->_id) & 0xffffffff)}; + setPropertyIds(ids, 1); + + _vertices.ensureCapacity(frameCount); + for (size_t i = 0; i < frameCount; ++i) { + Vector vec; + _vertices.add(vec); + } +} + +void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slotP = skeleton._slots[_slotIndex]; + Slot &slot = *slotP; + if (!slot._bone.isActive()) return; + + Attachment *slotAttachment = slot.getAttachment(); + if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) { + return; + } + + VertexAttachment *attachment = static_cast(slotAttachment); + if (attachment->_deformAttachment != _attachment) { + return; + } + + Vector &deformArray = slot._deform; + if (deformArray.size() == 0) { + blend = MixBlend_Setup; + } + + Vector> &vertices = _vertices; + size_t vertexCount = vertices[0].size(); + + Vector &frames = _frames; + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + deformArray.clear(); + return; + case MixBlend_First: { + if (alpha == 1) { + deformArray.clear(); + return; + } + deformArray.setSize(vertexCount, 0); + Vector &deform = deformArray; + if (attachment->getBones().size() == 0) { + // Unweighted vertex positions. + Vector &setupVertices = attachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) + deform[i] += (setupVertices[i] - deform[i]) * alpha; + } else { + // Weighted deform offsets. + alpha = 1 - alpha; + for (size_t i = 0; i < vertexCount; i++) + deform[i] *= alpha; + } + } + case MixBlend_Replace: + case MixBlend_Add: { + } + } + return; + } + + deformArray.setSize(vertexCount, 0); + Vector &deform = deformArray; + + if (time >= frames[frames.size() - 1]) {// Time is after last frame. + Vector &lastVertices = vertices[frames.size() - 1]; + if (alpha == 1) { + if (blend == MixBlend_Add) { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, no alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) + deform[i] += lastVertices[i] - setupVertices[i]; + } else { + // Weighted deform offsets, no alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] += lastVertices[i]; + } + } else { + // Vertex positions or deform offsets, no alpha. + memcpy(deform.buffer(), lastVertices.buffer(), vertexCount * sizeof(float)); + } + } else { + switch (blend) { + case MixBlend_Setup: { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, with alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float setup = setupVertices[i]; + deform[i] = setup + (lastVertices[i] - setup) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] = lastVertices[i] * alpha; + } + break; + } + case MixBlend_First: + case MixBlend_Replace: + // Vertex positions or deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] += (lastVertices[i] - deform[i]) * alpha; + break; + case MixBlend_Add: + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, no alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) + deform[i] += (lastVertices[i] - setupVertices[i]) * alpha; + } else { + // Weighted deform offsets, alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] += lastVertices[i] * alpha; + } + } + } + return; + } + + // Interpolate between the previous frame and the current frame. + int frame = Animation::search(frames, time); + float percent = getCurvePercent(time, frame); + Vector &prevVertices = vertices[frame]; + Vector &nextVertices = vertices[frame + 1]; + + if (alpha == 1) { + if (blend == MixBlend_Add) { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, no alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i]; + } + } else { + // Weighted deform offsets, no alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += prev + (nextVertices[i] - prev) * percent; + } + } + } else { + // Vertex positions or deform offsets, no alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] = prev + (nextVertices[i] - prev) * percent; + } + } + } else { + switch (blend) { + case MixBlend_Setup: { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, with alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i], setup = setupVertices[i]; + deform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } + break; + } + case MixBlend_First: + case MixBlend_Replace: + // Vertex positions or deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha; + } + break; + case MixBlend_Add: + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, with alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } + } + } +} + +void DeformTimeline::setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, + float cx2, float cy2, float time2, float value2) { + SP_UNUSED(value1); + SP_UNUSED(value2); + size_t i = getFrameCount() + bezier * DeformTimeline::BEZIER_SIZE; + if (value == 0) _curves[frame] = DeformTimeline::BEZIER + i; + float tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06; + float dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = (cy1 - cy2 + 0.33333333) * 0.018; + float ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + float dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667; + float x = time1 + dx, y = dy; + for (size_t n = i + DeformTimeline::BEZIER_SIZE; i < n; i += 2) { + _curves[i] = x; + _curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } +} + +float DeformTimeline::getCurvePercent(float time, int frame) { + int i = (int) _curves[frame]; + switch (i) { + case DeformTimeline::LINEAR: { + float x = _frames[frame]; + return (time - x) / (_frames[frame + getFrameEntries()] - x); + } + case DeformTimeline::STEPPED: { + return 0; + } + default: { + } + } + i -= DeformTimeline::BEZIER; + if (_curves[i] > time) { + float x = _frames[frame]; + return _curves[i + 1] * (time - x) / (_curves[i] - x); + } + int n = i + DeformTimeline::BEZIER_SIZE; + for (i += 2; i < n; i += 2) { + if (_curves[i] >= time) { + float x = _curves[i - 2], y = _curves[i - 1]; + return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y); + } + } + float x = _curves[n - 2], y = _curves[n - 1]; + return y + (1 - y) * (time - x) / (_frames[frame + getFrameEntries()] - x); +} + +void DeformTimeline::setFrame(int frame, float time, Vector &vertices) { + _frames[frame] = time; + _vertices[frame].clear(); + _vertices[frame].addAll(vertices); +} + +Vector> &DeformTimeline::getVertices() { + return _vertices; +} + +VertexAttachment *DeformTimeline::getAttachment() { + return _attachment; +} + +void DeformTimeline::setAttachment(VertexAttachment *inValue) { + _attachment = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp new file mode 100644 index 0000000..a6f3498 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -0,0 +1,106 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(DrawOrderTimeline, Timeline) + +DrawOrderTimeline::DrawOrderTimeline(size_t frameCount) : Timeline(frameCount, 1) { + PropertyId ids[] = {((PropertyId) Property_DrawOrder << 32)}; + setPropertyIds(ids, 1); + + _drawOrders.ensureCapacity(frameCount); + for (size_t i = 0; i < frameCount; ++i) { + Vector vec; + _drawOrders.add(vec); + } +} + +void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(alpha); + + Vector &drawOrder = skeleton._drawOrder; + Vector &slots = skeleton._slots; + if (direction == MixDirection_Out) { + if (blend == MixBlend_Setup) { + drawOrder.clear(); + drawOrder.ensureCapacity(slots.size()); + for (size_t i = 0, n = slots.size(); i < n; ++i) + drawOrder.add(slots[i]); + } + return; + } + + if (time < _frames[0]) { + if (blend == MixBlend_Setup || blend == MixBlend_First) { + drawOrder.clear(); + drawOrder.ensureCapacity(slots.size()); + for (size_t i = 0, n = slots.size(); i < n; ++i) + drawOrder.add(slots[i]); + } + return; + } + + Vector &drawOrderToSetupIndex = _drawOrders[Animation::search(_frames, time)]; + if (drawOrderToSetupIndex.size() == 0) { + drawOrder.clear(); + for (size_t i = 0, n = slots.size(); i < n; ++i) + drawOrder.add(slots[i]); + } else { + for (size_t i = 0, n = drawOrderToSetupIndex.size(); i < n; ++i) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } +} + +void DrawOrderTimeline::setFrame(size_t frame, float time, Vector &drawOrder) { + _frames[frame] = time; + _drawOrders[frame].clear(); + _drawOrders[frame].addAll(drawOrder); +} + +Vector> &DrawOrderTimeline::getDrawOrders() { + return _drawOrders; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Event.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Event.cpp new file mode 100644 index 0000000..bdadc8f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Event.cpp @@ -0,0 +1,94 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +spine::Event::Event(float time, const spine::EventData &data) : _data(data), + _time(time), + _intValue(0), + _floatValue(0), + _stringValue(), + _volume(1), + _balance(0) { +} + +const spine::EventData &spine::Event::getData() { + return _data; +} + +float spine::Event::getTime() { + return _time; +} + +int spine::Event::getIntValue() { + return _intValue; +} + +void spine::Event::setIntValue(int inValue) { + _intValue = inValue; +} + +float spine::Event::getFloatValue() { + return _floatValue; +} + +void spine::Event::setFloatValue(float inValue) { + _floatValue = inValue; +} + +const spine::String &spine::Event::getStringValue() { + return _stringValue; +} + +void spine::Event::setStringValue(const spine::String &inValue) { + _stringValue = inValue; +} + + +float spine::Event::getVolume() { + return _volume; +} + +void spine::Event::setVolume(float inValue) { + _volume = inValue; +} + +float spine::Event::getBalance() { + return _balance; +} + +void spine::Event::setBalance(float inValue) { + _balance = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/EventData.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/EventData.cpp new file mode 100644 index 0000000..d904af0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/EventData.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +spine::EventData::EventData(const spine::String &name) : _name(name), + _intValue(0), + _floatValue(0), + _stringValue(), + _audioPath(), + _volume(1), + _balance(0) { + assert(_name.length() > 0); +} + +/// The name of the event, which is unique within the skeleton. +const spine::String &spine::EventData::getName() const { + return _name; +} + +int spine::EventData::getIntValue() const { + return _intValue; +} + +void spine::EventData::setIntValue(int inValue) { + _intValue = inValue; +} + +float spine::EventData::getFloatValue() const { + return _floatValue; +} + +void spine::EventData::setFloatValue(float inValue) { + _floatValue = inValue; +} + +const spine::String &spine::EventData::getStringValue() const { + return _stringValue; +} + +void spine::EventData::setStringValue(const spine::String &inValue) { + this->_stringValue = inValue; +} + +const spine::String &spine::EventData::getAudioPath() const { + return _audioPath; +} + +void spine::EventData::setAudioPath(const spine::String &inValue) { + _audioPath = inValue; +} + + +float spine::EventData::getVolume() const { + return _volume; +} + +void spine::EventData::setVolume(float inValue) { + _volume = inValue; +} + +float spine::EventData::getBalance() const { + return _balance; +} + +void spine::EventData::setBalance(float inValue) { + _balance = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp new file mode 100644 index 0000000..40f7463 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -0,0 +1,103 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(EventTimeline, Timeline) + +EventTimeline::EventTimeline(size_t frameCount) : Timeline(frameCount, 1) { + PropertyId ids[] = {((PropertyId) Property_Event << 32)}; + setPropertyIds(ids, 1); + _events.setSize(frameCount, NULL); +} + +EventTimeline::~EventTimeline() { + ContainerUtil::cleanUpVectorOfPointers(_events); +} + +void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + if (pEvents == NULL) return; + + Vector &events = *pEvents; + + size_t frameCount = _frames.size(); + + if (lastTime > time) { + // Fire events after last time for looped animations. + apply(skeleton, lastTime, FLT_MAX, pEvents, alpha, blend, direction); + lastTime = -1.0f; + } else if (lastTime >= _frames[frameCount - 1]) { + // Last time is after last i. + return; + } + + if (time < _frames[0]) return;// Time is before first i. + + int i; + if (lastTime < _frames[0]) { + i = 0; + } else { + i = Animation::search(_frames, lastTime) + 1; + float frameTime = _frames[i]; + while (i > 0) { + // Fire multiple events with the same i. + if (_frames[i - 1] != frameTime) break; + i--; + } + } + + for (; (size_t) i < frameCount && time >= _frames[i]; i++) + events.add(_events[i]); +} + +void EventTimeline::setFrame(size_t frame, Event *event) { + _frames[frame] = event->getTime(); + _events[frame] = event; +} + +Vector &EventTimeline::getEvents() { return _events; } diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Extension.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Extension.cpp new file mode 100644 index 0000000..e19f273 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Extension.cpp @@ -0,0 +1,127 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include + +#include + +using namespace spine; + +SpineExtension *SpineExtension::_instance = NULL; + +void SpineExtension::setInstance(SpineExtension *inValue) { + assert(inValue); + + _instance = inValue; +} + +SpineExtension *SpineExtension::getInstance() { + if (!_instance) _instance = spine::getDefaultExtension(); + assert(_instance); + + return _instance; +} + +SpineExtension::~SpineExtension() { +} + +SpineExtension::SpineExtension() { +} + +DefaultSpineExtension::~DefaultSpineExtension() { +} + +void *DefaultSpineExtension::_alloc(size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + if (size == 0) + return 0; + void *ptr = ::malloc(size); + return ptr; +} + +void *DefaultSpineExtension::_calloc(size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + if (size == 0) + return 0; + + void *ptr = ::malloc(size); + if (ptr) { + memset(ptr, 0, size); + } + return ptr; +} + +void *DefaultSpineExtension::_realloc(void *ptr, size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + void *mem = NULL; + if (size == 0) + return 0; + if (ptr == NULL) + mem = ::malloc(size); + else + mem = ::realloc(ptr, size); + return mem; +} + +void DefaultSpineExtension::_free(void *mem, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + ::free(mem); +} + +char *DefaultSpineExtension::_readFile(const String &path, int *length) { + char *data; + FILE *file = fopen(path.buffer(), "rb"); + if (!file) return 0; + + fseek(file, 0, SEEK_END); + *length = (int) ftell(file); + fseek(file, 0, SEEK_SET); + + data = SpineExtension::alloc(*length, __FILE__, __LINE__); + fread(data, 1, *length, file); + fclose(file); + + return data; +} + +DefaultSpineExtension::DefaultSpineExtension() : SpineExtension() { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp new file mode 100644 index 0000000..cee23c5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -0,0 +1,360 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(IkConstraint, Updatable) + +void IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha) { + Bone *p = bone.getParent(); + float pa = p->_a, pb = p->_b, pc = p->_c, pd = p->_d; + float rotationIK = -bone._ashearX - bone._arotation; + float tx = 0, ty = 0; + + switch (bone._data.getTransformMode()) { + case TransformMode_OnlyTranslation: + tx = targetX - bone._worldX; + ty = targetY - bone._worldY; + break; + case TransformMode_NoRotationOrReflection: { + float s = MathUtil::abs(pa * pd - pb * pc) / (pa * pa + pc * pc); + float sa = pa / bone._skeleton.getScaleX(); + float sc = pc / bone._skeleton.getScaleY(); + pb = -sc * s * bone._skeleton.getScaleX(); + pd = sa * s * bone._skeleton.getScaleY(); + rotationIK += MathUtil::atan2(sc, sa) * MathUtil::Rad_Deg; + } + default: + float x = targetX - p->_worldX, y = targetY - p->_worldY; + float d = pa * pd - pb * pc; + tx = (x * pd - y * pb) / d - bone._ax; + ty = (y * pa - x * pc) / d - bone._ay; + } + rotationIK += MathUtil::atan2(ty, tx) * MathUtil::Rad_Deg; + if (bone._ascaleX < 0) rotationIK += 180; + if (rotationIK > 180) rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + float sx = bone._ascaleX; + float sy = bone._ascaleY; + if (compress || stretch) { + switch (bone._data.getTransformMode()) { + case TransformMode_NoScale: + case TransformMode_NoScaleOrReflection: + tx = targetX - bone._worldX; + ty = targetY - bone._worldY; + default:; + } + float b = bone._data.getLength() * sx, dd = MathUtil::sqrt(tx * tx + ty * ty); + if (((compress && dd < b) || (stretch && dd > b)) && (b > 0.0001f)) { + float s = (dd / b - 1) * alpha + 1; + sx *= s; + if (uniform) sy *= s; + } + } + bone.updateWorldTransform(bone._ax, bone._ay, bone._arotation + rotationIK * alpha, sx, sy, bone._ashearX, + bone._ashearY); +} + +void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, bool uniform, + float softness, + float alpha) { + float a, b, c, d; + float px, py, psx, psy, sx, sy; + float cx, cy, csx, cwx, cwy; + int o1, o2, s2, u; + Bone *pp = parent.getParent(); + float tx, ty, dx, dy, dd, l1, l2, a1, a2, r, td, sd, p; + float id, x, y; + px = parent._ax; + py = parent._ay; + psx = parent._ascaleX; + psy = parent._ascaleY; + sx = psx; + sy = psy; + csx = child._ascaleX; + if (psx < 0) { + psx = -psx; + o1 = 180; + s2 = -1; + } else { + o1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + o2 = 180; + } else + o2 = 0; + r = psx - psy; + cx = child._ax; + u = (r < 0 ? -r : r) <= 0.0001f; + if (!u || stretch) { + cy = 0; + cwx = parent._a * cx + parent._worldX; + cwy = parent._c * cx + parent._worldY; + } else { + cy = child._ay; + cwx = parent._a * cx + parent._b * cy + parent._worldX; + cwy = parent._c * cx + parent._d * cy + parent._worldY; + } + a = pp->_a; + b = pp->_b; + c = pp->_c; + d = pp->_d; + id = 1 / (a * d - b * c); + x = cwx - pp->_worldX; + y = cwy - pp->_worldY; + dx = (x * d - y * b) * id - px; + dy = (y * a - x * c) * id - py; + l1 = MathUtil::sqrt(dx * dx + dy * dy); + l2 = child._data.getLength() * csx; + if (l1 < 0.0001) { + apply(parent, targetX, targetY, false, stretch, false, alpha); + child.updateWorldTransform(cx, cy, 0, child._ascaleX, child._ascaleY, child._ashearX, child._ashearY); + return; + } + x = targetX - pp->_worldX; + y = targetY - pp->_worldY; + tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + dd = tx * tx + ty * ty; + if (softness != 0) { + softness *= psx * (csx + 1) * 0.5f; + td = MathUtil::sqrt(dd), sd = td - l1 - l2 * psx + softness; + if (sd > 0) { + p = MathUtil::min(1.0f, sd / (softness * 2)) - 1; + p = (sd - softness * (1 - p * p)) / td; + tx -= p * tx; + ty -= p * ty; + dd = tx * tx + ty * ty; + } + } + if (u) { + float cosine; + l2 *= psx; + cosine = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cosine < -1) { + cosine = -1; + a2 = MathUtil::Pi * bendDir; + } else if (cosine > 1) { + cosine = 1; + a2 = 0; + if (stretch) { + a = (MathUtil::sqrt(dd) / (l1 + l2) - 1) * alpha + 1; + sx *= a; + if (uniform) sy *= a; + } + } else + a2 = MathUtil::acos(cosine) * bendDir; + a = l1 + l2 * cosine; + b = l2 * MathUtil::sin(a2); + a1 = MathUtil::atan2(ty * a - tx * b, tx * a + ty * b); + } else { + a = psx * l2, b = psy * l2; + float aa = a * a, bb = b * b, ll = l1 * l1, ta = MathUtil::atan2(ty, tx); + float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c0; + if (d >= 0) { + float q = MathUtil::sqrt(d), r0, r1; + if (c1 < 0) q = -q; + q = -(c1 + q) * 0.5f; + r0 = q / c2; + r1 = c0 / q; + r = MathUtil::abs(r0) < MathUtil::abs(r1) ? r0 : r1; + if (r * r <= dd) { + y = MathUtil::sqrt(dd - r * r) * bendDir; + a1 = ta - MathUtil::atan2(y, r); + a2 = MathUtil::atan2(y / psy, (r - l1) / psx); + goto break_outer; + } + } + { + float minAngle = MathUtil::Pi, minX = l1 - a, minDist = minX * minX, minY = 0; + float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c0 = -a * l1 / (aa - bb); + if (c0 >= -1 && c0 <= 1) { + c0 = MathUtil::acos(c0); + x = a * MathUtil::cos(c0) + l1; + y = b * MathUtil::sin(c0); + d = x * x + y * y; + if (d < minDist) { + minAngle = c0; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c0; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) * 0.5f) { + a1 = ta - MathUtil::atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } else { + a1 = ta - MathUtil::atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + } +break_outer : { + float os = MathUtil::atan2(cy, cx) * s2; + a1 = (a1 - os) * MathUtil::Rad_Deg + o1 - parent._arotation; + if (a1 > 180) a1 -= 360; + else if (a1 < -180) + a1 += 360; + parent.updateWorldTransform(px, py, parent._arotation + a1 * alpha, sx, sy, 0, 0); + a2 = ((a2 + os) * MathUtil::Rad_Deg - child._ashearX) * s2 + o2 - child._arotation; + if (a2 > 180) a2 -= 360; + else if (a2 < -180) + a2 += 360; + child.updateWorldTransform(cx, cy, child._arotation + a2 * alpha, child._ascaleX, child._ascaleY, + child._ashearX, child._ashearY); +} +} + +IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Updatable(), + _data(data), + _bendDirection(data.getBendDirection()), + _compress(data.getCompress()), + _stretch(data.getStretch()), + _mix(data.getMix()), + _softness(data.getSoftness()), + _target(skeleton.findBone( + data.getTarget()->getName())), + _active(false) { + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); i++) { + BoneData *boneData = _data.getBones()[i]; + _bones.add(skeleton.findBone(boneData->getName())); + } +} + +void IkConstraint::update() { + if (_mix == 0) return; + switch (_bones.size()) { + case 1: { + Bone *bone0 = _bones[0]; + apply(*bone0, _target->getWorldX(), _target->getWorldY(), _compress, _stretch, _data._uniform, _mix); + } break; + case 2: { + Bone *bone0 = _bones[0]; + Bone *bone1 = _bones[1]; + apply(*bone0, *bone1, _target->getWorldX(), _target->getWorldY(), _bendDirection, _stretch, _data._uniform, + _softness, + _mix); + } break; + } +} + +int IkConstraint::getOrder() { + return _data.getOrder(); +} + +IkConstraintData &IkConstraint::getData() { + return _data; +} + +Vector &IkConstraint::getBones() { + return _bones; +} + +Bone *IkConstraint::getTarget() { + return _target; +} + +void IkConstraint::setTarget(Bone *inValue) { + _target = inValue; +} + +int IkConstraint::getBendDirection() { + return _bendDirection; +} + +void IkConstraint::setBendDirection(int inValue) { + _bendDirection = inValue; +} + +float IkConstraint::getMix() { + return _mix; +} + +void IkConstraint::setMix(float inValue) { + _mix = inValue; +} + +bool IkConstraint::getStretch() { + return _stretch; +} + +void IkConstraint::setStretch(bool inValue) { + _stretch = inValue; +} + +bool IkConstraint::getCompress() { + return _compress; +} + +void IkConstraint::setCompress(bool inValue) { + _compress = inValue; +} + +bool IkConstraint::isActive() { + return _active; +} + +void IkConstraint::setActive(bool inValue) { + _active = inValue; +} + +float IkConstraint::getSoftness() { + return _softness; +} + +void IkConstraint::setSoftness(float inValue) { + _softness = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp new file mode 100644 index 0000000..37e2bed --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -0,0 +1,109 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +IkConstraintData::IkConstraintData(const String &name) : ConstraintData(name), + _target(NULL), + _bendDirection(1), + _compress(false), + _stretch(false), + _uniform(false), + _mix(1), + _softness(0) { +} + +Vector &IkConstraintData::getBones() { + return _bones; +} + +BoneData *IkConstraintData::getTarget() { + return _target; +} + +void IkConstraintData::setTarget(BoneData *inValue) { + _target = inValue; +} + +int IkConstraintData::getBendDirection() { + return _bendDirection; +} + +void IkConstraintData::setBendDirection(int inValue) { + _bendDirection = inValue; +} + +float IkConstraintData::getMix() { + return _mix; +} + +void IkConstraintData::setMix(float inValue) { + _mix = inValue; +} + +bool IkConstraintData::getStretch() { + return _stretch; +} + +void IkConstraintData::setStretch(bool inValue) { + _stretch = inValue; +} + +bool IkConstraintData::getCompress() { + return _compress; +} + +void IkConstraintData::setCompress(bool inValue) { + _compress = inValue; +} + + +bool IkConstraintData::getUniform() { + return _uniform; +} + +void IkConstraintData::setUniform(bool inValue) { + _uniform = inValue; +} + +float IkConstraintData::getSoftness() { + return _softness; +} + +void IkConstraintData::setSoftness(float inValue) { + _softness = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp new file mode 100644 index 0000000..5aa3b1d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -0,0 +1,145 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(IkConstraintTimeline, CurveTimeline) + +IkConstraintTimeline::IkConstraintTimeline(size_t frameCount, size_t bezierCount, int ikConstraintIndex) + : CurveTimeline(frameCount, IkConstraintTimeline::ENTRIES, bezierCount), _ikConstraintIndex(ikConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_IkConstraint << 32) | ikConstraintIndex}; + setPropertyIds(ids, 1); +} + +void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + IkConstraint *constraintP = skeleton._ikConstraints[_ikConstraintIndex]; + IkConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._mix = constraint._data._mix; + constraint._softness = constraint._data._softness; + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + return; + case MixBlend_First: + constraint._mix += (constraint._data._mix - constraint._mix) * alpha; + constraint._softness += (constraint._data._softness - constraint._softness) * alpha; + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + return; + default: + return; + } + } + + float mix = 0, softness = 0; + int i = Animation::search(_frames, time, IkConstraintTimeline::ENTRIES); + int curveType = (int) _curves[i / IkConstraintTimeline::ENTRIES]; + switch (curveType) { + case IkConstraintTimeline::LINEAR: { + float before = _frames[i]; + mix = _frames[i + IkConstraintTimeline::MIX]; + softness = _frames[i + IkConstraintTimeline::SOFTNESS]; + float t = (time - before) / (_frames[i + IkConstraintTimeline::ENTRIES] - before); + mix += (_frames[i + IkConstraintTimeline::ENTRIES + IkConstraintTimeline::MIX] - mix) * t; + softness += (_frames[i + IkConstraintTimeline::ENTRIES + IkConstraintTimeline::SOFTNESS] - softness) * t; + break; + } + case IkConstraintTimeline::STEPPED: { + mix = _frames[i + IkConstraintTimeline::MIX]; + softness = _frames[i + IkConstraintTimeline::SOFTNESS]; + break; + } + default: { + mix = getBezierValue(time, i, IkConstraintTimeline::MIX, curveType - IkConstraintTimeline::BEZIER); + softness = getBezierValue(time, i, IkConstraintTimeline::SOFTNESS, + curveType + IkConstraintTimeline::BEZIER_SIZE - + IkConstraintTimeline::BEZIER); + } + } + + if (blend == MixBlend_Setup) { + constraint._mix = constraint._data._mix + (mix - constraint._data._mix) * alpha; + constraint._softness = constraint._data._softness + (softness - constraint._data._softness) * alpha; + + if (direction == MixDirection_Out) { + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + } else { + constraint._bendDirection = _frames[i + IkConstraintTimeline::BEND_DIRECTION]; + constraint._compress = _frames[i + IkConstraintTimeline::COMPRESS] != 0; + constraint._stretch = _frames[i + IkConstraintTimeline::STRETCH] != 0; + } + } else { + constraint._mix += (mix - constraint._mix) * alpha; + constraint._softness += (softness - constraint._softness) * alpha; + if (direction == MixDirection_In) { + constraint._bendDirection = _frames[i + IkConstraintTimeline::BEND_DIRECTION]; + constraint._compress = _frames[i + IkConstraintTimeline::COMPRESS] != 0; + constraint._stretch = _frames[i + IkConstraintTimeline::STRETCH] != 0; + } + } +} + +void IkConstraintTimeline::setFrame(int frame, float time, float mix, float softness, int bendDirection, bool compress, + bool stretch) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + MIX] = mix; + _frames[frame + SOFTNESS] = softness; + _frames[frame + BEND_DIRECTION] = (float) bendDirection; + _frames[frame + COMPRESS] = compress ? 1 : 0; + _frames[frame + STRETCH] = stretch ? 1 : 0; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Json.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Json.cpp new file mode 100644 index 0000000..9cc17b2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Json.cpp @@ -0,0 +1,565 @@ +/* +Copyright (c) 2009, Dave Gamble +Copyright (c) 2013, Esoteric Software + +Permission is hereby granted, dispose of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +/* Json */ +/* JSON parser in CPP, from json.c in the spine-c runtime */ + +#ifndef _DEFAULT_SOURCE +/* Bring strings.h definitions into string.h, where appropriate */ +#define _DEFAULT_SOURCE +#endif + +#ifndef _BSD_SOURCE +/* Bring strings.h definitions into string.h, where appropriate */ +#define _BSD_SOURCE +#endif + +#include +#include +#include + +#include +#include + +using namespace spine; + +const int Json::JSON_FALSE = 0; +const int Json::JSON_TRUE = 1; +const int Json::JSON_NULL = 2; +const int Json::JSON_NUMBER = 3; +const int Json::JSON_STRING = 4; +const int Json::JSON_ARRAY = 5; +const int Json::JSON_OBJECT = 6; + +const char *Json::_error = NULL; + +Json *Json::getItem(Json *object, const char *string) { + Json *c = object->_child; + while (c && json_strcasecmp(c->_name, string)) { + c = c->_next; + } + return c; +} + +Json *Json::getItem(Json *object, int childIndex) { + Json *current = object->_child; + while (current != NULL && childIndex > 0) { + childIndex--; + current = current->_next; + } + return current; +} + +const char *Json::getString(Json *object, const char *name, const char *defaultValue) { + object = getItem(object, name); + if (object) { + return object->_valueString; + } + + return defaultValue; +} + +float Json::getFloat(Json *value, const char *name, float defaultValue) { + value = getItem(value, name); + return value ? value->_valueFloat : defaultValue; +} + +int Json::getInt(Json *value, const char *name, int defaultValue) { + value = getItem(value, name); + return value ? value->_valueInt : defaultValue; +} + +bool Json::getBoolean(spine::Json *value, const char *name, bool defaultValue) { + value = getItem(value, name); + if (value) { + if (value->_valueString) return strcmp(value->_valueString, "true") == 0; + if (value->_type == JSON_NULL) return false; + if (value->_type == JSON_NUMBER) return value->_valueFloat != 0; + if (value->_type == JSON_FALSE) return false; + if (value->_type == JSON_TRUE) return true; + return defaultValue; + } else { + return defaultValue; + } +} + +const char *Json::getError() { + return _error; +} + +Json::Json(const char *value) : _next(NULL), +#if SPINE_JSON_HAVE_PREV + _prev(NULL), +#endif + _child(NULL), + _type(0), + _size(0), + _valueString(NULL), + _valueInt(0), + _valueFloat(0), + _name(NULL) { + if (value) { + value = parseValue(this, skip(value)); + + assert(value); + } +} + +Json::~Json() { + spine::Json *curr = NULL; + spine::Json *next = _child; + do { + curr = next; + if (curr) { + next = curr->_next; + } + delete curr; + } while (next); + + if (_valueString) { + SpineExtension::free(_valueString, __FILE__, __LINE__); + } + + if (_name) { + SpineExtension::free(_name, __FILE__, __LINE__); + } +} + +const char *Json::skip(const char *inValue) { + if (!inValue) { + /* must propagate NULL since it's often called in skip(f(...)) form */ + return NULL; + } + + while (*inValue && (unsigned char) *inValue <= 32) { + inValue++; + } + + return inValue; +} + +const char *Json::parseValue(Json *item, const char *value) { + /* Referenced by constructor, parseArray(), and parseObject(). */ + /* Always called with the result of skip(). */ +#ifdef SPINE_JSON_DEBUG /* Checked at entry to graph, constructor, and after every parse call. */ + if (!value) { + /* Fail on null. */ + return NULL; + } +#endif + + switch (*value) { + case 'n': { + if (!strncmp(value + 1, "ull", 3)) { + item->_type = JSON_NULL; + return value + 4; + } + break; + } + case 'f': { + if (!strncmp(value + 1, "alse", 4)) { + item->_type = JSON_FALSE; + /* calloc prevents us needing item->_type = JSON_FALSE or valueInt = 0 here */ + return value + 5; + } + break; + } + case 't': { + if (!strncmp(value + 1, "rue", 3)) { + item->_type = JSON_TRUE; + item->_valueInt = 1; + return value + 4; + } + break; + } + case '\"': + return parseString(item, value); + case '[': + return parseArray(item, value); + case '{': + return parseObject(item, value); + case '-': /* fallthrough */ + case '0': /* fallthrough */ + case '1': /* fallthrough */ + case '2': /* fallthrough */ + case '3': /* fallthrough */ + case '4': /* fallthrough */ + case '5': /* fallthrough */ + case '6': /* fallthrough */ + case '7': /* fallthrough */ + case '8': /* fallthrough */ + case '9': + return parseNumber(item, value); + default: + break; + } + + _error = value; + return NULL; /* failure. */ +} + +static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC}; + +const char *Json::parseString(Json *item, const char *str) { + const char *ptr = str + 1; + char *ptr2; + char *out; + int len = 0; + unsigned uc, uc2; + if (*str != '\"') { + /* TODO: don't need this check when called from parseValue, but do need from parseObject */ + _error = str; + return 0; + } /* not a string! */ + + while (*ptr != '\"' && *ptr && ++len) { + if (*ptr++ == '\\') { + ptr++; /* Skip escaped quotes. */ + } + } + + out = SpineExtension::alloc(len + 1, __FILE__, __LINE__); /* The length needed for the string, roughly. */ + if (!out) { + return 0; + } + + ptr = str + 1; + ptr2 = out; + while (*ptr != '\"' && *ptr) { + if (*ptr != '\\') { + *ptr2++ = *ptr++; + } else { + ptr++; + switch (*ptr) { + case 'b': + *ptr2++ = '\b'; + break; + case 'f': + *ptr2++ = '\f'; + break; + case 'n': + *ptr2++ = '\n'; + break; + case 'r': + *ptr2++ = '\r'; + break; + case 't': + *ptr2++ = '\t'; + break; + case 'u': { + /* transcode utf16 to utf8. */ + sscanf(ptr + 1, "%4x", &uc); + ptr += 4; /* get the unicode char. */ + + if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) { + break; /* check for invalid. */ + } + + /* TODO provide an option to ignore surrogates, use unicode replacement character? */ + if (uc >= 0xD800 && uc <= 0xDBFF) /* UTF16 surrogate pairs. */ { + if (ptr[1] != '\\' || ptr[2] != 'u') { + break; /* missing second-half of surrogate. */ + } + sscanf(ptr + 3, "%4x", &uc2); + ptr += 6; + if (uc2 < 0xDC00 || uc2 > 0xDFFF) { + break; /* invalid second-half of surrogate. */ + } + uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF)); + } + + len = 4; + if (uc < 0x80) { + len = 1; + } else if (uc < 0x800) { + len = 2; + } else if (uc < 0x10000) { + len = 3; + } + ptr2 += len; + + switch (len) { + case 4: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 3: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 2: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 1: + *--ptr2 = (uc | firstByteMark[len]); + } + ptr2 += len; + break; + } + default: + *ptr2++ = *ptr; + break; + } + ptr++; + } + } + + *ptr2 = 0; + + if (*ptr == '\"') { + ptr++; /* TODO error handling if not \" or \0 ? */ + } + + item->_valueString = out; + item->_type = JSON_STRING; + + return ptr; +} + +const char *Json::parseNumber(Json *item, const char *num) { + double result = 0.0; + int negative = 0; + char *ptr = (char *) num; + + if (*ptr == '-') { + negative = -1; + ++ptr; + } + + while (*ptr >= '0' && *ptr <= '9') { + result = result * 10.0 + (*ptr - '0'); + ++ptr; + } + + if (*ptr == '.') { + double fraction = 0.0; + int n = 0; + ++ptr; + + while (*ptr >= '0' && *ptr <= '9') { + fraction = (fraction * 10.0) + (*ptr - '0'); + ++ptr; + ++n; + } + result += fraction / pow(10.0, n); + } + + if (negative) { + result = -result; + } + + if (*ptr == 'e' || *ptr == 'E') { + double exponent = 0; + int expNegative = 0; + int n = 0; + ++ptr; + + if (*ptr == '-') { + expNegative = -1; + ++ptr; + } else if (*ptr == '+') { + ++ptr; + } + + while (*ptr >= '0' && *ptr <= '9') { + exponent = (exponent * 10.0) + (*ptr - '0'); + ++ptr; + ++n; + } + + if (expNegative) { + result = result / pow(10, exponent); + } else { + result = result * pow(10, exponent); + } + } + + if (ptr != num) { + /* Parse success, number found. */ + item->_valueFloat = (float) result; + item->_valueInt = (int) result; + item->_type = JSON_NUMBER; + return ptr; + } else { + /* Parse failure, _error is set. */ + _error = num; + return NULL; + } +} + +const char *Json::parseArray(Json *item, const char *value) { + Json *child; + +#ifdef SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */ + if (*value != '[') { + ep = value; + return 0; + } /* not an array! */ +#endif + + item->_type = JSON_ARRAY; + value = skip(value + 1); + if (*value == ']') { + return value + 1; /* empty array. */ + } + + item->_child = child = new (__FILE__, __LINE__) Json(NULL); + if (!item->_child) { + return NULL; /* memory fail */ + } + + value = skip(parseValue(child, skip(value))); /* skip any spacing, get the value. */ + + if (!value) { + return NULL; + } + + item->_size = 1; + + while (*value == ',') { + Json *new_item = new (__FILE__, __LINE__) Json(NULL); + if (!new_item) { + return NULL; /* memory fail */ + } + child->_next = new_item; +#if SPINE_JSON_HAVE_PREV + new_item->prev = child; +#endif + child = new_item; + value = skip(parseValue(child, skip(value + 1))); + if (!value) { + return NULL; /* parse fail */ + } + item->_size++; + } + + if (*value == ']') { + return value + 1; /* end of array */ + } + + _error = value; + + return NULL; /* malformed. */ +} + +/* Build an object from the text. */ +const char *Json::parseObject(Json *item, const char *value) { + Json *child; + +#ifdef SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */ + if (*value != '{') { + ep = value; + return 0; + } /* not an object! */ +#endif + + item->_type = JSON_OBJECT; + value = skip(value + 1); + if (*value == '}') { + return value + 1; /* empty array. */ + } + + item->_child = child = new (__FILE__, __LINE__) Json(NULL); + if (!item->_child) { + return NULL; + } + value = skip(parseString(child, skip(value))); + if (!value) { + return NULL; + } + child->_name = child->_valueString; + child->_valueString = 0; + if (*value != ':') { + _error = value; + return NULL; + } /* fail! */ + + value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return NULL; + } + + item->_size = 1; + + while (*value == ',') { + Json *new_item = new (__FILE__, __LINE__) Json(NULL); + if (!new_item) { + return NULL; /* memory fail */ + } + child->_next = new_item; +#if SPINE_JSON_HAVE_PREV + new_item->prev = child; +#endif + child = new_item; + value = skip(parseString(child, skip(value + 1))); + if (!value) { + return NULL; + } + child->_name = child->_valueString; + child->_valueString = 0; + if (*value != ':') { + _error = value; + return NULL; + } /* fail! */ + + value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return NULL; + } + item->_size++; + } + + if (*value == '}') { + return value + 1; /* end of array */ + } + + _error = value; + + return NULL; /* malformed. */ +} + +int Json::json_strcasecmp(const char *s1, const char *s2) { + /* TODO we may be able to elide these NULL checks if we can prove + * the graph and input (only callsite is Json_getItem) should not have NULLs + */ + if (s1 && s2) { +#if defined(_WIN32) + return _stricmp(s1, s2); +#else + return strcasecmp(s1, s2); +#endif + } else { + if (s1 < s2) { + return -1; /* s1 is null, s2 is not */ + } else if (s1 == s2) { + return 0; /* both are null */ + } else { + return 1; /* s2 is nul s1 is not */ + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp new file mode 100644 index 0000000..7528963 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp @@ -0,0 +1,46 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +LinkedMesh::LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, + bool inheritDeform) : _mesh(mesh), + _skin(skin), + _slotIndex(slotIndex), + _parent(parent), + _inheritDeform(inheritDeform) { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Log.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Log.cpp new file mode 100644 index 0000000..714f3ef --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Log.cpp @@ -0,0 +1,123 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +void spine::spDebug_printSkeletonData(SkeletonData *skeletonData) { + int i, n; + spDebug_printBoneDatas(skeletonData->getBones()); + + for (i = 0, n = skeletonData->getAnimations().size(); i < n; i++) { + spDebug_printAnimation(skeletonData->getAnimations()[i]); + } +} + +void _spDebug_printTimelineBase(Timeline *timeline) { + printf(" Timeline %s:\n", timeline->getRTTI().getClassName()); + printf(" frame count: %zu\n", timeline->getFrameCount()); + printf(" frame entries: %zu\n", timeline->getFrameEntries()); + printf(" frames: "); + spDebug_printFloats(timeline->getFrames()); + printf("\n"); +} + +void _spDebug_printCurveTimeline(CurveTimeline *timeline) { + _spDebug_printTimelineBase(timeline); + printf(" curves: "); + spDebug_printFloats(timeline->getCurves()); + printf("\n"); +} + +void spine::spDebug_printTimeline(Timeline *timeline) { + if (timeline->getRTTI().instanceOf(CurveTimeline::rtti)) + _spDebug_printCurveTimeline(static_cast(timeline)); + else + _spDebug_printTimelineBase(timeline); +} + +void spine::spDebug_printAnimation(Animation *animation) { + int i, n; + printf("Animation %s: %zu timelines\n", animation->getName().buffer(), animation->getTimelines().size()); + + for (i = 0, n = animation->getTimelines().size(); i < n; i++) { + Timeline *timeline = animation->getTimelines()[i]; + spDebug_printTimeline(timeline); + } +} + +void spine::spDebug_printBoneDatas(Vector &boneDatas) { + int i, n; + for (i = 0, n = boneDatas.size(); i < n; i++) { + spDebug_printBoneData(boneDatas[i]); + } +} + +void spine::spDebug_printBoneData(BoneData *boneData) { + printf("Bone data %s: %f, %f, %f, %f, %f, %f %f\n", boneData->getName().buffer(), boneData->getRotation(), + boneData->getScaleX(), boneData->getScaleY(), boneData->getX(), boneData->getY(), boneData->getShearX(), + boneData->getShearY()); +} + +void spine::spDebug_printSkeleton(Skeleton *skeleton) { + spDebug_printBones(skeleton->getBones()); +} + +void spine::spDebug_printBones(Vector &bones) { + int i, n; + for (i = 0, n = bones.size(); i < n; i++) { + spDebug_printBone(bones[i]); + } +} + +void spine::spDebug_printBone(Bone *bone) { + printf("Bone %s: %f, %f, %f, %f, %f, %f\n", bone->getData().getName().buffer(), bone->getA(), bone->getB(), + bone->getC(), bone->getD(), bone->getWorldX(), bone->getWorldY()); +} + +void spine::spDebug_printFloats(float *values, int numFloats) { + int i; + printf("(%i) [", numFloats); + for (i = 0; i < numFloats; i++) { + printf("%f, ", values[i]); + } + printf("]"); +} + +void spine::spDebug_printFloats(Vector &values) { + int i, n; + printf("(%zu) [", values.size()); + for (i = 0, n = values.size(); i < n; i++) { + printf("%f, ", values[i]); + } + printf("]"); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/MathUtil.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/MathUtil.cpp new file mode 100644 index 0000000..af761b1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/MathUtil.cpp @@ -0,0 +1,128 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include + +// Required for division by 0 in _isNaN on MSVC +#ifdef _MSC_VER +#pragma warning(disable : 4723) +#endif + +using namespace spine; + +const float MathUtil::Pi = 3.1415926535897932385f; +const float MathUtil::Pi_2 = 3.1415926535897932385f * 2; +const float MathUtil::Deg_Rad = (3.1415926535897932385f / 180.0f); +const float MathUtil::Rad_Deg = (180.0f / 3.1415926535897932385f); + +float MathUtil::abs(float v) { + return ((v) < 0 ? -(v) : (v)); +} + +float MathUtil::sign(float v) { + return ((v) < 0 ? -1.0f : (v) > 0 ? 1.0f + : 0.0f); +} + +float MathUtil::clamp(float x, float min, float max) { + return ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))); +} + +float MathUtil::fmod(float a, float b) { + return (float) ::fmod(a, b); +} + +/// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 +/// degrees), largest error of 0.00488 radians (0.2796 degrees). +float MathUtil::atan2(float y, float x) { + return (float) ::atan2(y, x); +} + +/// Returns the cosine in radians from a lookup table. +float MathUtil::cos(float radians) { + return (float) ::cos(radians); +} + +/// Returns the sine in radians from a lookup table. +float MathUtil::sin(float radians) { + return (float) ::sin(radians); +} + +float MathUtil::sqrt(float v) { + return (float) ::sqrt(v); +} + +float MathUtil::acos(float v) { + return (float) ::acos(v); +} + +/// Returns the sine in radians from a lookup table. +float MathUtil::sinDeg(float degrees) { + return (float) ::sin(degrees * MathUtil::Deg_Rad); +} + +/// Returns the cosine in radians from a lookup table. +float MathUtil::cosDeg(float degrees) { + return (float) ::cos(degrees * MathUtil::Deg_Rad); +} + +/* Need to pass 0 as an argument, so VC++ doesn't error with C2124 */ +static bool _isNan(float value, float zero) { + float _nan = (float) 0.0 / zero; + return 0 == memcmp((void *) &value, (void *) &_nan, sizeof(value)); +} + +bool MathUtil::isNan(float v) { + return _isNan(v, 0); +} + +float MathUtil::random() { + return ::rand() / (float) RAND_MAX; +} + +float MathUtil::randomTriangular(float min, float max) { + return randomTriangular(min, max, (min + max) * 0.5f); +} + +float MathUtil::randomTriangular(float min, float max, float mode) { + float u = random(); + float d = max - min; + if (u <= (mode - min) / d) return min + sqrt(u * d * (mode - min)); + return max - sqrt((1 - u) * d * (max - mode)); +} + +float MathUtil::pow(float a, float b) { + return (float) ::pow(a, b); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp new file mode 100644 index 0000000..12d5682 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp @@ -0,0 +1,337 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include + +using namespace spine; + +RTTI_IMPL(MeshAttachment, VertexAttachment) + +MeshAttachment::MeshAttachment(const String &name) : VertexAttachment(name), HasRendererObject(), + _regionOffsetX(0), + _regionOffsetY(0), + _regionWidth(0), + _regionHeight(0), + _regionOriginalWidth(0), + _regionOriginalHeight(0), + _parentMesh(NULL), + _path(), + _regionU(0), + _regionV(0), + _regionU2(0), + _regionV2(0), + _width(0), + _height(0), + _color(1, 1, 1, 1), + _hullLength(0), + _regionDegrees(0) {} + +MeshAttachment::~MeshAttachment() {} + +void MeshAttachment::updateUVs() { + if (_uvs.size() != _regionUVs.size()) { + _uvs.setSize(_regionUVs.size(), 0); + } + + int i = 0, n = _regionUVs.size(); + float u = _regionU, v = _regionV; + float width = 0, height = 0; + + switch (_regionDegrees) { + case 90: { + float textureWidth = _regionHeight / (_regionU2 - _regionU); + float textureHeight = _regionWidth / (_regionV2 - _regionV); + u -= (_regionOriginalHeight - _regionOffsetY - _regionHeight) / textureWidth; + v -= (_regionOriginalWidth - _regionOffsetX - _regionWidth) / textureHeight; + width = _regionOriginalHeight / textureWidth; + height = _regionOriginalWidth / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + _regionUVs[i + 1] * width; + _uvs[i + 1] = v + (1 - _regionUVs[i]) * height; + } + return; + } + case 180: { + float textureWidth = _regionWidth / (_regionU2 - _regionU); + float textureHeight = _regionHeight / (_regionV2 - _regionV); + u -= (_regionOriginalWidth - _regionOffsetX - _regionWidth) / textureWidth; + v -= _regionOffsetY / textureHeight; + width = _regionOriginalWidth / textureWidth; + height = _regionOriginalHeight / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + (1 - _regionUVs[i]) * width; + _uvs[i + 1] = v + (1 - _regionUVs[i + 1]) * height; + } + return; + } + case 270: { + float textureHeight = _regionHeight / (_regionV2 - _regionV); + float textureWidth = _regionWidth / (_regionU2 - _regionU); + u -= _regionOffsetY / textureWidth; + v -= _regionOffsetX / textureHeight; + width = _regionOriginalHeight / textureWidth; + height = _regionOriginalWidth / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + (1 - _regionUVs[i + 1]) * width; + _uvs[i + 1] = v + _regionUVs[i] * height; + } + return; + } + default: { + float textureWidth = _regionWidth / (_regionU2 - _regionU); + float textureHeight = _regionHeight / (_regionV2 - _regionV); + u -= _regionOffsetX / textureWidth; + v -= (_regionOriginalHeight - _regionOffsetY - _regionHeight) / textureHeight; + width = _regionOriginalWidth / textureWidth; + height = _regionOriginalHeight / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + _regionUVs[i] * width; + _uvs[i + 1] = v + _regionUVs[i + 1] * height; + } + } + } +} + +int MeshAttachment::getHullLength() { + return _hullLength; +} + +void MeshAttachment::setHullLength(int inValue) { + _hullLength = inValue; +} + +Vector &MeshAttachment::getRegionUVs() { + return _regionUVs; +} + +Vector &MeshAttachment::getUVs() { + return _uvs; +} + +Vector &MeshAttachment::getTriangles() { + return _triangles; +} + +const String &MeshAttachment::getPath() { + return _path; +} + +void MeshAttachment::setPath(const String &inValue) { + _path = inValue; +} + +float MeshAttachment::getRegionU() { + return _regionU; +} + +void MeshAttachment::setRegionU(float inValue) { + _regionU = inValue; +} + +float MeshAttachment::getRegionV() { + return _regionV; +} + +void MeshAttachment::setRegionV(float inValue) { + _regionV = inValue; +} + +float MeshAttachment::getRegionU2() { + return _regionU2; +} + +void MeshAttachment::setRegionU2(float inValue) { + _regionU2 = inValue; +} + +float MeshAttachment::getRegionV2() { + return _regionV2; +} + +void MeshAttachment::setRegionV2(float inValue) { + _regionV2 = inValue; +} + +int MeshAttachment::getRegionDegrees() { + return _regionDegrees; +} + +void MeshAttachment::setRegionDegrees(int inValue) { + _regionDegrees = inValue; +} + +float MeshAttachment::getRegionOffsetX() { + return _regionOffsetX; +} + +void MeshAttachment::setRegionOffsetX(float inValue) { + _regionOffsetX = inValue; +} + +float MeshAttachment::getRegionOffsetY() { + return _regionOffsetY; +} + +void MeshAttachment::setRegionOffsetY(float inValue) { + _regionOffsetY = inValue; +} + +float MeshAttachment::getRegionWidth() { + return _regionWidth; +} + +void MeshAttachment::setRegionWidth(float inValue) { + _regionWidth = inValue; +} + +float MeshAttachment::getRegionHeight() { + return _regionHeight; +} + +void MeshAttachment::setRegionHeight(float inValue) { + _regionHeight = inValue; +} + +float MeshAttachment::getRegionOriginalWidth() { + return _regionOriginalWidth; +} + +void MeshAttachment::setRegionOriginalWidth(float inValue) { + _regionOriginalWidth = inValue; +} + +float MeshAttachment::getRegionOriginalHeight() { + return _regionOriginalHeight; +} + +void MeshAttachment::setRegionOriginalHeight(float inValue) { + _regionOriginalHeight = inValue; +} + +MeshAttachment *MeshAttachment::getParentMesh() { + return _parentMesh; +} + +void MeshAttachment::setParentMesh(MeshAttachment *inValue) { + _parentMesh = inValue; + if (inValue != NULL) { + _bones.clearAndAddAll(inValue->_bones); + _vertices.clearAndAddAll(inValue->_vertices); + _worldVerticesLength = inValue->_worldVerticesLength; + _regionUVs.clearAndAddAll(inValue->_regionUVs); + _triangles.clearAndAddAll(inValue->_triangles); + _hullLength = inValue->_hullLength; + _edges.clearAndAddAll(inValue->_edges); + _width = inValue->_width; + _height = inValue->_height; + } +} + +Vector &MeshAttachment::getEdges() { + return _edges; +} + +float MeshAttachment::getWidth() { + return _width; +} + +void MeshAttachment::setWidth(float inValue) { + _width = inValue; +} + +float MeshAttachment::getHeight() { + return _height; +} + +void MeshAttachment::setHeight(float inValue) { + _height = inValue; +} + +spine::Color &MeshAttachment::getColor() { + return _color; +} + +Attachment *MeshAttachment::copy() { + if (_parentMesh) return newLinkedMesh(); + + MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName()); + copy->setRendererObject(getRendererObject()); + copy->_regionU = _regionU; + copy->_regionV = _regionV; + copy->_regionU2 = _regionU2; + copy->_regionV2 = _regionV2; + copy->_regionDegrees = _regionDegrees; + copy->_regionOffsetX = _regionOffsetX; + copy->_regionOffsetY = _regionOffsetY; + copy->_regionWidth = _regionWidth; + copy->_regionHeight = _regionHeight; + copy->_regionOriginalWidth = _regionOriginalWidth; + copy->_regionOriginalHeight = _regionOriginalHeight; + copy->_path = _path; + copy->_color.set(_color); + + copyTo(copy); + copy->_regionUVs.clearAndAddAll(_regionUVs); + copy->_uvs.clearAndAddAll(_uvs); + copy->_triangles.clearAndAddAll(_triangles); + copy->_hullLength = _hullLength; + + // Nonessential. + copy->_edges.clearAndAddAll(copy->_edges); + copy->_width = _width; + copy->_height = _height; + return copy; +} + +MeshAttachment *MeshAttachment::newLinkedMesh() { + MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName()); + copy->setRendererObject(getRendererObject()); + copy->_regionU = _regionU; + copy->_regionV = _regionV; + copy->_regionU2 = _regionU2; + copy->_regionV2 = _regionV2; + copy->_regionDegrees = _regionDegrees; + copy->_regionOffsetX = _regionOffsetX; + copy->_regionOffsetY = _regionOffsetY; + copy->_regionWidth = _regionWidth; + copy->_regionHeight = _regionHeight; + copy->_regionOriginalWidth = _regionOriginalWidth; + copy->_regionOriginalHeight = _regionOriginalHeight; + copy->_path = _path; + copy->_color.set(_color); + copy->_deformAttachment = this->_deformAttachment; + copy->setParentMesh(_parentMesh ? _parentMesh : this); + copy->updateUVs(); + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp new file mode 100644 index 0000000..016932f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp @@ -0,0 +1,75 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +using namespace spine; + +RTTI_IMPL(PathAttachment, VertexAttachment) + +PathAttachment::PathAttachment(const String &name) : VertexAttachment(name), _closed(false), _constantSpeed(false), + _color() { +} + +Vector &PathAttachment::getLengths() { + return _lengths; +} + +bool PathAttachment::isClosed() { + return _closed; +} + +void PathAttachment::setClosed(bool inValue) { + _closed = inValue; +} + +bool PathAttachment::isConstantSpeed() { + return _constantSpeed; +} + +void PathAttachment::setConstantSpeed(bool inValue) { + _constantSpeed = inValue; +} + +Color &PathAttachment::getColor() { + return _color; +} + +Attachment *PathAttachment::copy() { + PathAttachment *copy = new (__FILE__, __LINE__) PathAttachment(getName()); + copyTo(copy); + copy->_lengths.clearAndAddAll(_lengths); + copy->_closed = _closed; + copy->_constantSpeed = _constantSpeed; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp new file mode 100644 index 0000000..4682010 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -0,0 +1,586 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraint, Updatable) + +const float PathConstraint::EPSILON = 0.00001f; +const int PathConstraint::NONE = -1; +const int PathConstraint::BEFORE = -2; +const int PathConstraint::AFTER = -3; + +PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : Updatable(), + _data(data), + _target(skeleton.findSlot( + data.getTarget()->getName())), + _position(data.getPosition()), + _spacing(data.getSpacing()), + _mixRotate(data.getMixRotate()), + _mixX(data.getMixX()), + _mixY(data.getMixY()), + _active(false) { + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); i++) { + BoneData *boneData = _data.getBones()[i]; + _bones.add(skeleton.findBone(boneData->getName())); + } + + _segments.setSize(10, 0); +} + +void PathConstraint::update() { + Attachment *baseAttachment = _target->getAttachment(); + if (baseAttachment == NULL || !baseAttachment->getRTTI().instanceOf(PathAttachment::rtti)) { + return; + } + PathAttachment *attachment = static_cast(baseAttachment); + + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY; + if (mixRotate == 0 && mixX == 0 && mixY == 0) return; + + PathConstraintData &data = _data; + bool tangents = data._rotateMode == RotateMode_Tangent, scale = data._rotateMode == RotateMode_ChainScale; + size_t boneCount = _bones.size(); + size_t spacesCount = tangents ? boneCount : boneCount + 1; + _spaces.setSize(spacesCount, 0); + if (scale) _lengths.setSize(boneCount, 0); + float spacing = _spacing; + + switch (data._spacingMode) { + case SpacingMode_Percent: { + if (scale) { + for (size_t i = 0, n = spacesCount - 1; i < n; i++) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + float setupLength = bone._data.getLength(); + if (setupLength < PathConstraint::EPSILON) { + _lengths[i] = 0; + } else { + float x = setupLength * bone._a, y = setupLength * bone._c; + _lengths[i] = MathUtil::sqrt(x * x + y * y); + } + } + } + for (size_t i = 1; i < spacesCount; ++i) { + _spaces[i] = spacing; + } + break; + } + case SpacingMode_Proportional: { + float sum = 0; + for (size_t i = 0, n = spacesCount - 1; i < n;) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + float setupLength = bone._data.getLength(); + if (setupLength < PathConstraint::EPSILON) { + if (scale) _lengths[i] = 0; + _spaces[++i] = spacing; + } else { + float x = setupLength * bone._a, y = setupLength * bone._c; + float length = MathUtil::sqrt(x * x + y * y); + if (scale) _lengths[i] = length; + _spaces[++i] = length; + sum += length; + } + } + if (sum > 0) { + sum = spacesCount / sum * spacing; + for (size_t i = 1; i < spacesCount; i++) { + _spaces[i] *= sum; + } + } + break; + } + default: { + bool lengthSpacing = data._spacingMode == SpacingMode_Length; + for (size_t i = 0, n = spacesCount - 1; i < n;) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + float setupLength = bone._data.getLength(); + if (setupLength < PathConstraint::EPSILON) { + if (scale) _lengths[i] = 0; + _spaces[++i] = spacing; + } else { + float x = setupLength * bone._a, y = setupLength * bone._c; + float length = MathUtil::sqrt(x * x + y * y); + if (scale) _lengths[i] = length; + _spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; + } + } + } + } + + Vector &positions = computeWorldPositions(*attachment, spacesCount, tangents); + float boneX = positions[0]; + float boneY = positions[1]; + float offsetRotation = data.getOffsetRotation(); + bool tip; + if (offsetRotation == 0) { + tip = data._rotateMode == RotateMode_Chain; + } else { + tip = false; + Bone &p = _target->getBone(); + offsetRotation *= p.getA() * p.getD() - p.getB() * p.getC() > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; + } + + for (size_t i = 0, p = 3; i < boneCount; i++, p += 3) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + bone._worldX += (boneX - bone._worldX) * mixX; + bone._worldY += (boneY - bone._worldY) * mixY; + float x = positions[p]; + float y = positions[p + 1]; + float dx = x - boneX; + float dy = y - boneY; + if (scale) { + float length = _lengths[i]; + if (length >= PathConstraint::EPSILON) { + float s = (MathUtil::sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1; + bone._a *= s; + bone._c *= s; + } + } + + boneX = x; + boneY = y; + + if (mixRotate > 0) { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d, r, cos, sin; + if (tangents) + r = positions[p - 1]; + else if (_spaces[i + 1] < PathConstraint::EPSILON) + r = positions[p + 2]; + else + r = MathUtil::atan2(dy, dx); + + r -= MathUtil::atan2(c, a); + + if (tip) { + cos = MathUtil::cos(r); + sin = MathUtil::sin(r); + float length = bone._data.getLength(); + boneX += (length * (cos * a - sin * c) - dx) * mixRotate; + boneY += (length * (sin * a + cos * c) - dy) * mixRotate; + } else + r += offsetRotation; + + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r *= mixRotate; + cos = MathUtil::cos(r); + sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + } + + bone.updateAppliedTransform(); + } +} + +int PathConstraint::getOrder() { + return _data.getOrder(); +} + +float PathConstraint::getPosition() { + return _position; +} + +void PathConstraint::setPosition(float inValue) { + _position = inValue; +} + +float PathConstraint::getSpacing() { + return _spacing; +} + +void PathConstraint::setSpacing(float inValue) { + _spacing = inValue; +} + +float PathConstraint::getMixRotate() { + return _mixRotate; +} + +void PathConstraint::setMixRotate(float inValue) { + _mixRotate = inValue; +} + +float PathConstraint::getMixX() { + return _mixX; +} + +void PathConstraint::setMixX(float inValue) { + _mixX = inValue; +} + +float PathConstraint::getMixY() { + return _mixY; +} + +void PathConstraint::setMixY(float inValue) { + _mixY = inValue; +} + +Vector &PathConstraint::getBones() { + return _bones; +} + +Slot *PathConstraint::getTarget() { + return _target; +} + +void PathConstraint::setTarget(Slot *inValue) { + _target = inValue; +} + +PathConstraintData &PathConstraint::getData() { + return _data; +} + +Vector & +PathConstraint::computeWorldPositions(PathAttachment &path, int spacesCount, bool tangents) { + Slot &target = *_target; + float position = _position; + _positions.setSize(spacesCount * 3 + 2, 0); + Vector &out = _positions; + Vector &world = _world; + bool closed = path.isClosed(); + int verticesLength = path.getWorldVerticesLength(); + int curveCount = verticesLength / 6; + int prevCurve = NONE; + + float pathLength; + if (!path.isConstantSpeed()) { + Vector &lengths = path.getLengths(); + curveCount -= closed ? 1 : 2; + pathLength = lengths[curveCount]; + if (_data._positionMode == PositionMode_Percent) position *= pathLength; + + float multiplier = 0; + switch (_data._spacingMode) { + case SpacingMode_Percent: + multiplier = pathLength; + break; + case SpacingMode_Proportional: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + + world.setSize(8, 0); + for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + float space = _spaces[i] * multiplier; + position += space; + float p = position; + + if (closed) { + p = MathUtil::fmod(p, pathLength); + if (p < 0) p += pathLength; + curve = 0; + } else if (p < 0) { + if (prevCurve != BEFORE) { + prevCurve = BEFORE; + path.computeWorldVertices(target, 2, 4, world, 0); + } + + addBeforePosition(p, world, 0, out, o); + + continue; + } else if (p > pathLength) { + if (prevCurve != AFTER) { + prevCurve = AFTER; + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0); + } + + addAfterPosition(p - pathLength, world, 0, out, o); + + continue; + } + + // Determine curve containing position. + for (;; curve++) { + float length = lengths[curve]; + if (p > length) continue; + + if (curve == 0) + p /= length; + else { + float prev = lengths[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + + if (curve != prevCurve) { + prevCurve = curve; + if (closed && curve == curveCount) { + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0); + path.computeWorldVertices(target, 0, 4, world, 4); + } else + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0); + } + + addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], + out, o, tangents || (i > 0 && space < EPSILON)); + } + return out; + } + + // World vertices. + if (closed) { + verticesLength += 2; + world.setSize(verticesLength, 0); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } else { + curveCount--; + verticesLength -= 4; + world.setSize(verticesLength, 0); + path.computeWorldVertices(target, 2, verticesLength, world, 0); + } + + // Curve lengths. + _curves.setSize(curveCount, 0); + pathLength = 0; + float x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy; + for (int i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875f; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875f; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375f; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375f; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f; + dfy = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + + if (_data._positionMode == PositionMode_Percent) position *= pathLength; + + float multiplier = 0; + switch (_data._spacingMode) { + case SpacingMode_Percent: + multiplier = pathLength; + break; + case SpacingMode_Proportional: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + + float curveLength = 0; + for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + float space = _spaces[i] * multiplier; + position += space; + float p = position; + + if (closed) { + p = MathUtil::fmod(p, pathLength); + if (p < 0) p += pathLength; + curve = 0; + } else if (p < 0) { + addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength) { + addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + + // Determine curve containing position. + for (;; curve++) { + float length = _curves[curve]; + if (p > length) continue; + if (curve == 0) + p /= length; + else { + float prev = _curves[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + + // Curve segment lengths. + if (curve != prevCurve) { + prevCurve = curve; + int ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03f; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03f; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006f; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006f; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f; + dfy = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f; + curveLength = MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[9] = curveLength; + segment = 0; + } + + // Weight by segment length. + p *= curveLength; + for (;; segment++) { + float length = _segments[segment]; + if (p > length) continue; + if (segment == 0) + p /= length; + else { + float prev = _segments[segment - 1]; + p = segment + (p - prev) / (length - prev); + } + break; + } + addCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, + tangents || (i > 0 && space < EPSILON)); + } + + return out; +} + +void PathConstraint::addBeforePosition(float p, Vector &temp, int i, Vector &output, int o) { + float x1 = temp[i]; + float y1 = temp[i + 1]; + float dx = temp[i + 2] - x1; + float dy = temp[i + 3] - y1; + float r = MathUtil::atan2(dy, dx); + output[o] = x1 + p * MathUtil::cos(r); + output[o + 1] = y1 + p * MathUtil::sin(r); + output[o + 2] = r; +} + +void PathConstraint::addAfterPosition(float p, Vector &temp, int i, Vector &output, int o) { + float x1 = temp[i + 2]; + float y1 = temp[i + 3]; + float dx = x1 - temp[i]; + float dy = y1 - temp[i + 1]; + float r = MathUtil::atan2(dy, dx); + output[o] = x1 + p * MathUtil::cos(r); + output[o + 1] = y1 + p * MathUtil::sin(r); + output[o + 2] = r; +} + +void PathConstraint::addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, + float y2, Vector &output, int o, bool tangents) { + if (p < EPSILON || MathUtil::isNan(p)) { + output[o] = x1; + output[o + 1] = y1; + output[o + 2] = MathUtil::atan2(cy1 - y1, cx1 - x1); + return; + } + + float tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + float ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + float x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + output[o] = x; + output[o + 1] = y; + if (tangents) { + if (p < 0.001) + output[o + 2] = MathUtil::atan2(cy1 - y1, cx1 - x1); + else + output[o + 2] = MathUtil::atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), + x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } +} + +bool PathConstraint::isActive() { + return _active; +} + +void PathConstraint::setActive(bool inValue) { + _active = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp new file mode 100644 index 0000000..4110663 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -0,0 +1,138 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include + +using namespace spine; + +PathConstraintData::PathConstraintData(const String &name) : ConstraintData(name), + _target(NULL), + _positionMode(PositionMode_Fixed), + _spacingMode(SpacingMode_Length), + _rotateMode(RotateMode_Tangent), + _offsetRotation(0), + _position(0), + _spacing(0), + _mixRotate(0), + _mixX(0), + _mixY(0) { +} + +Vector &PathConstraintData::getBones() { + return _bones; +} + +SlotData *PathConstraintData::getTarget() { + return _target; +} + +void PathConstraintData::setTarget(SlotData *inValue) { + _target = inValue; +} + +PositionMode PathConstraintData::getPositionMode() { + return _positionMode; +} + +void PathConstraintData::setPositionMode(PositionMode inValue) { + _positionMode = inValue; +} + +SpacingMode PathConstraintData::getSpacingMode() { + return _spacingMode; +} + +void PathConstraintData::setSpacingMode(SpacingMode inValue) { + _spacingMode = inValue; +} + +RotateMode PathConstraintData::getRotateMode() { + return _rotateMode; +} + +void PathConstraintData::setRotateMode(RotateMode inValue) { + _rotateMode = inValue; +} + +float PathConstraintData::getOffsetRotation() { + return _offsetRotation; +} + +void PathConstraintData::setOffsetRotation(float inValue) { + _offsetRotation = inValue; +} + +float PathConstraintData::getPosition() { + return _position; +} + +void PathConstraintData::setPosition(float inValue) { + _position = inValue; +} + +float PathConstraintData::getSpacing() { + return _spacing; +} + +void PathConstraintData::setSpacing(float inValue) { + _spacing = inValue; +} + +float PathConstraintData::getMixRotate() { + return _mixRotate; +} + +void PathConstraintData::setMixRotate(float inValue) { + _mixRotate = inValue; +} + +float PathConstraintData::getMixX() { + return _mixX; +} + +void PathConstraintData::setMixX(float inValue) { + _mixX = inValue; +} + +float PathConstraintData::getMixY() { + return _mixY; +} + +void PathConstraintData::setMixY(float inValue) { + _mixY = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp new file mode 100644 index 0000000..a10de35 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -0,0 +1,130 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline) + +PathConstraintMixTimeline::PathConstraintMixTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex) + : CurveTimeline(frameCount, PathConstraintMixTimeline::ENTRIES, bezierCount), + _pathConstraintIndex(pathConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_PathConstraintMix << 32) | pathConstraintIndex}; + setPropertyIds(ids, 1); +} + +void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; + PathConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._mixRotate = constraint._data._mixRotate; + constraint._mixX = constraint._data._mixX; + constraint._mixY = constraint._data._mixY; + return; + case MixBlend_First: + constraint._mixRotate += (constraint._data._mixRotate - constraint._mixRotate) * alpha; + constraint._mixX += (constraint._data._mixX - constraint._mixX) * alpha; + constraint._mixY += (constraint._data._mixY - constraint._mixY) * alpha; + default: { + } + } + return; + } + + float rotate, x, y; + int i = Animation::search(_frames, time, PathConstraintMixTimeline::ENTRIES); + int curveType = (int) _curves[i >> 2]; + switch (curveType) { + case LINEAR: { + float before = _frames[i]; + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + float t = (time - before) / (_frames[i + ENTRIES] - before); + rotate += (_frames[i + ENTRIES + ROTATE] - rotate) * t; + x += (_frames[i + ENTRIES + X] - x) * t; + y += (_frames[i + ENTRIES + Y] - y) * t; + break; + } + case STEPPED: { + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + break; + } + default: { + rotate = getBezierValue(time, i, ROTATE, curveType - BEZIER); + x = getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER); + y = getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER); + } + } + + if (blend == MixBlend_Setup) { + PathConstraintData data = constraint._data; + constraint._mixRotate = data._mixRotate + (rotate - data._mixRotate) * alpha; + constraint._mixX = data._mixX + (x - data._mixX) * alpha; + constraint._mixY = data._mixY + (y - data._mixY) * alpha; + } else { + constraint._mixRotate += (rotate - constraint._mixRotate) * alpha; + constraint._mixX += (x - constraint._mixX) * alpha; + constraint._mixY += (y - constraint._mixY) * alpha; + } +} + +void PathConstraintMixTimeline::setFrame(int frame, float time, float mixRotate, float mixX, float mixY) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + ROTATE] = mixRotate; + _frames[frame + X] = mixX; + _frames[frame + Y] = mixY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp new file mode 100644 index 0000000..8fea333 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -0,0 +1,91 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline1) + +PathConstraintPositionTimeline::PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, + int pathConstraintIndex) : CurveTimeline1(frameCount, + bezierCount), + _pathConstraintIndex( + pathConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_PathConstraintPosition << 32) | pathConstraintIndex}; + setPropertyIds(ids, 1); +} + +PathConstraintPositionTimeline::~PathConstraintPositionTimeline() { +} + +void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; + PathConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._position = constraint._data._position; + return; + case MixBlend_First: + constraint._position += (constraint._data._position - constraint._position) * alpha; + return; + default: + return; + } + } + + float position = getCurveValue(time); + + if (blend == MixBlend_Setup) + constraint._position = constraint._data._position + (position - constraint._data._position) * alpha; + else + constraint._position += (position - constraint._position) * alpha; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp new file mode 100644 index 0000000..d20b898 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -0,0 +1,88 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline) + +PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(size_t frameCount, size_t bezierCount, + int pathConstraintIndex) : CurveTimeline1(frameCount, + bezierCount), + _pathConstraintIndex( + pathConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_PathConstraintSpacing << 32) | pathConstraintIndex}; + setPropertyIds(ids, 1); +} + +void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; + PathConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._spacing = constraint._data._spacing; + return; + case MixBlend_First: + constraint._spacing += (constraint._data._spacing - constraint._spacing) * alpha; + return; + default: + return; + } + } + + float spacing = getCurveValue(time); + + if (blend == MixBlend_Setup) + constraint._spacing = constraint._data._spacing + (spacing - constraint._data._spacing) * alpha; + else + constraint._spacing += (spacing - constraint._spacing) * alpha; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp new file mode 100644 index 0000000..4493632 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp @@ -0,0 +1,94 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +#include + +using namespace spine; + +RTTI_IMPL(PointAttachment, Attachment) + +PointAttachment::PointAttachment(const String &name) : Attachment(name), _x(0), _y(0), _rotation(0), _color() { +} + +void PointAttachment::computeWorldPosition(Bone &bone, float &ox, float &oy) { + bone.localToWorld(_x, _y, ox, oy); +} + +float PointAttachment::computeWorldRotation(Bone &bone) { + float cos = MathUtil::cosDeg(_rotation); + float sin = MathUtil::sinDeg(_rotation); + float ix = cos * bone._a + sin * bone._b; + float iy = cos * bone._c + sin * bone._d; + + return MathUtil::atan2(iy, ix) * MathUtil::Rad_Deg; +} + +float PointAttachment::getX() { + return _x; +} + +void PointAttachment::setX(float inValue) { + _x = inValue; +} + +float PointAttachment::getY() { + return _y; +} + +void PointAttachment::setY(float inValue) { + _y = inValue; +} + +float PointAttachment::getRotation() { + return _rotation; +} + +void PointAttachment::setRotation(float inValue) { + _rotation = inValue; +} + +Color &PointAttachment::getColor() { + return _color; +} + +Attachment *PointAttachment::copy() { + PointAttachment *copy = new (__FILE__, __LINE__) PointAttachment(getName()); + copy->_x = _x; + copy->_y = _y; + copy->_rotation = _rotation; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/RTTI.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/RTTI.cpp new file mode 100644 index 0000000..4b91544 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/RTTI.cpp @@ -0,0 +1,60 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include + +using namespace spine; + +RTTI::RTTI(const char *className) : _className(className), _pBaseRTTI(NULL) { +} + +RTTI::RTTI(const char *className, const RTTI &baseRTTI) : _className(className), _pBaseRTTI(&baseRTTI) { +} + +const char *RTTI::getClassName() const { + return _className; +} + +bool RTTI::isExactly(const RTTI &rtti) const { + return !strcmp(this->_className, rtti._className); +} + +bool RTTI::instanceOf(const RTTI &rtti) const { + const RTTI *pCompare = this; + while (pCompare) { + if (!strcmp(pCompare->_className, rtti._className)) return true; + pCompare = pCompare->_pBaseRTTI; + } + return false; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp new file mode 100644 index 0000000..b7adab6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -0,0 +1,306 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +#include + +using namespace spine; + +RTTI_IMPL(RegionAttachment, Attachment) + +const int RegionAttachment::BLX = 0; +const int RegionAttachment::BLY = 1; +const int RegionAttachment::ULX = 2; +const int RegionAttachment::ULY = 3; +const int RegionAttachment::URX = 4; +const int RegionAttachment::URY = 5; +const int RegionAttachment::BRX = 6; +const int RegionAttachment::BRY = 7; + +RegionAttachment::RegionAttachment(const String &name) : Attachment(name), HasRendererObject(), + _x(0), + _y(0), + _rotation(0), + _scaleX(1), + _scaleY(1), + _width(0), + _height(0), + _regionOffsetX(0), + _regionOffsetY(0), + _regionWidth(0), + _regionHeight(0), + _regionOriginalWidth(0), + _regionOriginalHeight(0), + _path(), + _regionU(0), + _regionV(0), + _regionU2(0), + _regionV2(0), + _color(1, 1, 1, 1) { + _vertexOffset.setSize(NUM_UVS, 0); + _uvs.setSize(NUM_UVS, 0); +} + +void RegionAttachment::updateOffset() { + float regionScaleX = _width / _regionOriginalWidth * _scaleX; + float regionScaleY = _height / _regionOriginalHeight * _scaleY; + float localX = -_width / 2 * _scaleX + _regionOffsetX * regionScaleX; + float localY = -_height / 2 * _scaleY + _regionOffsetY * regionScaleY; + float localX2 = localX + _regionWidth * regionScaleX; + float localY2 = localY + _regionHeight * regionScaleY; + float cos = MathUtil::cosDeg(_rotation); + float sin = MathUtil::sinDeg(_rotation); + float localXCos = localX * cos + _x; + float localXSin = localX * sin; + float localYCos = localY * cos + _y; + float localYSin = localY * sin; + float localX2Cos = localX2 * cos + _x; + float localX2Sin = localX2 * sin; + float localY2Cos = localY2 * cos + _y; + float localY2Sin = localY2 * sin; + + _vertexOffset[BLX] = localXCos - localYSin; + _vertexOffset[BLY] = localYCos + localXSin; + _vertexOffset[ULX] = localXCos - localY2Sin; + _vertexOffset[ULY] = localY2Cos + localXSin; + _vertexOffset[URX] = localX2Cos - localY2Sin; + _vertexOffset[URY] = localY2Cos + localX2Sin; + _vertexOffset[BRX] = localX2Cos - localYSin; + _vertexOffset[BRY] = localYCos + localX2Sin; +} + +void RegionAttachment::setUVs(float u, float v, float u2, float v2, float degrees) { + if (degrees == 90) { + _uvs[URX] = u; + _uvs[URY] = v2; + _uvs[BRX] = u; + _uvs[BRY] = v; + _uvs[BLX] = u2; + _uvs[BLY] = v; + _uvs[ULX] = u2; + _uvs[ULY] = v2; + } else { + _uvs[ULX] = u; + _uvs[ULY] = v2; + _uvs[URX] = u; + _uvs[URY] = v; + _uvs[BRX] = u2; + _uvs[BRY] = v; + _uvs[BLX] = u2; + _uvs[BLY] = v2; + } +} + +void RegionAttachment::computeWorldVertices(Bone &bone, Vector &worldVertices, size_t offset, size_t stride) { + assert(worldVertices.size() >= (offset + 8)); + computeWorldVertices(bone, worldVertices.buffer(), offset, stride); +} + +void RegionAttachment::computeWorldVertices(Bone &bone, float *worldVertices, size_t offset, size_t stride) { + float x = bone.getWorldX(), y = bone.getWorldY(); + float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD(); + float offsetX, offsetY; + + offsetX = _vertexOffset[BRX]; + offsetY = _vertexOffset[BRY]; + worldVertices[offset] = offsetX * a + offsetY * b + x;// br + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = _vertexOffset[BLX]; + offsetY = _vertexOffset[BLY]; + worldVertices[offset] = offsetX * a + offsetY * b + x;// bl + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = _vertexOffset[ULX]; + offsetY = _vertexOffset[ULY]; + worldVertices[offset] = offsetX * a + offsetY * b + x;// ul + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = _vertexOffset[URX]; + offsetY = _vertexOffset[URY]; + worldVertices[offset] = offsetX * a + offsetY * b + x;// ur + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; +} + +float RegionAttachment::getX() { + return _x; +} + +void RegionAttachment::setX(float inValue) { + _x = inValue; +} + +float RegionAttachment::getY() { + return _y; +} + +void RegionAttachment::setY(float inValue) { + _y = inValue; +} + +float RegionAttachment::getRotation() { + return _rotation; +} + +void RegionAttachment::setRotation(float inValue) { + _rotation = inValue; +} + +float RegionAttachment::getScaleX() { + return _scaleX; +} + +void RegionAttachment::setScaleX(float inValue) { + _scaleX = inValue; +} + +float RegionAttachment::getScaleY() { + return _scaleY; +} + +void RegionAttachment::setScaleY(float inValue) { + _scaleY = inValue; +} + +float RegionAttachment::getWidth() { + return _width; +} + +void RegionAttachment::setWidth(float inValue) { + _width = inValue; +} + +float RegionAttachment::getHeight() { + return _height; +} + +void RegionAttachment::setHeight(float inValue) { + _height = inValue; +} + +const String &RegionAttachment::getPath() { + return _path; +} + +void RegionAttachment::setPath(const String &inValue) { + _path = inValue; +} + +float RegionAttachment::getRegionOffsetX() { + return _regionOffsetX; +} + +void RegionAttachment::setRegionOffsetX(float inValue) { + _regionOffsetX = inValue; +} + +float RegionAttachment::getRegionOffsetY() { + return _regionOffsetY; +} + +void RegionAttachment::setRegionOffsetY(float inValue) { + _regionOffsetY = inValue; +} + +float RegionAttachment::getRegionWidth() { + return _regionWidth; +} + +void RegionAttachment::setRegionWidth(float inValue) { + _regionWidth = inValue; +} + +float RegionAttachment::getRegionHeight() { + return _regionHeight; +} + +void RegionAttachment::setRegionHeight(float inValue) { + _regionHeight = inValue; +} + +float RegionAttachment::getRegionOriginalWidth() { + return _regionOriginalWidth; +} + +void RegionAttachment::setRegionOriginalWidth(float inValue) { + _regionOriginalWidth = inValue; +} + +float RegionAttachment::getRegionOriginalHeight() { + return _regionOriginalHeight; +} + +void RegionAttachment::setRegionOriginalHeight(float inValue) { + _regionOriginalHeight = inValue; +} + +Vector &RegionAttachment::getOffset() { + return _vertexOffset; +} + +Vector &RegionAttachment::getUVs() { + return _uvs; +} + +spine::Color &RegionAttachment::getColor() { + return _color; +} + +Attachment *RegionAttachment::copy() { + RegionAttachment *copy = new (__FILE__, __LINE__) RegionAttachment(getName()); + copy->_regionWidth = _regionWidth; + copy->_regionHeight = _regionHeight; + copy->_regionOffsetX = _regionOffsetX; + copy->_regionOffsetY = _regionOffsetY; + copy->_regionOriginalWidth = _regionOriginalWidth; + copy->_regionOriginalHeight = _regionOriginalHeight; + copy->setRendererObject(getRendererObject()); + copy->_path = _path; + copy->_x = _x; + copy->_y = _y; + copy->_scaleX = _scaleX; + copy->_scaleY = _scaleY; + copy->_rotation = _rotation; + copy->_width = _width; + copy->_height = _height; + copy->_uvs.clearAndAddAll(_uvs); + copy->_vertexOffset.clearAndAddAll(_vertexOffset); + copy->_color.set(_color); + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp new file mode 100644 index 0000000..a1b1805 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -0,0 +1,88 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(RotateTimeline, CurveTimeline1) + +RotateTimeline::RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_Rotate << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_rotation = bone->_data._rotation; + return; + case MixBlend_First: + bone->_rotation += (bone->_data._rotation - bone->_rotation) * alpha; + default: { + } + } + return; + } + + float r = getCurveValue(time); + switch (blend) { + case MixBlend_Setup: + bone->_rotation = bone->_data._rotation + r * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + r += bone->_data._rotation - bone->_rotation; + case MixBlend_Add: + bone->_rotation += r * alpha; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp new file mode 100644 index 0000000..6707311 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -0,0 +1,304 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(ScaleTimeline, CurveTimeline2) + +ScaleTimeline::ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ScaleX << 32) | boneIndex, + ((PropertyId) Property_ScaleY << 32) | boneIndex}; + setPropertyIds(ids, 2); +} + +ScaleTimeline::~ScaleTimeline() {} + +void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_scaleX = bone->_data._scaleX; + bone->_scaleY = bone->_data._scaleY; + return; + case MixBlend_First: + bone->_scaleX += (bone->_data._scaleX - bone->_scaleX) * alpha; + bone->_scaleY += (bone->_data._scaleY - bone->_scaleY) * alpha; + default: { + } + } + return; + } + + float x, y; + int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES); + int curveType = (int) _curves[i / CurveTimeline2::ENTRIES]; + switch (curveType) { + case CurveTimeline::LINEAR: { + float before = _frames[i]; + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before); + x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t; + y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t; + break; + } + case CurveTimeline::STEPPED: { + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + break; + } + default: { + x = getBezierValue(time, i, CurveTimeline2::VALUE1, curveType - CurveTimeline2::BEZIER); + y = getBezierValue(time, i, CurveTimeline2::VALUE2, + curveType + CurveTimeline2::BEZIER_SIZE - CurveTimeline2::BEZIER); + } + } + x *= bone->_data._scaleX; + y *= bone->_data._scaleY; + + if (alpha == 1) { + if (blend == MixBlend_Add) { + bone->_scaleX += x - bone->_data._scaleX; + bone->_scaleY += y - bone->_data._scaleY; + } else { + bone->_scaleX = x; + bone->_scaleY = y; + } + } else { + float bx, by; + if (direction == MixDirection_Out) { + switch (blend) { + case MixBlend_Setup: + bx = bone->_data._scaleX; + by = bone->_data._scaleY; + bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; + bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bx = bone->_scaleX; + by = bone->_scaleY; + bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; + bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; + break; + case MixBlend_Add: + bone->_scaleX += (x - bone->_data._scaleX) * alpha; + bone->_scaleY += (y - bone->_data._scaleY) * alpha; + } + } else { + switch (blend) { + case MixBlend_Setup: + bx = MathUtil::abs(bone->_data._scaleX) * MathUtil::sign(x); + by = MathUtil::abs(bone->_data._scaleY) * MathUtil::sign(y); + bone->_scaleX = bx + (x - bx) * alpha; + bone->_scaleY = by + (y - by) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bx = MathUtil::abs(bone->_scaleX) * MathUtil::sign(x); + by = MathUtil::abs(bone->_scaleY) * MathUtil::sign(y); + bone->_scaleX = bx + (x - bx) * alpha; + bone->_scaleY = by + (y - by) * alpha; + break; + case MixBlend_Add: + bone->_scaleX += (x - bone->_data._scaleX) * alpha; + bone->_scaleY += (y - bone->_data._scaleY) * alpha; + } + } + } +} + +RTTI_IMPL(ScaleXTimeline, CurveTimeline1) + +ScaleXTimeline::ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ScaleX << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +ScaleXTimeline::~ScaleXTimeline() {} + +void ScaleXTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_scaleX = bone->_data._scaleX; + return; + case MixBlend_First: + bone->_scaleX += (bone->_data._scaleX - bone->_scaleX) * alpha; + default: { + } + } + return; + } + + float x = getCurveValue(time) * bone->_data._scaleX; + if (alpha == 1) { + if (blend == MixBlend_Add) + bone->_scaleX += x - bone->_data._scaleX; + else + bone->_scaleX = x; + } else { + // Mixing out uses sign of setup or current pose, else use sign of key. + float bx; + if (direction == MixDirection_Out) { + switch (blend) { + case MixBlend_Setup: + bx = bone->_data._scaleX; + bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bx = bone->_scaleX; + bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; + break; + case MixBlend_Add: + bone->_scaleX += (x - bone->_data._scaleX) * alpha; + } + } else { + switch (blend) { + case MixBlend_Setup: + bx = MathUtil::abs(bone->_data._scaleX) * MathUtil::sign(x); + bone->_scaleX = bx + (x - bx) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bx = MathUtil::abs(bone->_scaleX) * MathUtil::sign(x); + bone->_scaleX = bx + (x - bx) * alpha; + break; + case MixBlend_Add: + bone->_scaleX += (x - bone->_data._scaleX) * alpha; + } + } + } +} + +RTTI_IMPL(ScaleYTimeline, CurveTimeline1) + +ScaleYTimeline::ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ScaleY << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +ScaleYTimeline::~ScaleYTimeline() {} + +void ScaleYTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_scaleY = bone->_data._scaleY; + return; + case MixBlend_First: + bone->_scaleY += (bone->_data._scaleY - bone->_scaleY) * alpha; + default: { + } + } + return; + } + + float y = getCurveValue(time) * bone->_data._scaleY; + if (alpha == 1) { + if (blend == MixBlend_Add) + bone->_scaleY += y - bone->_data._scaleY; + else + bone->_scaleY = y; + } else { + // Mixing out uses sign of setup or current pose, else use sign of key. + float by = 0; + if (direction == MixDirection_Out) { + switch (blend) { + case MixBlend_Setup: + by = bone->_data._scaleY; + bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + by = bone->_scaleY; + bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; + break; + case MixBlend_Add: + bone->_scaleY += (y - bone->_data._scaleY) * alpha; + } + } else { + switch (blend) { + case MixBlend_Setup: + by = MathUtil::abs(bone->_data._scaleY) * MathUtil::sign(y); + bone->_scaleY = by + (y - by) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + by = MathUtil::abs(bone->_scaleY) * MathUtil::sign(y); + bone->_scaleY = by + (y - by) * alpha; + break; + case MixBlend_Add: + bone->_scaleY += (y - bone->_data._scaleY) * alpha; + } + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp new file mode 100644 index 0000000..1c154a1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -0,0 +1,218 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(ShearTimeline, CurveTimeline2) + +ShearTimeline::ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ShearX << 32) | boneIndex, + ((PropertyId) Property_ShearY << 32) | boneIndex}; + setPropertyIds(ids, 2); +} + +ShearTimeline::~ShearTimeline() { +} + +void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_shearX = bone->_data._shearX; + bone->_shearY = bone->_data._shearY; + return; + case MixBlend_First: + bone->_shearX += (bone->_data._shearX - bone->_shearX) * alpha; + bone->_shearY += (bone->_data._shearY - bone->_shearY) * alpha; + default: { + } + } + return; + } + + float x, y; + int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES); + int curveType = (int) _curves[i / CurveTimeline2::ENTRIES]; + switch (curveType) { + case CurveTimeline2::LINEAR: { + float before = _frames[i]; + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before); + x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t; + y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t; + break; + } + case CurveTimeline2::STEPPED: { + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + break; + } + default: { + x = getBezierValue(time, i, CurveTimeline2::VALUE1, curveType - CurveTimeline2::BEZIER); + y = getBezierValue(time, i, CurveTimeline2::VALUE2, + curveType + CurveTimeline2::BEZIER_SIZE - CurveTimeline2::BEZIER); + } + } + + switch (blend) { + case MixBlend_Setup: + bone->_shearX = bone->_data._shearX + x * alpha; + bone->_shearY = bone->_data._shearY + y * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_shearX += (bone->_data._shearX + x - bone->_shearX) * alpha; + bone->_shearY += (bone->_data._shearY + y - bone->_shearY) * alpha; + break; + case MixBlend_Add: + bone->_shearX += x * alpha; + bone->_shearY += y * alpha; + } +} + +RTTI_IMPL(ShearXTimeline, CurveTimeline1) + +ShearXTimeline::ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ShearX << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +ShearXTimeline::~ShearXTimeline() { +} + +void ShearXTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_shearX = bone->_data._shearX; + return; + case MixBlend_First: + bone->_shearX += (bone->_data._shearX - bone->_shearX) * alpha; + default: { + } + } + return; + } + + float x = getCurveValue(time); + switch (blend) { + case MixBlend_Setup: + bone->_shearX = bone->_data._shearX + x * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_shearX += (bone->_data._shearX + x - bone->_shearX) * alpha; + break; + case MixBlend_Add: + bone->_shearX += x * alpha; + } +} + +RTTI_IMPL(ShearYTimeline, CurveTimeline1) + +ShearYTimeline::ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ShearX << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +ShearYTimeline::~ShearYTimeline() { +} + +void ShearYTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_shearY = bone->_data._shearY; + return; + case MixBlend_First: + bone->_shearY += (bone->_data._shearY - bone->_shearY) * alpha; + default: { + } + } + return; + } + + float y = getCurveValue(time); + switch (blend) { + case MixBlend_Setup: + bone->_shearY = bone->_data._shearY + y * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_shearY += (bone->_data._shearY + y - bone->_shearY) * alpha; + break; + case MixBlend_Add: + bone->_shearY += y * alpha; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Skeleton.cpp new file mode 100644 index 0000000..e634941 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -0,0 +1,702 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace spine; + +Skeleton::Skeleton(SkeletonData *skeletonData) : _data(skeletonData), + _skin(NULL), + _color(1, 1, 1, 1), + _time(0), + _scaleX(1), + _scaleY(1), + _x(0), + _y(0) { + _bones.ensureCapacity(_data->getBones().size()); + for (size_t i = 0; i < _data->getBones().size(); ++i) { + BoneData *data = _data->getBones()[i]; + + Bone *bone; + if (data->getParent() == NULL) { + bone = new (__FILE__, __LINE__) Bone(*data, *this, NULL); + } else { + Bone *parent = _bones[data->getParent()->getIndex()]; + bone = new (__FILE__, __LINE__) Bone(*data, *this, parent); + parent->getChildren().add(bone); + } + + _bones.add(bone); + } + + _slots.ensureCapacity(_data->getSlots().size()); + _drawOrder.ensureCapacity(_data->getSlots().size()); + for (size_t i = 0; i < _data->getSlots().size(); ++i) { + SlotData *data = _data->getSlots()[i]; + + Bone *bone = _bones[data->getBoneData().getIndex()]; + Slot *slot = new (__FILE__, __LINE__) Slot(*data, *bone); + + _slots.add(slot); + _drawOrder.add(slot); + } + + _ikConstraints.ensureCapacity(_data->getIkConstraints().size()); + for (size_t i = 0; i < _data->getIkConstraints().size(); ++i) { + IkConstraintData *data = _data->getIkConstraints()[i]; + + IkConstraint *constraint = new (__FILE__, __LINE__) IkConstraint(*data, *this); + + _ikConstraints.add(constraint); + } + + _transformConstraints.ensureCapacity(_data->getTransformConstraints().size()); + for (size_t i = 0; i < _data->getTransformConstraints().size(); ++i) { + TransformConstraintData *data = _data->getTransformConstraints()[i]; + + TransformConstraint *constraint = new (__FILE__, __LINE__) TransformConstraint(*data, *this); + + _transformConstraints.add(constraint); + } + + _pathConstraints.ensureCapacity(_data->getPathConstraints().size()); + for (size_t i = 0; i < _data->getPathConstraints().size(); ++i) { + PathConstraintData *data = _data->getPathConstraints()[i]; + + PathConstraint *constraint = new (__FILE__, __LINE__) PathConstraint(*data, *this); + + _pathConstraints.add(constraint); + } + + updateCache(); +} + +Skeleton::~Skeleton() { + ContainerUtil::cleanUpVectorOfPointers(_bones); + ContainerUtil::cleanUpVectorOfPointers(_slots); + ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); + ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); + ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); +} + +void Skeleton::updateCache() { + _updateCache.clear(); + + for (size_t i = 0, n = _bones.size(); i < n; ++i) { + Bone *bone = _bones[i]; + bone->_sorted = bone->_data.isSkinRequired(); + bone->_active = !bone->_sorted; + } + + if (_skin) { + Vector &skinBones = _skin->getBones(); + for (size_t i = 0, n = skinBones.size(); i < n; i++) { + Bone *bone = _bones[skinBones[i]->getIndex()]; + do { + bone->_sorted = false; + bone->_active = true; + bone = bone->_parent; + } while (bone); + } + } + + size_t ikCount = _ikConstraints.size(); + size_t transformCount = _transformConstraints.size(); + size_t pathCount = _pathConstraints.size(); + + size_t constraintCount = ikCount + transformCount + pathCount; + + size_t i = 0; +continue_outer: + for (; i < constraintCount; ++i) { + for (size_t ii = 0; ii < ikCount; ++ii) { + IkConstraint *constraint = _ikConstraints[ii]; + if (constraint->getData().getOrder() == i) { + sortIkConstraint(constraint); + i++; + goto continue_outer; + } + } + + for (size_t ii = 0; ii < transformCount; ++ii) { + TransformConstraint *constraint = _transformConstraints[ii]; + if (constraint->getData().getOrder() == i) { + sortTransformConstraint(constraint); + i++; + goto continue_outer; + } + } + + for (size_t ii = 0; ii < pathCount; ++ii) { + PathConstraint *constraint = _pathConstraints[ii]; + if (constraint->getData().getOrder() == i) { + sortPathConstraint(constraint); + i++; + goto continue_outer; + } + } + } + + size_t n = _bones.size(); + for (i = 0; i < n; ++i) { + sortBone(_bones[i]); + } +} + +void Skeleton::printUpdateCache() { + for (size_t i = 0; i < _updateCache.size(); i++) { + Updatable *updatable = _updateCache[i]; + if (updatable->getRTTI().isExactly(Bone::rtti)) { + printf("bone %s\n", ((Bone *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(TransformConstraint::rtti)) { + printf("transform constraint %s\n", ((TransformConstraint *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(IkConstraint::rtti)) { + printf("ik constraint %s\n", ((IkConstraint *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(PathConstraint::rtti)) { + printf("path constraint %s\n", ((PathConstraint *) updatable)->getData().getName().buffer()); + } + } +} + +void Skeleton::updateWorldTransform() { + for (size_t i = 0, n = _bones.size(); i < n; i++) { + Bone *bone = _bones[i]; + bone->_ax = bone->_x; + bone->_ay = bone->_y; + bone->_arotation = bone->_rotation; + bone->_ascaleX = bone->_scaleX; + bone->_ascaleY = bone->_scaleY; + bone->_ashearX = bone->_shearX; + bone->_ashearY = bone->_shearY; + } + + for (size_t i = 0, n = _updateCache.size(); i < n; ++i) { + _updateCache[i]->update(); + } +} + +void Skeleton::updateWorldTransform(Bone *parent) { + // Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection. + Bone &rootBone = *getRootBone(); + float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d; + rootBone._worldX = pa * _x + pb * _y + parent->_worldX; + rootBone._worldY = pc * _x + pd * _y + parent->_worldY; + + float rotationY = rootBone._rotation + 90 + rootBone._shearY; + float la = MathUtil::cosDeg(rootBone._rotation + rootBone._shearX) * rootBone._scaleX; + float lb = MathUtil::cosDeg(rotationY) * rootBone._scaleY; + float lc = MathUtil::sinDeg(rootBone._rotation + rootBone._shearX) * rootBone._scaleX; + float ld = MathUtil::sinDeg(rotationY) * rootBone._scaleY; + rootBone._a = (pa * la + pb * lc) * _scaleX; + rootBone._b = (pa * lb + pb * ld) * _scaleX; + rootBone._c = (pc * la + pd * lc) * _scaleY; + rootBone._d = (pc * lb + pd * ld) * _scaleY; + + // Update everything except root bone. + Bone *rb = getRootBone(); + for (size_t i = 0, n = _updateCache.size(); i < n; i++) { + Updatable *updatable = _updateCache[i]; + if (updatable != rb) updatable->update(); + } +} + +void Skeleton::setToSetupPose() { + setBonesToSetupPose(); + setSlotsToSetupPose(); +} + +void Skeleton::setBonesToSetupPose() { + for (size_t i = 0, n = _bones.size(); i < n; ++i) { + _bones[i]->setToSetupPose(); + } + + for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) { + IkConstraint *constraintP = _ikConstraints[i]; + IkConstraint &constraint = *constraintP; + + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + constraint._mix = constraint._data._mix; + constraint._softness = constraint._data._softness; + } + + for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) { + TransformConstraint *constraintP = _transformConstraints[i]; + TransformConstraint &constraint = *constraintP; + TransformConstraintData &constraintData = constraint._data; + + constraint._mixRotate = constraintData._mixRotate; + constraint._mixX = constraintData._mixX; + constraint._mixY = constraintData._mixY; + constraint._mixScaleX = constraintData._mixScaleX; + constraint._mixScaleY = constraintData._mixScaleY; + constraint._mixShearY = constraintData._mixShearY; + } + + for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) { + PathConstraint *constraintP = _pathConstraints[i]; + PathConstraint &constraint = *constraintP; + PathConstraintData &constraintData = constraint._data; + + constraint._position = constraintData._position; + constraint._spacing = constraintData._spacing; + constraint._mixRotate = constraintData._mixRotate; + constraint._mixX = constraintData._mixX; + constraint._mixY = constraintData._mixY; + } +} + +void Skeleton::setSlotsToSetupPose() { + _drawOrder.clear(); + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + _drawOrder.add(_slots[i]); + } + + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + _slots[i]->setToSetupPose(); + } +} + +Bone *Skeleton::findBone(const String &boneName) { + return ContainerUtil::findWithDataName(_bones, boneName); +} + +Slot *Skeleton::findSlot(const String &slotName) { + return ContainerUtil::findWithDataName(_slots, slotName); +} + +void Skeleton::setSkin(const String &skinName) { + Skin *foundSkin = skinName.isEmpty() ? NULL : _data->findSkin(skinName); + setSkin(foundSkin); +} + +void Skeleton::setSkin(Skin *newSkin) { + if (_skin == newSkin) return; + if (newSkin != NULL) { + if (_skin != NULL) { + Skeleton &thisRef = *this; + newSkin->attachAll(thisRef, *_skin); + } else { + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + Slot *slotP = _slots[i]; + Slot &slot = *slotP; + const String &name = slot._data.getAttachmentName(); + if (name.length() > 0) { + Attachment *attachment = newSkin->getAttachment(i, name); + if (attachment != NULL) { + slot.setAttachment(attachment); + } + } + } + } + } + + _skin = newSkin; + updateCache(); +} + +Attachment *Skeleton::getAttachment(const String &slotName, const String &attachmentName) { + return getAttachment(_data->findSlot(slotName)->getIndex(), attachmentName); +} + +Attachment *Skeleton::getAttachment(int slotIndex, const String &attachmentName) { + if (attachmentName.isEmpty()) return NULL; + + if (_skin != NULL) { + Attachment *attachment = _skin->getAttachment(slotIndex, attachmentName); + if (attachment != NULL) { + return attachment; + } + } + + return _data->getDefaultSkin() != NULL ? _data->getDefaultSkin()->getAttachment(slotIndex, attachmentName) : NULL; +} + +void Skeleton::setAttachment(const String &slotName, const String &attachmentName) { + assert(slotName.length() > 0); + + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + Slot *slot = _slots[i]; + if (slot->_data.getName() == slotName) { + Attachment *attachment = NULL; + if (attachmentName.length() > 0) { + attachment = getAttachment(i, attachmentName); + + assert(attachment != NULL); + } + + slot->setAttachment(attachment); + + return; + } + } + + printf("Slot not found: %s", slotName.buffer()); + + assert(false); +} + +IkConstraint *Skeleton::findIkConstraint(const String &constraintName) { + assert(constraintName.length() > 0); + + for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) { + IkConstraint *ikConstraint = _ikConstraints[i]; + if (ikConstraint->_data.getName() == constraintName) { + return ikConstraint; + } + } + return NULL; +} + +TransformConstraint *Skeleton::findTransformConstraint(const String &constraintName) { + assert(constraintName.length() > 0); + + for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) { + TransformConstraint *transformConstraint = _transformConstraints[i]; + if (transformConstraint->_data.getName() == constraintName) { + return transformConstraint; + } + } + + return NULL; +} + +PathConstraint *Skeleton::findPathConstraint(const String &constraintName) { + assert(constraintName.length() > 0); + + for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) { + PathConstraint *constraint = _pathConstraints[i]; + if (constraint->_data.getName() == constraintName) { + return constraint; + } + } + + return NULL; +} + +void Skeleton::update(float delta) { + _time += delta; +} + +void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector &outVertexBuffer) { + float minX = FLT_MAX; + float minY = FLT_MAX; + float maxX = FLT_MIN; + float maxY = FLT_MIN; + + for (size_t i = 0; i < _drawOrder.size(); ++i) { + Slot *slot = _drawOrder[i]; + if (!slot->_bone._active) continue; + size_t verticesLength = 0; + Attachment *attachment = slot->getAttachment(); + + if (attachment != NULL && attachment->getRTTI().instanceOf(RegionAttachment::rtti)) { + RegionAttachment *regionAttachment = static_cast(attachment); + + verticesLength = 8; + if (outVertexBuffer.size() < 8) { + outVertexBuffer.setSize(8, 0); + } + regionAttachment->computeWorldVertices(slot->getBone(), outVertexBuffer, 0); + } else if (attachment != NULL && attachment->getRTTI().instanceOf(MeshAttachment::rtti)) { + MeshAttachment *mesh = static_cast(attachment); + + verticesLength = mesh->getWorldVerticesLength(); + if (outVertexBuffer.size() < verticesLength) { + outVertexBuffer.setSize(verticesLength, 0); + } + + mesh->computeWorldVertices(*slot, 0, verticesLength, outVertexBuffer, 0); + } + + for (size_t ii = 0; ii < verticesLength; ii += 2) { + float vx = outVertexBuffer[ii]; + float vy = outVertexBuffer[ii + 1]; + + minX = MathUtil::min(minX, vx); + minY = MathUtil::min(minY, vy); + maxX = MathUtil::max(maxX, vx); + maxY = MathUtil::max(maxY, vy); + } + } + + outX = minX; + outY = minY; + outWidth = maxX - minX; + outHeight = maxY - minY; +} + +Bone *Skeleton::getRootBone() { + return _bones.size() == 0 ? NULL : _bones[0]; +} + +SkeletonData *Skeleton::getData() { + return _data; +} + +Vector &Skeleton::getBones() { + return _bones; +} + +Vector &Skeleton::getUpdateCacheList() { + return _updateCache; +} + +Vector &Skeleton::getSlots() { + return _slots; +} + +Vector &Skeleton::getDrawOrder() { + return _drawOrder; +} + +Vector &Skeleton::getIkConstraints() { + return _ikConstraints; +} + +Vector &Skeleton::getPathConstraints() { + return _pathConstraints; +} + +Vector &Skeleton::getTransformConstraints() { + return _transformConstraints; +} + +Skin *Skeleton::getSkin() { + return _skin; +} + +Color &Skeleton::getColor() { + return _color; +} + +float Skeleton::getTime() { + return _time; +} + +void Skeleton::setTime(float inValue) { + _time = inValue; +} + +void Skeleton::setPosition(float x, float y) { + _x = x; + _y = y; +} + +float Skeleton::getX() { + return _x; +} + +void Skeleton::setX(float inValue) { + _x = inValue; +} + +float Skeleton::getY() { + return _y; +} + +void Skeleton::setY(float inValue) { + _y = inValue; +} + +float Skeleton::getScaleX() { + return _scaleX; +} + +void Skeleton::setScaleX(float inValue) { + _scaleX = inValue; +} + +float Skeleton::getScaleY() { + return _scaleY * (Bone::isYDown() ? -1 : 1); +} + +void Skeleton::setScaleY(float inValue) { + _scaleY = inValue; +} + +void Skeleton::sortIkConstraint(IkConstraint *constraint) { + constraint->_active = constraint->_target->_active && (!constraint->_data.isSkinRequired() || + (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) return; + + Bone *target = constraint->getTarget(); + sortBone(target); + + Vector &constrained = constraint->getBones(); + Bone *parent = constrained[0]; + sortBone(parent); + + if (constrained.size() == 1) { + _updateCache.add(constraint); + sortReset(parent->_children); + } else { + Bone *child = constrained[constrained.size() - 1]; + sortBone(child); + + _updateCache.add(constraint); + + sortReset(parent->_children); + child->_sorted = true; + } +} + +void Skeleton::sortPathConstraint(PathConstraint *constraint) { + constraint->_active = constraint->_target->_bone._active && (!constraint->_data.isSkinRequired() || (_skin && + _skin->_constraints.contains( + &constraint->_data))); + if (!constraint->_active) return; + + Slot *slot = constraint->getTarget(); + int slotIndex = slot->getData().getIndex(); + Bone &slotBone = slot->getBone(); + if (_skin != NULL) sortPathConstraintAttachment(_skin, slotIndex, slotBone); + if (_data->_defaultSkin != NULL && _data->_defaultSkin != _skin) + sortPathConstraintAttachment(_data->_defaultSkin, slotIndex, slotBone); + for (size_t ii = 0, nn = _data->_skins.size(); ii < nn; ii++) + sortPathConstraintAttachment(_data->_skins[ii], slotIndex, slotBone); + + Attachment *attachment = slot->getAttachment(); + if (attachment != NULL && attachment->getRTTI().instanceOf(PathAttachment::rtti)) + sortPathConstraintAttachment(attachment, slotBone); + + Vector &constrained = constraint->getBones(); + size_t boneCount = constrained.size(); + for (size_t i = 0; i < boneCount; ++i) { + sortBone(constrained[i]); + } + + _updateCache.add(constraint); + + for (size_t i = 0; i < boneCount; i++) + sortReset(constrained[i]->getChildren()); + for (size_t i = 0; i < boneCount; i++) + constrained[i]->_sorted = true; +} + +void Skeleton::sortTransformConstraint(TransformConstraint *constraint) { + constraint->_active = constraint->_target->_active && (!constraint->_data.isSkinRequired() || + (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) return; + + sortBone(constraint->getTarget()); + + Vector &constrained = constraint->getBones(); + size_t boneCount = constrained.size(); + if (constraint->_data.isLocal()) { + for (size_t i = 0; i < boneCount; i++) { + Bone *child = constrained[i]; + sortBone(child->getParent()); + sortBone(child); + } + } else { + for (size_t i = 0; i < boneCount; ++i) { + sortBone(constrained[i]); + } + } + + _updateCache.add(constraint); + + for (size_t i = 0; i < boneCount; ++i) + sortReset(constrained[i]->getChildren()); + for (size_t i = 0; i < boneCount; ++i) + constrained[i]->_sorted = true; +} + +void Skeleton::sortPathConstraintAttachment(Skin *skin, size_t slotIndex, Bone &slotBone) { + Skin::AttachmentMap::Entries attachments = skin->getAttachments(); + + while (attachments.hasNext()) { + Skin::AttachmentMap::Entry entry = attachments.next(); + if (entry._slotIndex == slotIndex) { + Attachment *value = entry._attachment; + sortPathConstraintAttachment(value, slotBone); + } + } +} + +void Skeleton::sortPathConstraintAttachment(Attachment *attachment, Bone &slotBone) { + if (attachment == NULL || !attachment->getRTTI().instanceOf(PathAttachment::rtti)) return; + Vector &pathBones = static_cast(attachment)->getBones(); + if (pathBones.size() == 0) + sortBone(&slotBone); + else { + for (size_t i = 0, n = pathBones.size(); i < n;) { + size_t nn = pathBones[i++]; + nn += i; + while (i < nn) { + sortBone(_bones[pathBones[i++]]); + } + } + } +} + +void Skeleton::sortBone(Bone *bone) { + if (bone->_sorted) return; + Bone *parent = bone->_parent; + if (parent != NULL) sortBone(parent); + bone->_sorted = true; + _updateCache.add(bone); +} + +void Skeleton::sortReset(Vector &bones) { + for (size_t i = 0, n = bones.size(); i < n; ++i) { + Bone *bone = bones[i]; + if (!bone->_active) continue; + if (bone->_sorted) sortReset(bone->getChildren()); + bone->_sorted = false; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp new file mode 100644 index 0000000..f484ea0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -0,0 +1,1318 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +SkeletonBinary::SkeletonBinary(Atlas *atlasArray) : _attachmentLoader( + new (__FILE__, __LINE__) AtlasAttachmentLoader(atlasArray)), + _error(), _scale(1), _ownsLoader(true) { +} + +SkeletonBinary::SkeletonBinary(AttachmentLoader *attachmentLoader, bool ownsLoader) : _attachmentLoader( + attachmentLoader), + _error(), + _scale(1), + _ownsLoader(ownsLoader) { + assert(_attachmentLoader != NULL); +} + +SkeletonBinary::~SkeletonBinary() { + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + if (_ownsLoader) delete _attachmentLoader; +} + +SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, const int length) { + bool nonessential; + SkeletonData *skeletonData; + + DataInput *input = new (__FILE__, __LINE__) DataInput(); + input->cursor = binary; + input->end = binary + length; + + _linkedMeshes.clear(); + + skeletonData = new (__FILE__, __LINE__) SkeletonData(); + + char buffer[16] = {0}; + int lowHash = readInt(input); + int hightHash = readInt(input); + String hashString; + sprintf(buffer, "%x", hightHash); + hashString.append(buffer); + sprintf(buffer, "%x", lowHash); + hashString.append(buffer); + skeletonData->_hash = hashString; + + char *skeletonDataVersion = readString(input); + skeletonData->_version.own(skeletonDataVersion); + + skeletonData->_x = readFloat(input); + skeletonData->_y = readFloat(input); + skeletonData->_width = readFloat(input); + skeletonData->_height = readFloat(input); + + nonessential = readBoolean(input); + + if (nonessential) { + skeletonData->_fps = readFloat(input); + skeletonData->_imagesPath.own(readString(input)); + skeletonData->_audioPath.own(readString(input)); + } + + int numStrings = readVarint(input, true); + for (int i = 0; i < numStrings; i++) + skeletonData->_strings.add(readString(input)); + + /* Bones. */ + int numBones = readVarint(input, true); + skeletonData->_bones.setSize(numBones, 0); + for (int i = 0; i < numBones; ++i) { + const char *name = readString(input); + BoneData *parent = i == 0 ? 0 : skeletonData->_bones[readVarint(input, true)]; + BoneData *data = new (__FILE__, __LINE__) BoneData(i, String(name, true), parent); + data->_rotation = readFloat(input); + data->_x = readFloat(input) * _scale; + data->_y = readFloat(input) * _scale; + data->_scaleX = readFloat(input); + data->_scaleY = readFloat(input); + data->_shearX = readFloat(input); + data->_shearY = readFloat(input); + data->_length = readFloat(input) * _scale; + data->_transformMode = static_cast(readVarint(input, true)); + data->_skinRequired = readBoolean(input); + if (nonessential) { + readColor(input, data->getColor()); + } + skeletonData->_bones[i] = data; + } + + /* Slots. */ + int slotsCount = readVarint(input, true); + skeletonData->_slots.setSize(slotsCount, 0); + for (int i = 0; i < slotsCount; ++i) { + const char *slotName = readString(input); + BoneData *boneData = skeletonData->_bones[readVarint(input, true)]; + SlotData *slotData = new (__FILE__, __LINE__) SlotData(i, String(slotName, true), *boneData); + + readColor(input, slotData->getColor()); + unsigned char a = readByte(input); + unsigned char r = readByte(input); + unsigned char g = readByte(input); + unsigned char b = readByte(input); + if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) { + slotData->getDarkColor().set(r / 255.0f, g / 255.0f, b / 255.0f, 1); + slotData->setHasDarkColor(true); + } + slotData->_attachmentName = readStringRef(input, skeletonData); + slotData->_blendMode = static_cast(readVarint(input, true)); + skeletonData->_slots[i] = slotData; + } + + /* IK constraints. */ + int ikConstraintsCount = readVarint(input, true); + skeletonData->_ikConstraints.setSize(ikConstraintsCount, 0); + for (int i = 0; i < ikConstraintsCount; ++i) { + const char *name = readString(input); + IkConstraintData *data = new (__FILE__, __LINE__) IkConstraintData(String(name, true)); + data->setOrder(readVarint(input, true)); + data->setSkinRequired(readBoolean(input)); + int bonesCount = readVarint(input, true); + data->_bones.setSize(bonesCount, 0); + for (int ii = 0; ii < bonesCount; ++ii) + data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; + data->_target = skeletonData->_bones[readVarint(input, true)]; + data->_mix = readFloat(input); + data->_softness = readFloat(input) * _scale; + data->_bendDirection = readSByte(input); + data->_compress = readBoolean(input); + data->_stretch = readBoolean(input); + data->_uniform = readBoolean(input); + skeletonData->_ikConstraints[i] = data; + } + + /* Transform constraints. */ + int transformConstraintsCount = readVarint(input, true); + skeletonData->_transformConstraints.setSize(transformConstraintsCount, 0); + for (int i = 0; i < transformConstraintsCount; ++i) { + const char *name = readString(input); + TransformConstraintData *data = new (__FILE__, __LINE__) TransformConstraintData(String(name, true)); + data->setOrder(readVarint(input, true)); + data->setSkinRequired(readBoolean(input)); + int bonesCount = readVarint(input, true); + data->_bones.setSize(bonesCount, 0); + for (int ii = 0; ii < bonesCount; ++ii) + data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; + data->_target = skeletonData->_bones[readVarint(input, true)]; + data->_local = readBoolean(input); + data->_relative = readBoolean(input); + data->_offsetRotation = readFloat(input); + data->_offsetX = readFloat(input) * _scale; + data->_offsetY = readFloat(input) * _scale; + data->_offsetScaleX = readFloat(input); + data->_offsetScaleY = readFloat(input); + data->_offsetShearY = readFloat(input); + data->_mixRotate = readFloat(input); + data->_mixX = readFloat(input); + data->_mixY = readFloat(input); + data->_mixScaleX = readFloat(input); + data->_mixScaleY = readFloat(input); + data->_mixShearY = readFloat(input); + skeletonData->_transformConstraints[i] = data; + } + + /* Path constraints */ + int pathConstraintsCount = readVarint(input, true); + skeletonData->_pathConstraints.setSize(pathConstraintsCount, 0); + for (int i = 0; i < pathConstraintsCount; ++i) { + const char *name = readString(input); + PathConstraintData *data = new (__FILE__, __LINE__) PathConstraintData(String(name, true)); + data->setOrder(readVarint(input, true)); + data->setSkinRequired(readBoolean(input)); + int bonesCount = readVarint(input, true); + data->_bones.setSize(bonesCount, 0); + for (int ii = 0; ii < bonesCount; ++ii) + data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; + data->_target = skeletonData->_slots[readVarint(input, true)]; + data->_positionMode = static_cast(readVarint(input, true)); + data->_spacingMode = static_cast(readVarint(input, true)); + data->_rotateMode = static_cast(readVarint(input, true)); + data->_offsetRotation = readFloat(input); + data->_position = readFloat(input); + if (data->_positionMode == PositionMode_Fixed) data->_position *= _scale; + data->_spacing = readFloat(input); + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) + data->_spacing *= _scale; + data->_mixRotate = readFloat(input); + data->_mixX = readFloat(input); + data->_mixY = readFloat(input); + skeletonData->_pathConstraints[i] = data; + } + + /* Default skin. */ + Skin *defaultSkin = readSkin(input, true, skeletonData, nonessential); + if (defaultSkin) { + skeletonData->_defaultSkin = defaultSkin; + skeletonData->_skins.add(defaultSkin); + } + + /* Skins. */ + for (size_t i = 0, n = (size_t) readVarint(input, true); i < n; ++i) { + Skin *skin = readSkin(input, false, skeletonData, nonessential); + if (skin) + skeletonData->_skins.add(skin); + else { + delete input; + delete skeletonData; + return NULL; + } + } + + /* Linked meshes. */ + for (int i = 0, n = _linkedMeshes.size(); i < n; ++i) { + LinkedMesh *linkedMesh = _linkedMeshes[i]; + Skin *skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin(linkedMesh->_skin); + if (skin == NULL) { + delete input; + delete skeletonData; + setError("Skin not found: ", linkedMesh->_skin.buffer()); + return NULL; + } + Attachment *parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); + if (parent == NULL) { + delete input; + delete skeletonData; + setError("Parent mesh not found: ", linkedMesh->_parent.buffer()); + return NULL; + } + linkedMesh->_mesh->_deformAttachment = linkedMesh->_inheritDeform ? static_cast(parent) + : linkedMesh->_mesh; + linkedMesh->_mesh->setParentMesh(static_cast(parent)); + linkedMesh->_mesh->updateUVs(); + _attachmentLoader->configureAttachment(linkedMesh->_mesh); + } + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + /* Events. */ + int eventsCount = readVarint(input, true); + skeletonData->_events.setSize(eventsCount, 0); + for (int i = 0; i < eventsCount; ++i) { + const char *name = readStringRef(input, skeletonData); + EventData *eventData = new (__FILE__, __LINE__) EventData(String(name)); + eventData->_intValue = readVarint(input, false); + eventData->_floatValue = readFloat(input); + eventData->_stringValue.own(readString(input)); + eventData->_audioPath.own(readString(input)); + if (!eventData->_audioPath.isEmpty()) { + eventData->_volume = readFloat(input); + eventData->_balance = readFloat(input); + } + skeletonData->_events[i] = eventData; + } + + /* Animations. */ + int animationsCount = readVarint(input, true); + skeletonData->_animations.setSize(animationsCount, 0); + for (int i = 0; i < animationsCount; ++i) { + String name(readString(input), true); + Animation *animation = readAnimation(name, input, skeletonData); + if (!animation) { + delete input; + delete skeletonData; + return NULL; + } + skeletonData->_animations[i] = animation; + } + + delete input; + return skeletonData; +} + +SkeletonData *SkeletonBinary::readSkeletonDataFile(const String &path) { + int length; + SkeletonData *skeletonData; + const char *binary = SpineExtension::readFile(path.buffer(), &length); + if (length == 0 || !binary) { + setError("Unable to read skeleton file: ", path.buffer()); + return NULL; + } + skeletonData = readSkeletonData((unsigned char *) binary, length); + SpineExtension::free(binary, __FILE__, __LINE__); + return skeletonData; +} + +void SkeletonBinary::setError(const char *value1, const char *value2) { + char message[256]; + int length; + strcpy(message, value1); + length = (int) strlen(value1); + if (value2) strncat(message + length, value2, 255 - length); + _error = String(message); +} + +char *SkeletonBinary::readString(DataInput *input) { + int length = readVarint(input, true); + char *string; + if (length == 0) return NULL; + string = SpineExtension::alloc(length, __FILE__, __LINE__); + memcpy(string, input->cursor, length - 1); + input->cursor += length - 1; + string[length - 1] = '\0'; + return string; +} + +char *SkeletonBinary::readStringRef(DataInput *input, SkeletonData *skeletonData) { + int index = readVarint(input, true); + return index == 0 ? NULL : skeletonData->_strings[index - 1]; +} + +float SkeletonBinary::readFloat(DataInput *input) { + union { + int intValue; + float floatValue; + } intToFloat; + intToFloat.intValue = readInt(input); + return intToFloat.floatValue; +} + +unsigned char SkeletonBinary::readByte(DataInput *input) { + return *input->cursor++; +} + +signed char SkeletonBinary::readSByte(DataInput *input) { + return (signed char) readByte(input); +} + +bool SkeletonBinary::readBoolean(DataInput *input) { + return readByte(input) != 0; +} + +int SkeletonBinary::readInt(DataInput *input) { + int result = readByte(input); + result <<= 8; + result |= readByte(input); + result <<= 8; + result |= readByte(input); + result <<= 8; + result |= readByte(input); + return result; +} + +void SkeletonBinary::readColor(DataInput *input, Color &color) { + color.r = readByte(input) / 255.0f; + color.g = readByte(input) / 255.0f; + color.b = readByte(input) / 255.0f; + color.a = readByte(input) / 255.0f; +} + +int SkeletonBinary::readVarint(DataInput *input, bool optimizePositive) { + unsigned char b = readByte(input); + int value = b & 0x7F; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 7; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 14; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 21; + if (b & 0x80) value |= (readByte(input) & 0x7F) << 28; + } + } + } + if (!optimizePositive) value = (((unsigned int) value >> 1) ^ -(value & 1)); + return value; +} + +Skin *SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential) { + Skin *skin; + int slotCount = 0; + if (defaultSkin) { + slotCount = readVarint(input, true); + if (slotCount == 0) return NULL; + skin = new (__FILE__, __LINE__) Skin("default"); + } else { + skin = new (__FILE__, __LINE__) Skin(readStringRef(input, skeletonData)); + for (int i = 0, n = readVarint(input, true); i < n; i++) + skin->getBones().add(skeletonData->_bones[readVarint(input, true)]); + + for (int i = 0, n = readVarint(input, true); i < n; i++) + skin->getConstraints().add(skeletonData->_ikConstraints[readVarint(input, true)]); + + for (int i = 0, n = readVarint(input, true); i < n; i++) + skin->getConstraints().add(skeletonData->_transformConstraints[readVarint(input, true)]); + + for (int i = 0, n = readVarint(input, true); i < n; i++) + skin->getConstraints().add(skeletonData->_pathConstraints[readVarint(input, true)]); + slotCount = readVarint(input, true); + } + + for (int i = 0; i < slotCount; ++i) { + int slotIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + String name(readStringRef(input, skeletonData)); + Attachment *attachment = readAttachment(input, skin, slotIndex, name, skeletonData, nonessential); + if (attachment) + skin->setAttachment(slotIndex, String(name), attachment); + else { + delete skin; + return nullptr; + } + } + } + return skin; +} + +Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName, + SkeletonData *skeletonData, bool nonessential) { + String name(readStringRef(input, skeletonData)); + if (name.isEmpty()) name = attachmentName; + + AttachmentType type = static_cast(readByte(input)); + switch (type) { + case AttachmentType_Region: { + String path(readStringRef(input, skeletonData)); + if (path.isEmpty()) path = name; + RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path)); + if (!region) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + region->_path = path; + region->_rotation = readFloat(input); + region->_x = readFloat(input) * _scale; + region->_y = readFloat(input) * _scale; + region->_scaleX = readFloat(input); + region->_scaleY = readFloat(input); + region->_width = readFloat(input) * _scale; + region->_height = readFloat(input) * _scale; + readColor(input, region->getColor()); + region->updateOffset(); + _attachmentLoader->configureAttachment(region); + return region; + } + case AttachmentType_Boundingbox: { + int vertexCount = readVarint(input, true); + BoundingBoxAttachment *box = _attachmentLoader->newBoundingBoxAttachment(*skin, String(name)); + if (!box) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + readVertices(input, static_cast(box), vertexCount); + if (nonessential) { + readColor(input, box->getColor()); + } + _attachmentLoader->configureAttachment(box); + return box; + } + case AttachmentType_Mesh: { + int vertexCount; + MeshAttachment *mesh; + String path(readStringRef(input, skeletonData)); + if (path.isEmpty()) path = name; + + mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path)); + if (!mesh) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + mesh->_path = path; + readColor(input, mesh->getColor()); + vertexCount = readVarint(input, true); + readFloatArray(input, vertexCount << 1, 1, mesh->getRegionUVs()); + readShortArray(input, mesh->getTriangles()); + readVertices(input, static_cast(mesh), vertexCount); + mesh->updateUVs(); + mesh->_hullLength = readVarint(input, true) << 1; + if (nonessential) { + readShortArray(input, mesh->getEdges()); + mesh->_width = readFloat(input) * _scale; + mesh->_height = readFloat(input) * _scale; + } else { + mesh->_width = 0; + mesh->_height = 0; + } + _attachmentLoader->configureAttachment(mesh); + return mesh; + } + case AttachmentType_Linkedmesh: { + String path(readStringRef(input, skeletonData)); + if (path.isEmpty()) path = name; + + MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path)); + if (!mesh) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + mesh->_path = path; + readColor(input, mesh->getColor()); + String skinName(readStringRef(input, skeletonData)); + String parent(readStringRef(input, skeletonData)); + bool inheritDeform = readBoolean(input); + if (nonessential) { + mesh->_width = readFloat(input) * _scale; + mesh->_height = readFloat(input) * _scale; + } + + LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, String(skinName), slotIndex, + String(parent), inheritDeform); + _linkedMeshes.add(linkedMesh); + return mesh; + } + case AttachmentType_Path: { + PathAttachment *path = _attachmentLoader->newPathAttachment(*skin, String(name)); + if (!path) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + path->_closed = readBoolean(input); + path->_constantSpeed = readBoolean(input); + int vertexCount = readVarint(input, true); + readVertices(input, static_cast(path), vertexCount); + int lengthsLength = vertexCount / 3; + path->_lengths.setSize(lengthsLength, 0); + for (int i = 0; i < lengthsLength; ++i) { + path->_lengths[i] = readFloat(input) * _scale; + } + if (nonessential) { + readColor(input, path->getColor()); + } + _attachmentLoader->configureAttachment(path); + return path; + } + case AttachmentType_Point: { + PointAttachment *point = _attachmentLoader->newPointAttachment(*skin, String(name)); + if (!point) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + point->_rotation = readFloat(input); + point->_x = readFloat(input) * _scale; + point->_y = readFloat(input) * _scale; + + if (nonessential) { + readColor(input, point->getColor()); + } + _attachmentLoader->configureAttachment(point); + return point; + } + case AttachmentType_Clipping: { + int endSlotIndex = readVarint(input, true); + int vertexCount = readVarint(input, true); + ClippingAttachment *clip = _attachmentLoader->newClippingAttachment(*skin, name); + if (!clip) { + setError("Error reading attachment: ", name.buffer()); + return nullptr; + } + readVertices(input, static_cast(clip), vertexCount); + clip->_endSlot = skeletonData->_slots[endSlotIndex]; + if (nonessential) { + readColor(input, clip->getColor()); + } + _attachmentLoader->configureAttachment(clip); + return clip; + } + } + return nullptr; +} + +void SkeletonBinary::readVertices(DataInput *input, VertexAttachment *attachment, int vertexCount) { + float scale = _scale; + int verticesLength = vertexCount << 1; + attachment->setWorldVerticesLength(vertexCount << 1); + + if (!readBoolean(input)) { + readFloatArray(input, verticesLength, scale, attachment->getVertices()); + return; + } + + Vector &vertices = attachment->getVertices(); + Vector &bones = attachment->getBones(); + vertices.ensureCapacity(verticesLength * 3 * 3); + bones.ensureCapacity(verticesLength * 3); + + for (int i = 0; i < vertexCount; ++i) { + int boneCount = readVarint(input, true); + bones.add(boneCount); + for (int ii = 0; ii < boneCount; ++ii) { + bones.add(readVarint(input, true)); + vertices.add(readFloat(input) * scale); + vertices.add(readFloat(input) * scale); + vertices.add(readFloat(input)); + } + } +} + +void SkeletonBinary::readFloatArray(DataInput *input, int n, float scale, Vector &array) { + array.setSize(n, 0); + + int i; + if (scale == 1) { + for (i = 0; i < n; ++i) { + array[i] = readFloat(input); + } + } else { + for (i = 0; i < n; ++i) { + array[i] = readFloat(input) * scale; + } + } +} + +void SkeletonBinary::readShortArray(DataInput *input, Vector &array) { + int n = readVarint(input, true); + array.setSize(n, 0); + + int i; + for (i = 0; i < n; ++i) { + array[i] = readByte(input) << 8; + array[i] |= readByte(input); + } +} + +void SkeletonBinary::setBezier(DataInput *input, CurveTimeline *timeline, int bezier, int frame, int value, float time1, + float time2, + float value1, float value2, float scale) { + float cx1 = readFloat(input); + float cy1 = readFloat(input); + float cx2 = readFloat(input); + float cy2 = readFloat(input); + timeline->setBezier(bezier, frame, value, time1, value1, cx1, cy1 * scale, cx2, cy2 * scale, time2, value2); +} + +Timeline *SkeletonBinary::readTimeline(DataInput *input, CurveTimeline1 *timeline, float scale) { + float time = readFloat(input); + float value = readFloat(input) * scale; + for (int frame = 0, bezier = 0, frameLast = timeline->getFrameCount() - 1;; frame++) { + timeline->setFrame(frame, time, value); + if (frame == frameLast) break; + float time2 = readFloat(input); + float value2 = readFloat(input) * scale; + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale); + } + time = time2; + value = value2; + } + return timeline; +} + +Timeline *SkeletonBinary::readTimeline2(DataInput *input, CurveTimeline2 *timeline, float scale) { + float time = readFloat(input); + float value1 = readFloat(input) * scale; + float value2 = readFloat(input) * scale; + for (int frame = 0, bezier = 0, frameLast = timeline->getFrameCount() - 1;; frame++) { + timeline->setFrame(frame, time, value1, value2); + if (frame == frameLast) break; + float time2 = readFloat(input); + float nvalue1 = readFloat(input) * scale; + float nvalue2 = readFloat(input) * scale; + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale); + setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + } + return timeline; +} + +Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, SkeletonData *skeletonData) { + Vector timelines; + float scale = _scale; + int numTimelines = readVarint(input, true); + SP_UNUSED(numTimelines); + // Slot timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int slotIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + unsigned char timelineType = readByte(input); + int frameCount = readVarint(input, true); + int frameLast = frameCount - 1; + switch (timelineType) { + case SLOT_ATTACHMENT: { + AttachmentTimeline *timeline = new (__FILE__, __LINE__) AttachmentTimeline(frameCount, slotIndex); + for (int frame = 0; frame < frameCount; ++frame) { + float time = readFloat(input); + String attachmentName(readStringRef(input, skeletonData)); + timeline->setFrame(frame, time, attachmentName); + } + timelines.add(timeline); + break; + } + case SLOT_RGBA: { + int bezierCount = readVarint(input, true); + RGBATimeline *timeline = new (__FILE__, __LINE__) RGBATimeline(frameCount, bezierCount, slotIndex); + + float time = readFloat(input); + float r = readByte(input) / 255.0; + float g = readByte(input) / 255.0; + float b = readByte(input) / 255.0; + float a = readByte(input) / 255.0; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b, a); + if (frame == frameLast) break; + + float time2 = readFloat(input); + float r2 = readByte(input) / 255.0; + float g2 = readByte(input) / 255.0; + float b2 = readByte(input) / 255.0; + float a2 = readByte(input) / 255.0; + + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + a = a2; + } + timelines.add(timeline); + break; + } + case SLOT_RGB: { + int bezierCount = readVarint(input, true); + RGBTimeline *timeline = new (__FILE__, __LINE__) RGBTimeline(frameCount, bezierCount, slotIndex); + + float time = readFloat(input); + float r = readByte(input) / 255.0; + float g = readByte(input) / 255.0; + float b = readByte(input) / 255.0; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b); + if (frame == frameLast) break; + + float time2 = readFloat(input); + float r2 = readByte(input) / 255.0; + float g2 = readByte(input) / 255.0; + float b2 = readByte(input) / 255.0; + + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + } + timelines.add(timeline); + break; + } + case SLOT_RGBA2: { + int bezierCount = readVarint(input, true); + RGBA2Timeline *timeline = new (__FILE__, __LINE__) RGBA2Timeline(frameCount, bezierCount, slotIndex); + + float time = readFloat(input); + float r = readByte(input) / 255.0; + float g = readByte(input) / 255.0; + float b = readByte(input) / 255.0; + float a = readByte(input) / 255.0; + float r2 = readByte(input) / 255.0; + float g2 = readByte(input) / 255.0; + float b2 = readByte(input) / 255.0; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b, a, r2, g2, b2); + if (frame == frameLast) break; + float time2 = readFloat(input); + float nr = readByte(input) / 255.0; + float ng = readByte(input) / 255.0; + float nb = readByte(input) / 255.0; + float na = readByte(input) / 255.0; + float nr2 = readByte(input) / 255.0; + float ng2 = readByte(input) / 255.0; + float nb2 = readByte(input) / 255.0; + + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + a = na; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.add(timeline); + break; + } + case SLOT_RGB2: { + int bezierCount = readVarint(input, true); + RGB2Timeline *timeline = new (__FILE__, __LINE__) RGB2Timeline(frameCount, bezierCount, slotIndex); + + float time = readFloat(input); + float r = readByte(input) / 255.0; + float g = readByte(input) / 255.0; + float b = readByte(input) / 255.0; + float r2 = readByte(input) / 255.0; + float g2 = readByte(input) / 255.0; + float b2 = readByte(input) / 255.0; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b, r2, g2, b2); + if (frame == frameLast) break; + float time2 = readFloat(input); + float nr = readByte(input) / 255.0; + float ng = readByte(input) / 255.0; + float nb = readByte(input) / 255.0; + float nr2 = readByte(input) / 255.0; + float ng2 = readByte(input) / 255.0; + float nb2 = readByte(input) / 255.0; + + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.add(timeline); + break; + } + case SLOT_ALPHA: { + int bezierCount = readVarint(input, true); + AlphaTimeline *timeline = new (__FILE__, __LINE__) AlphaTimeline(frameCount, bezierCount, slotIndex); + float time = readFloat(input); + float a = readByte(input) / 255.0; + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, a); + if (frame == frameLast) break; + float time2 = readFloat(input); + float a2 = readByte(input) / 255; + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1); + } + time = time2; + a = a2; + } + timelines.add(timeline); + break; + } + default: { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Invalid timeline type for a slot: ", skeletonData->_slots[slotIndex]->_name.buffer()); + return NULL; + } + } + } + } + + // Bone timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int boneIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + unsigned char timelineType = readByte(input); + int frameCount = readVarint(input, true); + int bezierCount = readVarint(input, true); + Timeline *timeline = NULL; + switch (timelineType) { + case BONE_ROTATE: + timeline = readTimeline(input, + new (__FILE__, __LINE__) RotateTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_TRANSLATE: + timeline = readTimeline2(input, new (__FILE__, __LINE__) TranslateTimeline(frameCount, bezierCount, boneIndex), scale); + break; + case BONE_TRANSLATEX: + timeline = readTimeline(input, new (__FILE__, __LINE__) TranslateXTimeline(frameCount, bezierCount, boneIndex), scale); + break; + case BONE_TRANSLATEY: + timeline = readTimeline(input, new (__FILE__, __LINE__) TranslateYTimeline(frameCount, bezierCount, boneIndex), scale); + break; + case BONE_SCALE: + timeline = readTimeline2(input, + new (__FILE__, __LINE__) ScaleTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SCALEX: + timeline = readTimeline(input, + new (__FILE__, __LINE__) ScaleXTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SCALEY: + timeline = readTimeline(input, + new (__FILE__, __LINE__) ScaleYTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SHEAR: + timeline = readTimeline2(input, + new (__FILE__, __LINE__) ShearTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SHEARX: + timeline = readTimeline(input, + new (__FILE__, __LINE__) ShearXTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SHEARY: + timeline = readTimeline(input, + new (__FILE__, __LINE__) ShearYTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + default: { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Invalid timeline type for a bone: ", skeletonData->_bones[boneIndex]->_name.buffer()); + return NULL; + } + } + timelines.add(timeline); + } + } + + // IK timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int index = readVarint(input, true); + int frameCount = readVarint(input, true); + int frameLast = frameCount - 1; + int bezierCount = readVarint(input, true); + IkConstraintTimeline *timeline = new (__FILE__, __LINE__) IkConstraintTimeline(frameCount, bezierCount, index); + float time = readFloat(input); + float mix = readFloat(input); + float softness = readFloat(input) * scale; + for (int frame = 0, bezier = 0;; frame++) { + int bendDirection = readSByte(input); + bool compress = readBoolean(input); + bool stretch = readBoolean(input); + timeline->setFrame(frame, time, mix, softness, bendDirection, compress, stretch); + if (frame == frameLast) break; + float time2 = readFloat(input); + float mix2 = readFloat(input); + float softness2 = readFloat(input) * scale; + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + } + timelines.add(timeline); + } + + // Transform constraint timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int index = readVarint(input, true); + int frameCount = readVarint(input, true); + int frameLast = frameCount - 1; + int bezierCount = readVarint(input, true); + TransformConstraintTimeline *timeline = new TransformConstraintTimeline(frameCount, bezierCount, index); + float time = readFloat(input); + float mixRotate = readFloat(input); + float mixX = readFloat(input); + float mixY = readFloat(input); + float mixScaleX = readFloat(input); + float mixScaleY = readFloat(input); + float mixShearY = readFloat(input); + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + if (frame == frameLast) break; + float time2 = readFloat(input); + float mixRotate2 = readFloat(input); + float mixX2 = readFloat(input); + float mixY2 = readFloat(input); + float mixScaleX2 = readFloat(input); + float mixScaleY2 = readFloat(input); + float mixShearY2 = readFloat(input); + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + } + timelines.add(timeline); + } + + // Path constraint timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int index = readVarint(input, true); + PathConstraintData *data = skeletonData->_pathConstraints[index]; + for (int ii = 0, nn = readVarint(input, true); ii < nn; ii++) { + int type = readSByte(input); + int frameCount = readVarint(input, true); + int bezierCount = readVarint(input, true); + switch (type) { + case PATH_POSITION: { + timelines + .add(readTimeline(input, new PathConstraintPositionTimeline(frameCount, bezierCount, index), + data->_positionMode == PositionMode_Fixed ? scale : 1)); + break; + } + case PATH_SPACING: { + timelines + .add(readTimeline(input, + new PathConstraintSpacingTimeline(frameCount, + bezierCount, + index), + data->_spacingMode == SpacingMode_Length || + data->_spacingMode == SpacingMode_Fixed + ? scale + : 1)); + break; + } + case PATH_MIX: + PathConstraintMixTimeline *timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index); + float time = readFloat(input); + float mixRotate = readFloat(input); + float mixX = readFloat(input); + float mixY = readFloat(input); + for (int frame = 0, bezier = 0, frameLast = timeline->getFrameCount() - 1;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY); + if (frame == frameLast) break; + float time2 = readFloat(input); + float mixRotate2 = readFloat(input); + float mixX2 = readFloat(input); + float mixY2 = readFloat(input); + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + } + timelines.add(timeline); + } + } + } + + // Deform timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + Skin *skin = skeletonData->_skins[readVarint(input, true)]; + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + int slotIndex = readVarint(input, true); + for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) { + const char *attachmentName = readStringRef(input, skeletonData); + Attachment *baseAttachment = skin->getAttachment(slotIndex, String(attachmentName)); + + if (!baseAttachment) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Attachment not found: ", attachmentName); + return NULL; + } + + VertexAttachment *attachment = static_cast(baseAttachment); + + bool weighted = attachment->_bones.size() > 0; + Vector &vertices = attachment->_vertices; + int deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size(); + + int frameCount = readVarint(input, true); + int frameLast = frameCount - 1; + int bezierCount = readVarint(input, true); + DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frameCount, bezierCount, slotIndex, + attachment); + + float time = readFloat(input); + for (int frame = 0, bezier = 0;; ++frame) { + Vector deform; + size_t end = (size_t) readVarint(input, true); + if (end == 0) { + if (weighted) { + deform.setSize(deformLength, 0); + for (int iiii = 0; iiii < deformLength; ++iiii) + deform[iiii] = 0; + } else { + deform.clearAndAddAll(vertices); + } + } else { + deform.setSize(deformLength, 0); + size_t start = (size_t) readVarint(input, true); + end += start; + if (scale == 1) { + for (size_t v = start; v < end; ++v) + deform[v] = readFloat(input); + } else { + for (size_t v = start; v < end; ++v) + deform[v] = readFloat(input) * scale; + } + + if (!weighted) { + for (size_t v = 0, vn = deform.size(); v < vn; ++v) + deform[v] += vertices[v]; + } + } + + timeline->setFrame(frame, time, deform); + if (frame == frameLast) break; + float time2 = readFloat(input); + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1); + } + time = time2; + } + + timelines.add(timeline); + } + } + } + + // Draw order timeline. + size_t drawOrderCount = (size_t) readVarint(input, true); + if (drawOrderCount > 0) { + DrawOrderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderTimeline(drawOrderCount); + + size_t slotCount = skeletonData->_slots.size(); + for (size_t i = 0; i < drawOrderCount; ++i) { + float time = readFloat(input); + size_t offsetCount = (size_t) readVarint(input, true); + + Vector drawOrder; + drawOrder.setSize(slotCount, 0); + for (int ii = (int) slotCount - 1; ii >= 0; --ii) + drawOrder[ii] = -1; + + Vector unchanged; + unchanged.setSize(slotCount - offsetCount, 0); + size_t originalIndex = 0, unchangedIndex = 0; + for (size_t ii = 0; ii < offsetCount; ++ii) { + size_t slotIndex = (size_t) readVarint(input, true); + // Collect unchanged items. + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + // Set changed items. + size_t index = originalIndex; + drawOrder[index + (size_t) readVarint(input, true)] = originalIndex++; + } + + // Collect remaining unchanged items. + while (originalIndex < slotCount) { + unchanged[unchangedIndex++] = originalIndex++; + } + + // Fill in unchanged items. + for (int ii = (int) slotCount - 1; ii >= 0; --ii) + if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; + timeline->setFrame(i, time, drawOrder); + } + timelines.add(timeline); + } + + // Event timeline. + int eventCount = readVarint(input, true); + if (eventCount > 0) { + EventTimeline *timeline = new (__FILE__, __LINE__) EventTimeline(eventCount); + + for (int i = 0; i < eventCount; ++i) { + float time = readFloat(input); + EventData *eventData = skeletonData->_events[readVarint(input, true)]; + Event *event = new (__FILE__, __LINE__) Event(time, *eventData); + + event->_intValue = readVarint(input, false); + event->_floatValue = readFloat(input); + bool freeString = readBoolean(input); + const char *event_stringValue = freeString ? readString(input) : eventData->_stringValue.buffer(); + event->_stringValue = String(event_stringValue); + if (freeString) SpineExtension::free(event_stringValue, __FILE__, __LINE__); + + if (!eventData->_audioPath.isEmpty()) { + event->_volume = readFloat(input); + event->_balance = readFloat(input); + } + timeline->setFrame(i, event); + } + timelines.add(timeline); + } + + float duration = 0; + for (int i = 0, n = timelines.size(); i < n; i++) { + duration = MathUtil::max(duration, (timelines[i])->getDuration()); + } + return new (__FILE__, __LINE__) Animation(String(name), timelines, duration); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp new file mode 100644 index 0000000..dde0876 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp @@ -0,0 +1,222 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include + +#include + +#include + +using namespace spine; + +SkeletonBounds::SkeletonBounds() : _minX(0), _minY(0), _maxX(0), _maxY(0) { +} + +SkeletonBounds::~SkeletonBounds() { + for (size_t i = 0, n = _polygons.size(); i < n; i++) + _polygonPool.free(_polygons[i]); + _polygons.clear(); +} + +void SkeletonBounds::update(Skeleton &skeleton, bool updateAabb) { + Vector &slots = skeleton.getSlots(); + size_t slotCount = slots.size(); + + _boundingBoxes.clear(); + for (size_t i = 0, n = _polygons.size(); i < n; ++i) { + _polygonPool.free(_polygons[i]); + } + + _polygons.clear(); + + for (size_t i = 0; i < slotCount; i++) { + Slot *slot = slots[i]; + if (!slot->getBone().isActive()) continue; + + Attachment *attachment = slot->getAttachment(); + if (attachment == NULL || !attachment->getRTTI().instanceOf(BoundingBoxAttachment::rtti)) continue; + BoundingBoxAttachment *boundingBox = static_cast(attachment); + _boundingBoxes.add(boundingBox); + + spine::Polygon *polygonP = _polygonPool.obtain(); + _polygons.add(polygonP); + + Polygon &polygon = *polygonP; + + size_t count = boundingBox->getWorldVerticesLength(); + polygon._count = count; + if (polygon._vertices.size() < count) { + polygon._vertices.setSize(count, 0); + } + boundingBox->computeWorldVertices(*slot, polygon._vertices); + } + + if (updateAabb) + aabbCompute(); + else { + _minX = FLT_MIN; + _minY = FLT_MIN; + _maxX = FLT_MAX; + _maxY = FLT_MAX; + } +} + +bool SkeletonBounds::aabbcontainsPoint(float x, float y) { + return x >= _minX && x <= _maxX && y >= _minY && y <= _maxY; +} + +bool SkeletonBounds::aabbintersectsSegment(float x1, float y1, float x2, float y2) { + float minX = _minX; + float minY = _minY; + float maxX = _maxX; + float maxY = _maxY; + + if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || + (y1 >= maxY && y2 >= maxY)) { + return false; + } + + float m = (y2 - y1) / (x2 - x1); + float y = m * (minX - x1) + y1; + if (y > minY && y < maxY) return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) return true; + float x = (minY - y1) / m + x1; + if (x > minX && x < maxX) return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) return true; + return false; +} + +bool SkeletonBounds::aabbIntersectsSkeleton(SkeletonBounds bounds) { + return _minX < bounds._maxX && _maxX > bounds._minX && _minY < bounds._maxY && _maxY > bounds._minY; +} + +bool SkeletonBounds::containsPoint(spine::Polygon *polygon, float x, float y) { + Vector &vertices = polygon->_vertices; + int nn = polygon->_count; + + int prevIndex = nn - 2; + bool inside = false; + for (int ii = 0; ii < nn; ii += 2) { + float vertexY = vertices[ii + 1]; + float prevY = vertices[prevIndex + 1]; + if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { + float vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) { + inside = !inside; + } + } + prevIndex = ii; + } + return inside; +} + +BoundingBoxAttachment *SkeletonBounds::containsPoint(float x, float y) { + for (size_t i = 0, n = _polygons.size(); i < n; ++i) + if (containsPoint(_polygons[i], x, y)) return _boundingBoxes[i]; + return NULL; +} + +BoundingBoxAttachment *SkeletonBounds::intersectsSegment(float x1, float y1, float x2, float y2) { + for (size_t i = 0, n = _polygons.size(); i < n; ++i) + if (intersectsSegment(_polygons[i], x1, y1, x2, y2)) return _boundingBoxes[i]; + return NULL; +} + +bool SkeletonBounds::intersectsSegment(spine::Polygon *polygon, float x1, float y1, float x2, float y2) { + Vector &vertices = polygon->_vertices; + size_t nn = polygon->_count; + + float width12 = x1 - x2, height12 = y1 - y2; + float det1 = x1 * y2 - y1 * x2; + float x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (size_t ii = 0; ii < nn; ii += 2) { + float x4 = vertices[ii], y4 = vertices[ii + 1]; + float det2 = x3 * y4 - y3 * x4; + float width34 = x3 - x4, height34 = y3 - y4; + float det3 = width12 * height34 - height12 * width34; + float x = (det1 * width34 - width12 * det2) / det3; + if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { + float y = (det1 * height34 - height12 * det2) / det3; + if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) { + return true; + } + } + x3 = x4; + y3 = y4; + } + + return false; +} + +spine::Polygon *SkeletonBounds::getPolygon(BoundingBoxAttachment *attachment) { + int index = _boundingBoxes.indexOf(attachment); + return index == -1 ? NULL : _polygons[index]; +} + +float SkeletonBounds::getWidth() { + return _maxX - _minX; +} + +float SkeletonBounds::getHeight() { + return _maxY - _minY; +} + +void SkeletonBounds::aabbCompute() { + float minX = FLT_MAX; + float minY = FLT_MAX; + float maxX = FLT_MIN; + float maxY = FLT_MIN; + + for (size_t i = 0, n = _polygons.size(); i < n; ++i) { + spine::Polygon *polygon = _polygons[i]; + Vector &vertices = polygon->_vertices; + for (int ii = 0, nn = polygon->_count; ii < nn; ii += 2) { + float x = vertices[ii]; + float y = vertices[ii + 1]; + minX = MathUtil::min(minX, x); + minY = MathUtil::min(minY, y); + maxX = MathUtil::max(maxX, x); + maxY = MathUtil::max(maxY, y); + } + } + _minX = minX; + _minY = minY; + _maxX = maxX; + _maxY = maxY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp new file mode 100644 index 0000000..cc82a6e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp @@ -0,0 +1,327 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +using namespace spine; + +SkeletonClipping::SkeletonClipping() : _clipAttachment(NULL) { + _clipOutput.ensureCapacity(128); + _clippedVertices.ensureCapacity(128); + _clippedTriangles.ensureCapacity(128); + _clippedUVs.ensureCapacity(128); +} + +size_t SkeletonClipping::clipStart(Slot &slot, ClippingAttachment *clip) { + if (_clipAttachment != NULL) { + return 0; + } + + _clipAttachment = clip; + + int n = clip->getWorldVerticesLength(); + _clippingPolygon.setSize(n, 0); + clip->computeWorldVertices(slot, 0, n, _clippingPolygon, 0, 2); + makeClockwise(_clippingPolygon); + _clippingPolygons = &_triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon)); + + for (size_t i = 0; i < _clippingPolygons->size(); ++i) { + Vector *polygonP = (*_clippingPolygons)[i]; + Vector &polygon = *polygonP; + makeClockwise(polygon); + polygon.add(polygon[0]); + polygon.add(polygon[1]); + } + + return (*_clippingPolygons).size(); +} + +void SkeletonClipping::clipEnd(Slot &slot) { + if (_clipAttachment != NULL && _clipAttachment->_endSlot == &slot._data) { + clipEnd(); + } +} + +void SkeletonClipping::clipEnd() { + if (_clipAttachment == NULL) return; + + _clipAttachment = NULL; + _clippingPolygons = NULL; + _clippedVertices.clear(); + _clippedUVs.clear(); + _clippedTriangles.clear(); + _clippingPolygon.clear(); +} + +void SkeletonClipping::clipTriangles(Vector &vertices, Vector &triangles, Vector &uvs, + size_t stride) { + clipTriangles(vertices.buffer(), triangles.buffer(), triangles.size(), uvs.buffer(), stride); +} + +void SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, + size_t trianglesLength, float *uvs, size_t stride) { + Vector &clipOutput = _clipOutput; + Vector &clippedVertices = _clippedVertices; + Vector &clippedTriangles = _clippedTriangles; + Vector *> &polygons = *_clippingPolygons; + size_t polygonsCount = (*_clippingPolygons).size(); + + size_t index = 0; + clippedVertices.clear(); + _clippedUVs.clear(); + clippedTriangles.clear(); + + size_t i = 0; +continue_outer: + for (; i < trianglesLength; i += 3) { + int vertexOffset = triangles[i] * stride; + float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + + vertexOffset = triangles[i + 1] * stride; + float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + float u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + + vertexOffset = triangles[i + 2] * stride; + float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + float u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + + for (size_t p = 0; p < polygonsCount; p++) { + size_t s = clippedVertices.size(); + if (clip(x1, y1, x2, y2, x3, y3, &(*polygons[p]), &clipOutput)) { + size_t clipOutputLength = clipOutput.size(); + if (clipOutputLength == 0) continue; + float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + float d = 1 / (d0 * d2 + d1 * (y1 - y3)); + + size_t clipOutputCount = clipOutputLength >> 1; + clippedVertices.setSize(s + clipOutputCount * 2, 0); + _clippedUVs.setSize(s + clipOutputCount * 2, 0); + for (size_t ii = 0; ii < clipOutputLength; ii += 2) { + float x = clipOutput[ii], y = clipOutput[ii + 1]; + clippedVertices[s] = x; + clippedVertices[s + 1] = y; + float c0 = x - x3, c1 = y - y3; + float a = (d0 * c0 + d1 * c1) * d; + float b = (d4 * c0 + d2 * c1) * d; + float c = 1 - a - b; + _clippedUVs[s] = u1 * a + u2 * b + u3 * c; + _clippedUVs[s + 1] = v1 * a + v2 * b + v3 * c; + s += 2; + } + + s = clippedTriangles.size(); + clippedTriangles.setSize(s + 3 * (clipOutputCount - 2), 0); + clipOutputCount--; + for (size_t ii = 1; ii < clipOutputCount; ii++) { + clippedTriangles[s] = (unsigned short) (index); + clippedTriangles[s + 1] = (unsigned short) (index + ii); + clippedTriangles[s + 2] = (unsigned short) (index + ii + 1); + s += 3; + } + index += clipOutputCount + 1; + } else { + clippedVertices.setSize(s + 3 * 2, 0); + _clippedUVs.setSize(s + 3 * 2, 0); + clippedVertices[s] = x1; + clippedVertices[s + 1] = y1; + clippedVertices[s + 2] = x2; + clippedVertices[s + 3] = y2; + clippedVertices[s + 4] = x3; + clippedVertices[s + 5] = y3; + + _clippedUVs[s] = u1; + _clippedUVs[s + 1] = v1; + _clippedUVs[s + 2] = u2; + _clippedUVs[s + 3] = v2; + _clippedUVs[s + 4] = u3; + _clippedUVs[s + 5] = v3; + + s = clippedTriangles.size(); + clippedTriangles.setSize(s + 3, 0); + clippedTriangles[s] = (unsigned short) index; + clippedTriangles[s + 1] = (unsigned short) (index + 1); + clippedTriangles[s + 2] = (unsigned short) (index + 2); + index += 3; + i += 3; + goto continue_outer; + } + } + } +} + +bool SkeletonClipping::isClipping() { + return _clipAttachment != NULL; +} + +Vector &SkeletonClipping::getClippedVertices() { + return _clippedVertices; +} + +Vector &SkeletonClipping::getClippedTriangles() { + return _clippedTriangles; +} + +Vector &SkeletonClipping::getClippedUVs() { + return _clippedUVs; +} + +bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector *clippingArea, + Vector *output) { + Vector *originalOutput = output; + bool clipped = false; + + // Avoid copy at the end. + Vector *input; + if (clippingArea->size() % 4 >= 2) { + input = output; + output = &_scratch; + } else + input = &_scratch; + + input->clear(); + input->add(x1); + input->add(y1); + input->add(x2); + input->add(y2); + input->add(x3); + input->add(y3); + input->add(x1); + input->add(y1); + output->clear(); + + Vector &clippingVertices = *clippingArea; + size_t clippingVerticesLast = clippingArea->size() - 4; + for (size_t i = 0;; i += 2) { + float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; + float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; + + Vector &inputVertices = *input; + size_t inputVerticesLength = input->size() - 2, outputStart = output->size(); + for (size_t ii = 0; ii < inputVerticesLength; ii += 2) { + float inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; + bool side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; + if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { + if (side2) { + // v1 inside, v2 inside + output->add(inputX2); + output->add(inputY2); + continue; + } + // v1 inside, v2 outside + float c0 = inputY2 - inputY, c2 = inputX2 - inputX; + float s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (MathUtil::abs(s) > 0.000001f) { + float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output->add(edgeX + (edgeX2 - edgeX) * ua); + output->add(edgeY + (edgeY2 - edgeY) * ua); + } else { + output->add(edgeX); + output->add(edgeY); + } + } else if (side2) { + // v1 outside, v2 inside + float c0 = inputY2 - inputY, c2 = inputX2 - inputX; + float s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (MathUtil::abs(s) > 0.000001f) { + float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output->add(edgeX + (edgeX2 - edgeX) * ua); + output->add(edgeY + (edgeY2 - edgeY) * ua); + } else { + output->add(edgeX); + output->add(edgeY); + } + output->add(inputX2); + output->add(inputY2); + } + clipped = true; + } + + if (outputStart == output->size()) { + // All edges outside. + originalOutput->clear(); + return true; + } + + output->add((*output)[0]); + output->add((*output)[1]); + + if (i == clippingVerticesLast) { + break; + } + Vector *temp = output; + output = input; + output->clear(); + input = temp; + } + + if (originalOutput != output) { + originalOutput->clear(); + for (size_t i = 0, n = output->size() - 2; i < n; ++i) + originalOutput->add((*output)[i]); + } else + originalOutput->setSize(originalOutput->size() - 2, 0); + + return clipped; +} + +void SkeletonClipping::makeClockwise(Vector &polygon) { + size_t verticeslength = polygon.size(); + + float area = polygon[verticeslength - 2] * polygon[1] - polygon[0] * polygon[verticeslength - 1]; + float p1x, p1y, p2x, p2y; + + for (size_t i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = polygon[i]; + p1y = polygon[i + 1]; + p2x = polygon[i + 2]; + p2y = polygon[i + 3]; + area += p1x * p2y - p2x * p1y; + } + + if (area < 0) return; + + for (size_t i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + float x = polygon[i], y = polygon[i + 1]; + int other = lastX - i; + polygon[i] = polygon[other]; + polygon[i + 1] = polygon[other + 1]; + polygon[other] = x; + polygon[other + 1] = y; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp new file mode 100644 index 0000000..5602389 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -0,0 +1,229 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +SkeletonData::SkeletonData() : _name(), + _defaultSkin(NULL), + _x(0), + _y(0), + _width(0), + _height(0), + _version(), + _hash(), + _fps(0), + _imagesPath() { +} + +SkeletonData::~SkeletonData() { + ContainerUtil::cleanUpVectorOfPointers(_bones); + ContainerUtil::cleanUpVectorOfPointers(_slots); + ContainerUtil::cleanUpVectorOfPointers(_skins); + + _defaultSkin = NULL; + + ContainerUtil::cleanUpVectorOfPointers(_events); + ContainerUtil::cleanUpVectorOfPointers(_animations); + ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); + ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); + ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); + for (size_t i = 0; i < _strings.size(); i++) { + SpineExtension::free(_strings[i], __FILE__, __LINE__); + } +} + +BoneData *SkeletonData::findBone(const String &boneName) { + return ContainerUtil::findWithName(_bones, boneName); +} + +SlotData *SkeletonData::findSlot(const String &slotName) { + return ContainerUtil::findWithName(_slots, slotName); +} + +Skin *SkeletonData::findSkin(const String &skinName) { + return ContainerUtil::findWithName(_skins, skinName); +} + +spine::EventData *SkeletonData::findEvent(const String &eventDataName) { + return ContainerUtil::findWithName(_events, eventDataName); +} + +Animation *SkeletonData::findAnimation(const String &animationName) { + return ContainerUtil::findWithName(_animations, animationName); +} + +IkConstraintData *SkeletonData::findIkConstraint(const String &constraintName) { + return ContainerUtil::findWithName(_ikConstraints, constraintName); +} + +TransformConstraintData *SkeletonData::findTransformConstraint(const String &constraintName) { + return ContainerUtil::findWithName(_transformConstraints, constraintName); +} + +PathConstraintData *SkeletonData::findPathConstraint(const String &constraintName) { + return ContainerUtil::findWithName(_pathConstraints, constraintName); +} + +const String &SkeletonData::getName() { + return _name; +} + +void SkeletonData::setName(const String &inValue) { + _name = inValue; +} + +Vector &SkeletonData::getBones() { + return _bones; +} + +Vector &SkeletonData::getSlots() { + return _slots; +} + +Vector &SkeletonData::getSkins() { + return _skins; +} + +Skin *SkeletonData::getDefaultSkin() { + return _defaultSkin; +} + +void SkeletonData::setDefaultSkin(Skin *inValue) { + _defaultSkin = inValue; +} + +Vector &SkeletonData::getEvents() { + return _events; +} + +Vector &SkeletonData::getAnimations() { + return _animations; +} + +Vector &SkeletonData::getIkConstraints() { + return _ikConstraints; +} + +Vector &SkeletonData::getTransformConstraints() { + return _transformConstraints; +} + +Vector &SkeletonData::getPathConstraints() { + return _pathConstraints; +} + +float SkeletonData::getX() { + return _x; +} + +void SkeletonData::setX(float inValue) { + _x = inValue; +} + +float SkeletonData::getY() { + return _y; +} + +void SkeletonData::setY(float inValue) { + _y = inValue; +} + +float SkeletonData::getWidth() { + return _width; +} + +void SkeletonData::setWidth(float inValue) { + _width = inValue; +} + +float SkeletonData::getHeight() { + return _height; +} + +void SkeletonData::setHeight(float inValue) { + _height = inValue; +} + +const String &SkeletonData::getVersion() { + return _version; +} + +void SkeletonData::setVersion(const String &inValue) { + _version = inValue; +} + +const String &SkeletonData::getHash() { + return _hash; +} + +void SkeletonData::setHash(const String &inValue) { + _hash = inValue; +} + +const String &SkeletonData::getImagesPath() { + return _imagesPath; +} + +void SkeletonData::setImagesPath(const String &inValue) { + _imagesPath = inValue; +} + + +const String &SkeletonData::getAudioPath() { + return _audioPath; +} + +void SkeletonData::setAudioPath(const String &inValue) { + _audioPath = inValue; +} + +float SkeletonData::getFps() { + return _fps; +} + +void SkeletonData::setFps(float inValue) { + _fps = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp new file mode 100644 index 0000000..9e517cb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -0,0 +1,1436 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +static float toColor(const char *value, size_t index) { + char digits[3]; + char *error; + int color; + + if (index >= strlen(value) / 2) return -1; + + value += index * 2; + + digits[0] = *value; + digits[1] = *(value + 1); + digits[2] = '\0'; + color = (int) strtoul(digits, &error, 16); + if (*error != 0) return -1; + + return color / (float) 255; +} + +static void toColor(Color &color, const char *value, bool hasAlpha) { + color.r = toColor(value, 0); + color.g = toColor(value, 1); + color.b = toColor(value, 2); + if (hasAlpha) color.a = toColor(value, 3); +} + +SkeletonJson::SkeletonJson(Atlas *atlas) : _attachmentLoader(new (__FILE__, __LINE__) AtlasAttachmentLoader(atlas)), + _scale(1), _ownsLoader(true) {} + +SkeletonJson::SkeletonJson(AttachmentLoader *attachmentLoader, bool ownsLoader) : _attachmentLoader(attachmentLoader), + _scale(1), + _ownsLoader(ownsLoader) { + assert(_attachmentLoader != NULL); +} + +SkeletonJson::~SkeletonJson() { + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + + if (_ownsLoader) delete _attachmentLoader; +} + +SkeletonData *SkeletonJson::readSkeletonDataFile(const String &path) { + int length; + SkeletonData *skeletonData; + const char *json = SpineExtension::readFile(path, &length); + if (length == 0 || !json) { + setError(NULL, "Unable to read skeleton file: ", path); + return NULL; + } + + skeletonData = readSkeletonData(json); + + SpineExtension::free(json, __FILE__, __LINE__); + + return skeletonData; +} + +SkeletonData *SkeletonJson::readSkeletonData(const char *json) { + int i, ii; + SkeletonData *skeletonData; + Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *slots, *skins, *animations, *events; + + _error = ""; + _linkedMeshes.clear(); + + root = new (__FILE__, __LINE__) Json(json); + + if (!root) { + setError(NULL, "Invalid skeleton JSON: ", Json::getError()); + return NULL; + } + + skeletonData = new (__FILE__, __LINE__) SkeletonData(); + + skeleton = Json::getItem(root, "skeleton"); + if (skeleton) { + skeletonData->_hash = Json::getString(skeleton, "hash", 0); + skeletonData->_version = Json::getString(skeleton, "spine", 0); + skeletonData->_x = Json::getFloat(skeleton, "x", 0); + skeletonData->_y = Json::getFloat(skeleton, "y", 0); + skeletonData->_width = Json::getFloat(skeleton, "width", 0); + skeletonData->_height = Json::getFloat(skeleton, "height", 0); + skeletonData->_fps = Json::getFloat(skeleton, "fps", 30); + skeletonData->_audioPath = Json::getString(skeleton, "audio", 0); + skeletonData->_imagesPath = Json::getString(skeleton, "images", 0); + } + + /* Bones. */ + bones = Json::getItem(root, "bones"); + skeletonData->_bones.setSize(bones->_size, 0); + int bonesCount = 0; + for (boneMap = bones->_child, i = 0; boneMap; boneMap = boneMap->_next, ++i) { + BoneData *data; + const char *transformMode; + + BoneData *parent = 0; + const char *parentName = Json::getString(boneMap, "parent", 0); + if (parentName) { + parent = skeletonData->findBone(parentName); + if (!parent) { + delete skeletonData; + setError(root, "Parent bone not found: ", parentName); + return NULL; + } + } + + data = new (__FILE__, __LINE__) BoneData(bonesCount, Json::getString(boneMap, "name", 0), parent); + + data->_length = Json::getFloat(boneMap, "length", 0) * _scale; + data->_x = Json::getFloat(boneMap, "x", 0) * _scale; + data->_y = Json::getFloat(boneMap, "y", 0) * _scale; + data->_rotation = Json::getFloat(boneMap, "rotation", 0); + data->_scaleX = Json::getFloat(boneMap, "scaleX", 1); + data->_scaleY = Json::getFloat(boneMap, "scaleY", 1); + data->_shearX = Json::getFloat(boneMap, "shearX", 0); + data->_shearY = Json::getFloat(boneMap, "shearY", 0); + transformMode = Json::getString(boneMap, "transform", "normal"); + data->_transformMode = TransformMode_Normal; + if (strcmp(transformMode, "normal") == 0) data->_transformMode = TransformMode_Normal; + else if (strcmp(transformMode, "onlyTranslation") == 0) + data->_transformMode = TransformMode_OnlyTranslation; + else if (strcmp(transformMode, "noRotationOrReflection") == 0) + data->_transformMode = TransformMode_NoRotationOrReflection; + else if (strcmp(transformMode, "noScale") == 0) + data->_transformMode = TransformMode_NoScale; + else if (strcmp(transformMode, "noScaleOrReflection") == 0) + data->_transformMode = TransformMode_NoScaleOrReflection; + data->_skinRequired = Json::getBoolean(boneMap, "skin", false); + + const char *color = Json::getString(boneMap, "color", NULL); + if (color) toColor(data->getColor(), color, true); + + skeletonData->_bones[i] = data; + bonesCount++; + } + + /* Slots. */ + slots = Json::getItem(root, "slots"); + if (slots) { + Json *slotMap; + skeletonData->_slots.ensureCapacity(slots->_size); + skeletonData->_slots.setSize(slots->_size, 0); + for (slotMap = slots->_child, i = 0; slotMap; slotMap = slotMap->_next, ++i) { + SlotData *data; + const char *color; + const char *dark; + Json *item; + + const char *boneName = Json::getString(slotMap, "bone", 0); + BoneData *boneData = skeletonData->findBone(boneName); + if (!boneData) { + delete skeletonData; + setError(root, "Slot bone not found: ", boneName); + return NULL; + } + + data = new (__FILE__, __LINE__) SlotData(i, Json::getString(slotMap, "name", 0), *boneData); + + color = Json::getString(slotMap, "color", 0); + if (color) { + Color &c = data->getColor(); + c.r = toColor(color, 0); + c.g = toColor(color, 1); + c.b = toColor(color, 2); + c.a = toColor(color, 3); + } + + dark = Json::getString(slotMap, "dark", 0); + if (dark) { + Color &darkColor = data->getDarkColor(); + darkColor.r = toColor(dark, 0); + darkColor.g = toColor(dark, 1); + darkColor.b = toColor(dark, 2); + darkColor.a = 1; + data->setHasDarkColor(true); + } + + item = Json::getItem(slotMap, "attachment"); + if (item) data->setAttachmentName(item->_valueString); + + item = Json::getItem(slotMap, "blend"); + if (item) { + if (strcmp(item->_valueString, "additive") == 0) data->_blendMode = BlendMode_Additive; + else if (strcmp(item->_valueString, "multiply") == 0) + data->_blendMode = BlendMode_Multiply; + else if (strcmp(item->_valueString, "screen") == 0) + data->_blendMode = BlendMode_Screen; + } + + skeletonData->_slots[i] = data; + } + } + + /* IK constraints. */ + ik = Json::getItem(root, "ik"); + if (ik) { + Json *constraintMap; + skeletonData->_ikConstraints.ensureCapacity(ik->_size); + skeletonData->_ikConstraints.setSize(ik->_size, 0); + for (constraintMap = ik->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *targetName; + + IkConstraintData *data = new (__FILE__, __LINE__) IkConstraintData( + Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.ensureCapacity(boneMap->_size); + data->_bones.setSize(boneMap->_size, 0); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) { + delete skeletonData; + setError(root, "IK bone not found: ", boneMap->_valueString); + return NULL; + } + } + + targetName = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findBone(targetName); + if (!data->_target) { + delete skeletonData; + setError(root, "Target bone not found: ", targetName); + return NULL; + } + + data->_mix = Json::getFloat(constraintMap, "mix", 1); + data->_softness = Json::getFloat(constraintMap, "softness", 0) * _scale; + data->_bendDirection = Json::getInt(constraintMap, "bendPositive", 1) ? 1 : -1; + data->_compress = Json::getInt(constraintMap, "compress", 0) ? true : false; + data->_stretch = Json::getInt(constraintMap, "stretch", 0) ? true : false; + data->_uniform = Json::getInt(constraintMap, "uniform", 0) ? true : false; + + skeletonData->_ikConstraints[i] = data; + } + } + + /* Transform constraints. */ + transform = Json::getItem(root, "transform"); + if (transform) { + Json *constraintMap; + skeletonData->_transformConstraints.ensureCapacity(transform->_size); + skeletonData->_transformConstraints.setSize(transform->_size, 0); + for (constraintMap = transform->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *name; + + TransformConstraintData *data = new (__FILE__, __LINE__) TransformConstraintData( + Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.ensureCapacity(boneMap->_size); + data->_bones.setSize(boneMap->_size, 0); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) { + delete skeletonData; + setError(root, "Transform bone not found: ", boneMap->_valueString); + return NULL; + } + } + + name = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findBone(name); + if (!data->_target) { + delete skeletonData; + setError(root, "Target bone not found: ", name); + return NULL; + } + + data->_local = Json::getInt(constraintMap, "local", 0) ? true : false; + data->_relative = Json::getInt(constraintMap, "relative", 0) ? true : false; + data->_offsetRotation = Json::getFloat(constraintMap, "rotation", 0); + data->_offsetX = Json::getFloat(constraintMap, "x", 0) * _scale; + data->_offsetY = Json::getFloat(constraintMap, "y", 0) * _scale; + data->_offsetScaleX = Json::getFloat(constraintMap, "scaleX", 0); + data->_offsetScaleY = Json::getFloat(constraintMap, "scaleY", 0); + data->_offsetShearY = Json::getFloat(constraintMap, "shearY", 0); + + data->_mixRotate = Json::getFloat(constraintMap, "mixRotate", 1); + data->_mixX = Json::getFloat(constraintMap, "mixX", 1); + data->_mixY = Json::getFloat(constraintMap, "mixY", data->_mixX); + data->_mixScaleX = Json::getFloat(constraintMap, "mixScaleX", 1); + data->_mixScaleY = Json::getFloat(constraintMap, "mixScaleY", data->_mixScaleX); + data->_mixShearY = Json::getFloat(constraintMap, "mixShearY", 1); + + skeletonData->_transformConstraints[i] = data; + } + } + + /* Path constraints */ + path = Json::getItem(root, "path"); + if (path) { + Json *constraintMap; + skeletonData->_pathConstraints.ensureCapacity(path->_size); + skeletonData->_pathConstraints.setSize(path->_size, 0); + for (constraintMap = path->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *name; + const char *item; + + PathConstraintData *data = new (__FILE__, __LINE__) PathConstraintData( + Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.ensureCapacity(boneMap->_size); + data->_bones.setSize(boneMap->_size, 0); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) { + delete skeletonData; + setError(root, "Path bone not found: ", boneMap->_valueString); + return NULL; + } + } + + name = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findSlot(name); + if (!data->_target) { + delete skeletonData; + setError(root, "Target slot not found: ", name); + return NULL; + } + + item = Json::getString(constraintMap, "positionMode", "percent"); + if (strcmp(item, "fixed") == 0) { + data->_positionMode = PositionMode_Fixed; + } else if (strcmp(item, "percent") == 0) { + data->_positionMode = PositionMode_Percent; + } + + item = Json::getString(constraintMap, "spacingMode", "length"); + if (strcmp(item, "length") == 0) data->_spacingMode = SpacingMode_Length; + else if (strcmp(item, "fixed") == 0) + data->_spacingMode = SpacingMode_Fixed; + else if (strcmp(item, "percent") == 0) + data->_spacingMode = SpacingMode_Percent; + else + data->_spacingMode = SpacingMode_Proportional; + + item = Json::getString(constraintMap, "rotateMode", "tangent"); + if (strcmp(item, "tangent") == 0) data->_rotateMode = RotateMode_Tangent; + else if (strcmp(item, "chain") == 0) + data->_rotateMode = RotateMode_Chain; + else if (strcmp(item, "chainScale") == 0) + data->_rotateMode = RotateMode_ChainScale; + + data->_offsetRotation = Json::getFloat(constraintMap, "rotation", 0); + data->_position = Json::getFloat(constraintMap, "position", 0); + if (data->_positionMode == PositionMode_Fixed) data->_position *= _scale; + data->_spacing = Json::getFloat(constraintMap, "spacing", 0); + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) + data->_spacing *= _scale; + data->_mixRotate = Json::getFloat(constraintMap, "mixRotate", 1); + data->_mixX = Json::getFloat(constraintMap, "mixX", 1); + data->_mixY = Json::getFloat(constraintMap, "mixY", data->_mixX); + + skeletonData->_pathConstraints[i] = data; + } + } + + /* Skins. */ + skins = Json::getItem(root, "skins"); + if (skins) { + Json *skinMap; + skeletonData->_skins.ensureCapacity(skins->_size); + skeletonData->_skins.setSize(skins->_size, 0); + int skinsIndex = 0; + for (skinMap = skins->_child, i = 0; skinMap; skinMap = skinMap->_next, ++i) { + Json *attachmentsMap; + Json *curves; + + Skin *skin = new (__FILE__, __LINE__) Skin(Json::getString(skinMap, "name", "")); + + Json *item = Json::getItem(skinMap, "bones"); + if (item) { + for (item = item->_child; item; item = item->_next) { + BoneData *data = skeletonData->findBone(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin bone not found: "), item->_valueString); + return NULL; + } + skin->getBones().add(data); + } + } + + item = Json::getItem(skinMap, "ik"); + if (item) { + for (item = item->_child; item; item = item->_next) { + IkConstraintData *data = skeletonData->findIkConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin IK constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + item = Json::getItem(skinMap, "transform"); + if (item) { + for (item = item->_child; item; item = item->_next) { + TransformConstraintData *data = skeletonData->findTransformConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin transform constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + item = Json::getItem(skinMap, "path"); + if (item) { + for (item = item->_child; item; item = item->_next) { + PathConstraintData *data = skeletonData->findPathConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin path constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + skeletonData->_skins[skinsIndex++] = skin; + if (strcmp(Json::getString(skinMap, "name", ""), "default") == 0) { + skeletonData->_defaultSkin = skin; + } + + Json *attachments = Json::getItem(skinMap, "attachments"); + if (attachments) + for (attachmentsMap = attachments->_child; + attachmentsMap; attachmentsMap = attachmentsMap->_next) { + SlotData *slot = skeletonData->findSlot(attachmentsMap->_name); + Json *attachmentMap; + + for (attachmentMap = attachmentsMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) { + Attachment *attachment = NULL; + const char *skinAttachmentName = attachmentMap->_name; + const char *attachmentName = Json::getString(attachmentMap, "name", skinAttachmentName); + const char *attachmentPath = Json::getString(attachmentMap, "path", attachmentName); + const char *color; + Json *entry; + + const char *typeString = Json::getString(attachmentMap, "type", "region"); + AttachmentType type; + if (strcmp(typeString, "region") == 0) type = AttachmentType_Region; + else if (strcmp(typeString, "mesh") == 0) + type = AttachmentType_Mesh; + else if (strcmp(typeString, "linkedmesh") == 0) + type = AttachmentType_Linkedmesh; + else if (strcmp(typeString, "boundingbox") == 0) + type = AttachmentType_Boundingbox; + else if (strcmp(typeString, "path") == 0) + type = AttachmentType_Path; + else if (strcmp(typeString, "clipping") == 0) + type = AttachmentType_Clipping; + else if (strcmp(typeString, "point") == 0) + type = AttachmentType_Point; + else { + delete skeletonData; + setError(root, "Unknown attachment type: ", typeString); + return NULL; + } + + switch (type) { + case AttachmentType_Region: { + attachment = _attachmentLoader->newRegionAttachment(*skin, attachmentName, attachmentPath); + if (!attachment) { + delete skeletonData; + setError(root, "Error reading attachment: ", skinAttachmentName); + return NULL; + } + + RegionAttachment *region = static_cast(attachment); + region->_path = attachmentPath; + + region->_x = Json::getFloat(attachmentMap, "x", 0) * _scale; + region->_y = Json::getFloat(attachmentMap, "y", 0) * _scale; + region->_scaleX = Json::getFloat(attachmentMap, "scaleX", 1); + region->_scaleY = Json::getFloat(attachmentMap, "scaleY", 1); + region->_rotation = Json::getFloat(attachmentMap, "rotation", 0); + region->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; + region->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; + + color = Json::getString(attachmentMap, "color", 0); + if (color) toColor(region->getColor(), color, true); + + region->updateOffset(); + _attachmentLoader->configureAttachment(region); + break; + } + case AttachmentType_Mesh: + case AttachmentType_Linkedmesh: { + attachment = _attachmentLoader->newMeshAttachment(*skin, attachmentName, attachmentPath); + + if (!attachment) { + delete skeletonData; + setError(root, "Error reading attachment: ", skinAttachmentName); + return NULL; + } + + MeshAttachment *mesh = static_cast(attachment); + mesh->_path = attachmentPath; + + color = Json::getString(attachmentMap, "color", 0); + if (color) toColor(mesh->getColor(), color, true); + + mesh->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; + mesh->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; + + entry = Json::getItem(attachmentMap, "parent"); + if (!entry) { + int verticesLength; + entry = Json::getItem(attachmentMap, "triangles"); + mesh->_triangles.ensureCapacity(entry->_size); + mesh->_triangles.setSize(entry->_size, 0); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + mesh->_triangles[ii] = (unsigned short) entry->_valueInt; + + entry = Json::getItem(attachmentMap, "uvs"); + verticesLength = entry->_size; + mesh->_regionUVs.ensureCapacity(verticesLength); + mesh->_regionUVs.setSize(verticesLength, 0); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + mesh->_regionUVs[ii] = entry->_valueFloat; + + readVertices(attachmentMap, mesh, verticesLength); + + mesh->updateUVs(); + + mesh->_hullLength = Json::getInt(attachmentMap, "hull", 0); + + entry = Json::getItem(attachmentMap, "edges"); + if (entry) { + mesh->_edges.ensureCapacity(entry->_size); + mesh->_edges.setSize(entry->_size, 0); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + mesh->_edges[ii] = entry->_valueInt; + } + _attachmentLoader->configureAttachment(mesh); + } else { + bool inheritDeform = Json::getInt(attachmentMap, "deform", 1) ? true : false; + LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, + String(Json::getString( + attachmentMap, + "skin", 0)), + slot->getIndex(), + String(entry->_valueString), + inheritDeform); + _linkedMeshes.add(linkedMesh); + } + break; + } + case AttachmentType_Boundingbox: { + attachment = _attachmentLoader->newBoundingBoxAttachment(*skin, attachmentName); + + BoundingBoxAttachment *box = static_cast(attachment); + + int vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; + readVertices(attachmentMap, box, vertexCount); + color = Json::getString(attachmentMap, "color", NULL); + if (color) toColor(box->getColor(), color, true); + _attachmentLoader->configureAttachment(attachment); + break; + } + case AttachmentType_Path: { + attachment = _attachmentLoader->newPathAttachment(*skin, attachmentName); + + PathAttachment *pathAttatchment = static_cast(attachment); + + int vertexCount = 0; + pathAttatchment->_closed = Json::getInt(attachmentMap, "closed", 0) ? true : false; + pathAttatchment->_constantSpeed = Json::getInt(attachmentMap, "constantSpeed", 1) ? true + : false; + vertexCount = Json::getInt(attachmentMap, "vertexCount", 0); + readVertices(attachmentMap, pathAttatchment, vertexCount << 1); + + pathAttatchment->_lengths.ensureCapacity(vertexCount / 3); + pathAttatchment->_lengths.setSize(vertexCount / 3, 0); + + curves = Json::getItem(attachmentMap, "lengths"); + for (curves = curves->_child, ii = 0; curves; curves = curves->_next, ++ii) + pathAttatchment->_lengths[ii] = curves->_valueFloat * _scale; + color = Json::getString(attachmentMap, "color", NULL); + if (color) toColor(pathAttatchment->getColor(), color, true); + _attachmentLoader->configureAttachment(attachment); + break; + } + case AttachmentType_Point: { + attachment = _attachmentLoader->newPointAttachment(*skin, attachmentName); + + PointAttachment *point = static_cast(attachment); + + point->_x = Json::getFloat(attachmentMap, "x", 0) * _scale; + point->_y = Json::getFloat(attachmentMap, "y", 0) * _scale; + point->_rotation = Json::getFloat(attachmentMap, "rotation", 0); + color = Json::getString(attachmentMap, "color", NULL); + if (color) toColor(point->getColor(), color, true); + _attachmentLoader->configureAttachment(attachment); + break; + } + case AttachmentType_Clipping: { + attachment = _attachmentLoader->newClippingAttachment(*skin, attachmentName); + + ClippingAttachment *clip = static_cast(attachment); + + int vertexCount = 0; + const char *end = Json::getString(attachmentMap, "end", 0); + if (end) clip->_endSlot = skeletonData->findSlot(end); + vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; + readVertices(attachmentMap, clip, vertexCount); + color = Json::getString(attachmentMap, "color", NULL); + if (color) toColor(clip->getColor(), color, true); + _attachmentLoader->configureAttachment(attachment); + break; + } + } + + skin->setAttachment(slot->getIndex(), skinAttachmentName, attachment); + } + } + } + } + + /* Linked meshes. */ + int n = _linkedMeshes.size(); + for (i = 0; i < n; ++i) { + LinkedMesh *linkedMesh = _linkedMeshes[i]; + Skin *skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin(linkedMesh->_skin); + if (skin == NULL) { + delete skeletonData; + setError(root, "Skin not found: ", linkedMesh->_skin.buffer()); + return NULL; + } + Attachment *parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); + if (parent == NULL) { + delete skeletonData; + setError(root, "Parent mesh not found: ", linkedMesh->_parent.buffer()); + return NULL; + } + linkedMesh->_mesh->_deformAttachment = linkedMesh->_inheritDeform ? static_cast(parent) + : linkedMesh->_mesh; + linkedMesh->_mesh->setParentMesh(static_cast(parent)); + linkedMesh->_mesh->updateUVs(); + _attachmentLoader->configureAttachment(linkedMesh->_mesh); + } + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + /* Events. */ + events = Json::getItem(root, "events"); + if (events) { + Json *eventMap; + skeletonData->_events.ensureCapacity(events->_size); + skeletonData->_events.setSize(events->_size, 0); + for (eventMap = events->_child, i = 0; eventMap; eventMap = eventMap->_next, ++i) { + EventData *eventData = new (__FILE__, __LINE__) EventData(String(eventMap->_name)); + + eventData->_intValue = Json::getInt(eventMap, "int", 0); + eventData->_floatValue = Json::getFloat(eventMap, "float", 0); + const char *stringValue = Json::getString(eventMap, "string", 0); + eventData->_stringValue = stringValue; + const char *audioPath = Json::getString(eventMap, "audio", 0); + eventData->_audioPath = audioPath; + if (audioPath) { + eventData->_volume = Json::getFloat(eventMap, "volume", 1); + eventData->_balance = Json::getFloat(eventMap, "balance", 0); + } + skeletonData->_events[i] = eventData; + } + } + + /* Animations. */ + animations = Json::getItem(root, "animations"); + if (animations) { + Json *animationMap; + skeletonData->_animations.ensureCapacity(animations->_size); + skeletonData->_animations.setSize(animations->_size, 0); + int animationsIndex = 0; + for (animationMap = animations->_child; animationMap; animationMap = animationMap->_next) { + Animation *animation = readAnimation(animationMap, skeletonData); + if (!animation) { + delete skeletonData; + delete root; + return NULL; + } + skeletonData->_animations[animationsIndex++] = animation; + } + } + + delete root; + + return skeletonData; +} + +void SkeletonJson::setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1, + float cy1, + float cx2, float cy2, float time2, float value2) { + timeline->setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2); +} + +int SkeletonJson::readCurve(Json *curve, CurveTimeline *timeline, int bezier, int frame, int value, float time1, + float time2, + float value1, float value2, float scale) { + if (curve->_type == Json::JSON_STRING && strcmp(curve->_valueString, "stepped") == 0) { + timeline->setStepped(frame); + return bezier; + } + curve = Json::getItem(curve, value << 2); + float cx1 = curve->_valueFloat; + curve = curve->_next; + float cy1 = curve->_valueFloat * scale; + curve = curve->_next; + float cx2 = curve->_valueFloat; + curve = curve->_next; + float cy2 = curve->_valueFloat * scale; + setBezier(timeline, frame, value, bezier, time1, value1, cx1, cy1, cx2, cy2, time2, value2); + return bezier + 1; +} + +Timeline *SkeletonJson::readTimeline(Json *keyMap, CurveTimeline1 *timeline, float defaultValue, float scale) { + float time = Json::getFloat(keyMap, "time", 0); + float value = Json::getFloat(keyMap, "value", defaultValue) * scale; + int bezier = 0; + for (int frame = 0;; frame++) { + timeline->setFrame(frame, time, value); + Json *nextMap = keyMap->_next; + if (!nextMap) break; + float time2 = Json::getFloat(nextMap, "time", 0); + float value2 = Json::getFloat(nextMap, "value", defaultValue) * scale; + Json *curve = Json::getItem(keyMap, "curve"); + if (curve != NULL) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value, value2, scale); + time = time2; + value = value2; + keyMap = nextMap; + } + // timeline.shrink(); // BOZO + return timeline; +} + +Timeline *SkeletonJson::readTimeline(Json *keyMap, CurveTimeline2 *timeline, const char *name1, const char *name2, + float defaultValue, float scale) { + float time = Json::getFloat(keyMap, "time", 0); + float value1 = Json::getFloat(keyMap, name1, defaultValue) * scale; + float value2 = Json::getFloat(keyMap, name2, defaultValue) * scale; + int bezier = 0; + for (int frame = 0;; frame++) { + timeline->setFrame(frame, time, value1, value2); + Json *nextMap = keyMap->_next; + if (!nextMap) break; + float time2 = Json::getFloat(nextMap, "time", 0); + float nvalue1 = Json::getFloat(nextMap, name1, defaultValue) * scale; + float nvalue2 = Json::getFloat(nextMap, name2, defaultValue) * scale; + Json *curve = Json::getItem(keyMap, "curve"); + if (curve != NULL) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + keyMap = nextMap; + } + // timeline.shrink(); // BOZO + return timeline; +} + +int SkeletonJson::findSlotIndex(SkeletonData *skeletonData, const String &slotName, Vector timelines) { + int slotIndex = ContainerUtil::findIndexWithName(skeletonData->getSlots(), slotName); + if (slotIndex == -1) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Slot not found: ", slotName); + } + return slotIndex; +} + +Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) { + Vector timelines; + Json *bones = Json::getItem(root, "bones"); + Json *slots = Json::getItem(root, "slots"); + Json *ik = Json::getItem(root, "ik"); + Json *transform = Json::getItem(root, "transform"); + Json *paths = Json::getItem(root, "path"); + Json *deform = Json::getItem(root, "deform"); + Json *drawOrder = Json::getItem(root, "drawOrder"); + Json *events = Json::getItem(root, "events"); + Json *boneMap, *slotMap, *constraintMap, *keyMap, *nextMap, *curve; + int frame, bezier; + Color color, color2, newColor, newColor2; + + /** Slot timelines. */ + for (slotMap = slots ? slots->_child : 0; slotMap; slotMap = slotMap->_next) { + int slotIndex = findSlotIndex(skeletonData, slotMap->_name, timelines); + if (slotIndex == -1) return NULL; + + for (Json *timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) { + int frames = timelineMap->_size; + if (strcmp(timelineMap->_name, "attachment") == 0) { + AttachmentTimeline *timeline = new (__FILE__, __LINE__) AttachmentTimeline(frames, slotIndex); + for (keyMap = timelineMap->_child, frame = 0; keyMap; keyMap = keyMap->_next, ++frame) { + timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0), + Json::getItem(keyMap, "name")->_valueString); + } + timelines.add(timeline); + + } else if (strcmp(timelineMap->_name, "rgba") == 0) { + RGBATimeline *timeline = new (__FILE__, __LINE__) RGBATimeline(frames, frames << 2, slotIndex); + keyMap = timelineMap->_child; + float time = Json::getFloat(keyMap, "time", 0); + toColor(color, Json::getString(keyMap, "color", 0), true); + + for (frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b, color.a); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + toColor(newColor, Json::getString(nextMap, "color", 0), true); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (strcmp(timelineMap->_name, "rgb") == 0) { + RGBTimeline *timeline = new (__FILE__, __LINE__) RGBTimeline(frames, frames * 3, slotIndex); + keyMap = timelineMap->_child; + float time = Json::getFloat(keyMap, "time", 0); + toColor(color, Json::getString(keyMap, "color", 0), false); + + for (frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + toColor(newColor, Json::getString(nextMap, "color", 0), false); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (strcmp(timelineMap->_name, "alpha") == 0) { + timelines.add(readTimeline(timelineMap->_child, + new (__FILE__, __LINE__) AlphaTimeline(frames, frames, slotIndex), + 0, 1)); + } else if (strcmp(timelineMap->_name, "rgba2") == 0) { + RGBA2Timeline *timeline = new (__FILE__, __LINE__) RGBA2Timeline(frames, frames * 7, slotIndex); + keyMap = timelineMap->_child; + float time = Json::getFloat(keyMap, "time", 0); + toColor(color, Json::getString(keyMap, "light", 0), true); + toColor(color2, Json::getString(keyMap, "dark", 0), false); + + for (frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b, color.a, color2.g, color2.g, color2.b); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + toColor(newColor, Json::getString(nextMap, "light", 0), true); + toColor(newColor2, Json::getString(nextMap, "dark", 0), false); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (strcmp(timelineMap->_name, "rgb2") == 0) { + RGBA2Timeline *timeline = new (__FILE__, __LINE__) RGBA2Timeline(frames, frames * 6, slotIndex); + keyMap = timelineMap->_child; + float time = Json::getFloat(keyMap, "time", 0); + toColor(color, Json::getString(keyMap, "light", 0), false); + toColor(color2, Json::getString(keyMap, "dark", 0), false); + + for (frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + toColor(newColor, Json::getString(nextMap, "light", 0), false); + toColor(newColor2, Json::getString(nextMap, "dark", 0), false); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.add(timeline); + } else { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Invalid timeline type for a slot: ", timelineMap->_name); + return NULL; + } + } + } + + /** Bone timelines. */ + for (boneMap = bones ? bones->_child : 0; boneMap; boneMap = boneMap->_next) { + int boneIndex = ContainerUtil::findIndexWithName(skeletonData->_bones, boneMap->_name); + if (boneIndex == -1) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Bone not found: ", boneMap->_name); + return NULL; + } + + for (Json *timelineMap = boneMap->_child; timelineMap; timelineMap = timelineMap->_next) { + int frames = timelineMap->_size; + if (frames == 0) continue; + + if (strcmp(timelineMap->_name, "rotate") == 0) { + timelines.add(readTimeline(timelineMap->_child, + new RotateTimeline(frames, frames, boneIndex), 0, + 1)); + } else if (strcmp(timelineMap->_name, "translate") == 0) { + TranslateTimeline *timeline = new TranslateTimeline(frames, frames << 1, + boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, "x", "y", 0, _scale)); + } else if (strcmp(timelineMap->_name, "translatex") == 0) { + TranslateXTimeline *timeline = new TranslateXTimeline(frames, frames, + boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 0, _scale)); + } else if (strcmp(timelineMap->_name, "translatey") == 0) { + TranslateYTimeline *timeline = new TranslateYTimeline(frames, frames, + boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 0, _scale)); + } else if (strcmp(timelineMap->_name, "scale") == 0) { + ScaleTimeline *timeline = new (__FILE__, __LINE__) ScaleTimeline(frames, + frames << 1, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, "x", "y", 1, 1)); + } else if (strcmp(timelineMap->_name, "scalex") == 0) { + ScaleXTimeline *timeline = new (__FILE__, __LINE__) ScaleXTimeline(frames, + frames, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 1, 1)); + } else if (strcmp(timelineMap->_name, "scaley") == 0) { + ScaleYTimeline *timeline = new (__FILE__, __LINE__) ScaleYTimeline(frames, + frames, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 1, 1)); + } else if (strcmp(timelineMap->_name, "shear") == 0) { + ShearTimeline *timeline = new (__FILE__, __LINE__) ShearTimeline(frames, + frames << 1, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, "x", "y", 0, 1)); + } else if (strcmp(timelineMap->_name, "shearx") == 0) { + ShearXTimeline *timeline = new (__FILE__, __LINE__) ShearXTimeline(frames, + frames, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 0, 1)); + } else if (strcmp(timelineMap->_name, "sheary") == 0) { + ShearYTimeline *timeline = new (__FILE__, __LINE__) ShearYTimeline(frames, + frames, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 0, 1)); + } else { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Invalid timeline type for a bone: ", timelineMap->_name); + return NULL; + } + } + } + + /** IK constraint timelines. */ + for (constraintMap = ik ? ik->_child : 0; constraintMap; constraintMap = constraintMap->_next) { + keyMap = constraintMap->_child; + if (keyMap == NULL) continue; + + IkConstraintData *constraint = skeletonData->findIkConstraint(constraintMap->_name); + int constraintIndex = skeletonData->_ikConstraints.indexOf(constraint); + IkConstraintTimeline *timeline = new (__FILE__, __LINE__) IkConstraintTimeline(constraintMap->_size, + constraintMap->_size << 1, + constraintIndex); + + float time = Json::getFloat(keyMap, "time", 0); + float mix = Json::getFloat(keyMap, "mix", 1); + float softness = Json::getFloat(keyMap, "softness", 0) * _scale; + + for (frame = 0, bezier = 0;; frame++) { + int bendDirection = Json::getBoolean(keyMap, "bendPositive", true) ? 1 : -1; + timeline->setFrame(frame, time, mix, softness, bendDirection, Json::getBoolean(keyMap, "compress", false), + Json::getBoolean(keyMap, "stretch", false)); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + + float time2 = Json::getFloat(nextMap, "time", 0); + float mix2 = Json::getFloat(nextMap, "mix", 1); + float softness2 = Json::getFloat(nextMap, "softness", 0) * _scale; + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, _scale); + } + + time = time2; + mix = mix2; + softness = softness2; + keyMap = nextMap; + } + + timelines.add(timeline); + } + + /** Transform constraint timelines. */ + for (constraintMap = transform ? transform->_child : 0; constraintMap; constraintMap = constraintMap->_next) { + keyMap = constraintMap->_child; + if (keyMap == NULL) continue; + + TransformConstraintData *constraint = skeletonData->findTransformConstraint(constraintMap->_name); + int constraintIndex = skeletonData->_transformConstraints.indexOf(constraint); + TransformConstraintTimeline *timeline = new (__FILE__, __LINE__) TransformConstraintTimeline( + constraintMap->_size, constraintMap->_size << 2, constraintIndex); + + float time = Json::getFloat(keyMap, "time", 0); + float mixRotate = Json::getFloat(keyMap, "mixRotate", 1); + float mixShearY = Json::getFloat(keyMap, "mixShearY", 1); + float mixX = Json::getFloat(keyMap, "mixX", 1); + float mixY = Json::getFloat(keyMap, "mixY", mixX); + float mixScaleX = Json::getFloat(keyMap, "mixScaleX", 1); + float mixScaleY = Json::getFloat(keyMap, "mixScaleY", mixScaleX); + + for (frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + + float time2 = Json::getFloat(nextMap, "time", 0); + float mixRotate2 = Json::getFloat(nextMap, "mixRotate", 1); + float mixShearY2 = Json::getFloat(nextMap, "mixShearY", 1); + float mixX2 = Json::getFloat(nextMap, "mixX", 1); + float mixY2 = Json::getFloat(nextMap, "mixY", mixX2); + float mixScaleX2 = Json::getFloat(nextMap, "mixScaleX", 1); + float mixScaleY2 = Json::getFloat(nextMap, "mixScaleY", mixScaleX2); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixScaleX = mixScaleX2; + keyMap = nextMap; + } + + timelines.add(timeline); + } + + /** Path constraint timelines. */ + for (constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) { + PathConstraintData *constraint = skeletonData->findPathConstraint(constraintMap->_name); + if (!constraint) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Path constraint not found: ", constraintMap->_name); + return NULL; + } + int constraintIndex = skeletonData->_pathConstraints.indexOf(constraint); + for (Json *timelineMap = constraintMap->_child; timelineMap; timelineMap = timelineMap->_next) { + keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + const char *timelineName = timelineMap->_name; + int frames = timelineMap->_size; + if (strcmp(timelineName, "position") == 0) { + PathConstraintPositionTimeline *timeline = new (__FILE__, __LINE__) PathConstraintPositionTimeline( + frames, frames, constraintIndex); + timelines.add( + readTimeline(keyMap, timeline, 0, constraint->_positionMode == PositionMode_Fixed ? _scale : 1)); + } else if (strcmp(timelineName, "spacing") == 0) { + CurveTimeline1 *timeline = new PathConstraintSpacingTimeline(frames, frames, + constraintIndex); + timelines.add(readTimeline(keyMap, timeline, 0, + constraint->_spacingMode == SpacingMode_Length || + constraint->_spacingMode == SpacingMode_Fixed + ? _scale + : 1)); + } else if (strcmp(timelineName, "mix") == 0) { + PathConstraintMixTimeline *timeline = new PathConstraintMixTimeline(frames, + frames * 3, constraintIndex); + float time = Json::getFloat(keyMap, "time", 0); + float mixRotate = Json::getFloat(keyMap, "mixRotate", 1); + float mixX = Json::getFloat(keyMap, "mixX", 1); + float mixY = Json::getFloat(keyMap, "mixY", mixX); + for (frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + float mixRotate2 = Json::getFloat(nextMap, "mixRotate", 1); + float mixX2 = Json::getFloat(nextMap, "mixX", 1); + float mixY2 = Json::getFloat(nextMap, "mixY", mixX2); + curve = Json::getItem(keyMap, "curve"); + if (curve != NULL) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + keyMap = nextMap; + } + timelines.add(timeline); + } + } + } + + /** Deform timelines. */ + for (constraintMap = deform ? deform->_child : NULL; constraintMap; constraintMap = constraintMap->_next) { + Skin *skin = skeletonData->findSkin(constraintMap->_name); + for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) { + int slotIndex = findSlotIndex(skeletonData, slotMap->_name, timelines); + if (slotIndex == -1) return NULL; + + for (Json *timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) { + keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + + Attachment *baseAttachment = skin->getAttachment(slotIndex, timelineMap->_name); + if (!baseAttachment) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Attachment not found: ", timelineMap->_name); + return NULL; + } + VertexAttachment *attachment = static_cast(baseAttachment); + + bool weighted = attachment->_bones.size() != 0; + Vector &verts = attachment->_vertices; + int deformLength = weighted ? verts.size() / 3 * 2 : verts.size(); + + DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(timelineMap->_size, + timelineMap->_size, slotIndex, + attachment); + float time = Json::getFloat(keyMap, "time", 0); + for (frame = 0, bezier = 0;; frame++) { + Json *vertices = Json::getItem(keyMap, "vertices"); + Vector deformed; + if (!vertices) { + if (weighted) { + deformed.setSize(deformLength, 0); + } else { + deformed.clearAndAddAll(attachment->_vertices); + } + } else { + int v, start = Json::getInt(keyMap, "offset", 0); + Json *vertex; + deformed.setSize(deformLength, 0); + if (_scale == 1) { + for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { + deformed[v] = vertex->_valueFloat; + } + } else { + for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { + deformed[v] = vertex->_valueFloat * _scale; + } + } + if (!weighted) { + Vector &verticesAttachment = attachment->_vertices; + for (v = 0; v < deformLength; ++v) { + deformed[v] += verticesAttachment[v]; + } + } + } + timeline->setFrame(frame, time, deformed); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1); + } + time = time2; + keyMap = nextMap; + } + timelines.add(timeline); + } + } + } + + /** Draw order timeline. */ + if (drawOrder) { + DrawOrderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderTimeline(drawOrder->_size); + + for (keyMap = drawOrder->_child, frame = 0; keyMap; keyMap = keyMap->_next, ++frame) { + int ii; + Vector drawOrder2; + Json *offsets = Json::getItem(keyMap, "offsets"); + if (offsets) { + Json *offsetMap; + Vector unchanged; + unchanged.ensureCapacity(skeletonData->_slots.size() - offsets->_size); + unchanged.setSize(skeletonData->_slots.size() - offsets->_size, 0); + size_t originalIndex = 0, unchangedIndex = 0; + + drawOrder2.ensureCapacity(skeletonData->_slots.size()); + drawOrder2.setSize(skeletonData->_slots.size(), 0); + for (ii = (int) skeletonData->_slots.size() - 1; ii >= 0; --ii) + drawOrder2[ii] = -1; + + for (offsetMap = offsets->_child; offsetMap; offsetMap = offsetMap->_next) { + int slotIndex = findSlotIndex(skeletonData, Json::getString(offsetMap, "slot", 0), timelines); + if (slotIndex == -1) return NULL; + + /* Collect unchanged items. */ + while (originalIndex != (size_t) slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + /* Set changed items. */ + drawOrder2[originalIndex + Json::getInt(offsetMap, "offset", 0)] = originalIndex; + originalIndex++; + } + /* Collect remaining unchanged items. */ + while (originalIndex < skeletonData->_slots.size()) + unchanged[unchangedIndex++] = originalIndex++; + /* Fill in unchanged items. */ + for (ii = (int) skeletonData->_slots.size() - 1; ii >= 0; ii--) + if (drawOrder2[ii] == -1) drawOrder2[ii] = unchanged[--unchangedIndex]; + } + timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0), drawOrder2); + } + timelines.add(timeline); + } + + /** Event timeline. */ + if (events) { + EventTimeline *timeline = new (__FILE__, __LINE__) EventTimeline(events->_size); + + for (keyMap = events->_child, frame = 0; keyMap; keyMap = keyMap->_next, ++frame) { + Event *event; + EventData *eventData = skeletonData->findEvent(Json::getString(keyMap, "name", 0)); + if (!eventData) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Event not found: ", Json::getString(keyMap, "name", 0)); + return NULL; + } + + event = new (__FILE__, __LINE__) Event(Json::getFloat(keyMap, "time", 0), *eventData); + event->_intValue = Json::getInt(keyMap, "int", eventData->_intValue); + event->_floatValue = Json::getFloat(keyMap, "float", eventData->_floatValue); + event->_stringValue = Json::getString(keyMap, "string", eventData->_stringValue.buffer()); + if (!eventData->_audioPath.isEmpty()) { + event->_volume = Json::getFloat(keyMap, "volume", 1); + event->_balance = Json::getFloat(keyMap, "balance", 0); + } + timeline->setFrame(frame, event); + } + timelines.add(timeline); + } + + float duration = 0; + for (size_t i = 0; i < timelines.size(); i++) + duration = MathUtil::max(duration, timelines[i]->getDuration()); + return new (__FILE__, __LINE__) Animation(String(root->_name), timelines, duration); +} + +void SkeletonJson::readVertices(Json *attachmentMap, VertexAttachment *attachment, size_t verticesLength) { + Json *entry; + size_t i, n, nn, entrySize; + Vector vertices; + + attachment->setWorldVerticesLength(verticesLength); + + entry = Json::getItem(attachmentMap, "vertices"); + entrySize = entry->_size; + vertices.ensureCapacity(entrySize); + vertices.setSize(entrySize, 0); + for (entry = entry->_child, i = 0; entry; entry = entry->_next, ++i) + vertices[i] = entry->_valueFloat; + + if (verticesLength == entrySize) { + if (_scale != 1) { + for (i = 0; i < entrySize; ++i) + vertices[i] *= _scale; + } + + attachment->getVertices().clearAndAddAll(vertices); + return; + } + + Vertices bonesAndWeights; + bonesAndWeights._bones.ensureCapacity(verticesLength * 3); + bonesAndWeights._vertices.ensureCapacity(verticesLength * 3 * 3); + + for (i = 0, n = entrySize; i < n;) { + int boneCount = (int) vertices[i++]; + bonesAndWeights._bones.add(boneCount); + for (nn = i + boneCount * 4; i < nn; i += 4) { + bonesAndWeights._bones.add((int) vertices[i]); + bonesAndWeights._vertices.add(vertices[i + 1] * _scale); + bonesAndWeights._vertices.add(vertices[i + 2] * _scale); + bonesAndWeights._vertices.add(vertices[i + 3]); + } + } + + attachment->getVertices().clearAndAddAll(bonesAndWeights._vertices); + attachment->getBones().clearAndAddAll(bonesAndWeights._bones); +} + +void SkeletonJson::setError(Json *root, const String &value1, const String &value2) { + _error = String(value1).append(value2); + delete root; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Skin.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Skin.cpp new file mode 100644 index 0000000..b5c75a3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -0,0 +1,199 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include + +#include +#include + +#include + +using namespace spine; + +Skin::AttachmentMap::AttachmentMap() { +} + +static void disposeAttachment(Attachment *attachment) { + if (!attachment) return; + attachment->dereference(); + if (attachment->getRefCount() == 0) delete attachment; +} + +void Skin::AttachmentMap::put(size_t slotIndex, const String &attachmentName, Attachment *attachment) { + if (slotIndex >= _buckets.size()) + _buckets.setSize(slotIndex + 1, Vector()); + Vector &bucket = _buckets[slotIndex]; + int existing = findInBucket(bucket, attachmentName); + attachment->reference(); + if (existing >= 0) { + disposeAttachment(bucket[existing]._attachment); + bucket[existing]._attachment = attachment; + } else { + bucket.add(Entry(slotIndex, attachmentName, attachment)); + } +} + +Attachment *Skin::AttachmentMap::get(size_t slotIndex, const String &attachmentName) { + if (slotIndex >= _buckets.size()) return NULL; + int existing = findInBucket(_buckets[slotIndex], attachmentName); + return existing >= 0 ? _buckets[slotIndex][existing]._attachment : NULL; +} + +void Skin::AttachmentMap::remove(size_t slotIndex, const String &attachmentName) { + if (slotIndex >= _buckets.size()) return; + int existing = findInBucket(_buckets[slotIndex], attachmentName); + if (existing >= 0) { + disposeAttachment(_buckets[slotIndex][existing]._attachment); + _buckets[slotIndex].removeAt(existing); + } +} + +int Skin::AttachmentMap::findInBucket(Vector &bucket, const String &attachmentName) { + for (size_t i = 0; i < bucket.size(); i++) + if (bucket[i]._name == attachmentName) return i; + return -1; +} + +Skin::AttachmentMap::Entries Skin::AttachmentMap::getEntries() { + return Skin::AttachmentMap::Entries(_buckets); +} + +Skin::Skin(const String &name) : _name(name), _attachments() { + assert(_name.length() > 0); +} + +Skin::~Skin() { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry entry = entries.next(); + disposeAttachment(entry._attachment); + } +} + +void Skin::setAttachment(size_t slotIndex, const String &name, Attachment *attachment) { + assert(attachment); + _attachments.put(slotIndex, name, attachment); +} + +Attachment *Skin::getAttachment(size_t slotIndex, const String &name) { + return _attachments.get(slotIndex, name); +} + +void Skin::removeAttachment(size_t slotIndex, const String &name) { + _attachments.remove(slotIndex, name); +} + +void Skin::findNamesForSlot(size_t slotIndex, Vector &names) { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == slotIndex) { + names.add(entry._name); + } + } +} + +void Skin::findAttachmentsForSlot(size_t slotIndex, Vector &attachments) { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == slotIndex) attachments.add(entry._attachment); + } +} + +const String &Skin::getName() { + return _name; +} + +Skin::AttachmentMap::Entries Skin::getAttachments() { + return _attachments.getEntries(); +} + +void Skin::attachAll(Skeleton &skeleton, Skin &oldSkin) { + Vector &slots = skeleton.getSlots(); + Skin::AttachmentMap::Entries entries = oldSkin.getAttachments(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + int slotIndex = entry._slotIndex; + Slot *slot = slots[slotIndex]; + + if (slot->getAttachment() == entry._attachment) { + Attachment *attachment = getAttachment(slotIndex, entry._name); + if (attachment) slot->setAttachment(attachment); + } + } +} + +void Skin::addSkin(Skin *other) { + for (size_t i = 0; i < other->getBones().size(); i++) + if (!_bones.contains(other->getBones()[i])) _bones.add(other->getBones()[i]); + + for (size_t i = 0; i < other->getConstraints().size(); i++) + if (!_constraints.contains(other->getConstraints()[i])) _constraints.add(other->getConstraints()[i]); + + AttachmentMap::Entries entries = other->getAttachments(); + while (entries.hasNext()) { + AttachmentMap::Entry &entry = entries.next(); + setAttachment(entry._slotIndex, entry._name, entry._attachment); + } +} + +void Skin::copySkin(Skin *other) { + for (size_t i = 0; i < other->getBones().size(); i++) + if (!_bones.contains(other->getBones()[i])) _bones.add(other->getBones()[i]); + + for (size_t i = 0; i < other->getConstraints().size(); i++) + if (!_constraints.contains(other->getConstraints()[i])) _constraints.add(other->getConstraints()[i]); + + AttachmentMap::Entries entries = other->getAttachments(); + while (entries.hasNext()) { + AttachmentMap::Entry &entry = entries.next(); + if (entry._attachment->getRTTI().isExactly(MeshAttachment::rtti)) + setAttachment(entry._slotIndex, entry._name, + static_cast(entry._attachment)->newLinkedMesh()); + else + setAttachment(entry._slotIndex, entry._name, entry._attachment->copy()); + } +} + +Vector &Skin::getConstraints() { + return _constraints; +} + +Vector &Skin::getBones() { + return _bones; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Slot.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Slot.cpp new file mode 100644 index 0000000..34f69ac --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -0,0 +1,132 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +Slot::Slot(SlotData &data, Bone &bone) : _data(data), + _bone(bone), + _skeleton(bone.getSkeleton()), + _color(1, 1, 1, 1), + _darkColor(0, 0, 0, 0), + _hasDarkColor(data.hasDarkColor()), + _attachment(NULL), + _attachmentState(0), + _attachmentTime(0) { + setToSetupPose(); +} + +void Slot::setToSetupPose() { + _color.set(_data.getColor()); + if (_hasDarkColor) _darkColor.set(_data.getDarkColor()); + + const String &attachmentName = _data.getAttachmentName(); + if (attachmentName.length() > 0) { + _attachment = NULL; + setAttachment(_skeleton.getAttachment(_data.getIndex(), attachmentName)); + } else { + setAttachment(NULL); + } +} + +SlotData &Slot::getData() { + return _data; +} + +Bone &Slot::getBone() { + return _bone; +} + +Skeleton &Slot::getSkeleton() { + return _skeleton; +} + +Color &Slot::getColor() { + return _color; +} + +Color &Slot::getDarkColor() { + return _darkColor; +} + +bool Slot::hasDarkColor() { + return _hasDarkColor; +} + +Attachment *Slot::getAttachment() { + return _attachment; +} + +void Slot::setAttachment(Attachment *inValue) { + if (_attachment == inValue) { + return; + } + + if (!inValue || + !_attachment || + !inValue->getRTTI().instanceOf(VertexAttachment::rtti) || + !_attachment->getRTTI().instanceOf(VertexAttachment::rtti) || + static_cast(inValue)->getDeformAttachment() != static_cast(_attachment)->getDeformAttachment()) { + _deform.clear(); + } + + _attachment = inValue; + _attachmentTime = _skeleton.getTime(); +} + +int Slot::getAttachmentState() { + return _attachmentState; +} + +void Slot::setAttachmentState(int state) { + _attachmentState = state; +} + +float Slot::getAttachmentTime() { + return _skeleton.getTime() - _attachmentTime; +} + +void Slot::setAttachmentTime(float inValue) { + _attachmentTime = _skeleton.getTime() - inValue; +} + +Vector &Slot::getDeform() { + return _deform; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SlotData.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SlotData.cpp new file mode 100644 index 0000000..850ecdb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SlotData.cpp @@ -0,0 +1,94 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +SlotData::SlotData(int index, const String &name, BoneData &boneData) : _index(index), + _name(name), + _boneData(boneData), + _color(1, 1, 1, 1), + _darkColor(0, 0, 0, 0), + _hasDarkColor(false), + _attachmentName(), + _blendMode(BlendMode_Normal) { + assert(_index >= 0); + assert(_name.length() > 0); +} + +int SlotData::getIndex() { + return _index; +} + +const String &SlotData::getName() { + return _name; +} + +BoneData &SlotData::getBoneData() { + return _boneData; +} + +Color &SlotData::getColor() { + return _color; +} + +Color &SlotData::getDarkColor() { + return _darkColor; +} + +bool SlotData::hasDarkColor() { + return _hasDarkColor; +} + +void SlotData::setHasDarkColor(bool inValue) { + _hasDarkColor = inValue; +} + +const String &SlotData::getAttachmentName() { + return _attachmentName; +} + +void SlotData::setAttachmentName(const String &inValue) { + _attachmentName = inValue; +} + +BlendMode SlotData::getBlendMode() { + return _blendMode; +} + +void SlotData::setBlendMode(BlendMode inValue) { + _blendMode = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SpineObject.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SpineObject.cpp new file mode 100644 index 0000000..60187ab --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/SpineObject.cpp @@ -0,0 +1,67 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include + +using namespace spine; + +void *SpineObject::operator new(size_t sz) { + return SpineExtension::getInstance()->_calloc(sz, __FILE__, __LINE__); +} + +void *SpineObject::operator new(size_t sz, const char *file, int line) { + return SpineExtension::getInstance()->_calloc(sz, file, line); +} + +void *SpineObject::operator new(size_t sz, void *ptr) { + SP_UNUSED(sz); + return ptr; +} + +void SpineObject::operator delete(void *p, const char *file, int line) { + SpineExtension::free(p, file, line); +} + +void SpineObject::operator delete(void *p, void *mem) { + SP_UNUSED(mem); + SpineExtension::free(p, __FILE__, __LINE__); +} + +void SpineObject::operator delete(void *p) { + SpineExtension::free(p, __FILE__, __LINE__); +} + +SpineObject::~SpineObject() { + SpineExtension::beforeFree(this); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp new file mode 100644 index 0000000..eb345e3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp @@ -0,0 +1,42 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +namespace spine { + TextureLoader::TextureLoader() { + } + + TextureLoader::~TextureLoader() { + } +}// namespace spine diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Timeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Timeline.cpp new file mode 100644 index 0000000..19f58ce --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Timeline.cpp @@ -0,0 +1,78 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +namespace spine { + RTTI_IMPL_NOPARENT(Timeline) + + Timeline::Timeline(size_t frameCount, size_t frameEntries) + : _propertyIds(), _frames(), _frameEntries(frameEntries) { + _frames.setSize(frameCount * frameEntries, 0); + } + + Timeline::~Timeline() { + } + + Vector &Timeline::getPropertyIds() { + return _propertyIds; + } + + void Timeline::setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount) { + _propertyIds.clear(); + _propertyIds.ensureCapacity(propertyIdsCount); + for (size_t i = 0; i < propertyIdsCount; i++) { + _propertyIds.add(propertyIds[i]); + } + } + + size_t Timeline::getFrameCount() { + return _frames.size() / _frameEntries; + } + + Vector &Timeline::getFrames() { + return _frames; + } + + size_t Timeline::getFrameEntries() { + return _frameEntries; + } + + float Timeline::getDuration() { + return _frames[_frames.size() - getFrameEntries()]; + } + +}// namespace spine diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp new file mode 100644 index 0000000..0e4fc53 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -0,0 +1,344 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(TransformConstraint, Updatable) + +TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : Updatable(), + _data(data), + _target(skeleton.findBone( + data.getTarget()->getName())), + _mixRotate( + data.getMixRotate()), + _mixX(data.getMixX()), + _mixY(data.getMixY()), + _mixScaleX( + data.getMixScaleX()), + _mixScaleY( + data.getMixScaleY()), + _mixShearY( + data.getMixShearY()), + _active(false) { + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); ++i) { + BoneData *boneData = _data.getBones()[i]; + _bones.add(skeleton.findBone(boneData->getName())); + } +} + +void TransformConstraint::update() { + if (_mixRotate == 0 && _mixX == 0 && _mixY == 0 && _mixScaleX == 0 && _mixScaleX == 0 && _mixShearY == 0) return; + + if (_data.isLocal()) { + if (_data.isRelative()) + applyRelativeLocal(); + else + applyAbsoluteLocal(); + } else { + if (_data.isRelative()) + applyRelativeWorld(); + else + applyAbsoluteWorld(); + } +} + +int TransformConstraint::getOrder() { + return _data.getOrder(); +} + +TransformConstraintData &TransformConstraint::getData() { + return _data; +} + +Vector &TransformConstraint::getBones() { + return _bones; +} + +Bone *TransformConstraint::getTarget() { + return _target; +} + +void TransformConstraint::setTarget(Bone *inValue) { + _target = inValue; +} + +float TransformConstraint::getMixRotate() { + return _mixRotate; +} + +void TransformConstraint::setMixRotate(float inValue) { + _mixRotate = inValue; +} + +float TransformConstraint::getMixX() { + return _mixX; +} + +void TransformConstraint::setMixX(float inValue) { + _mixX = inValue; +} + +float TransformConstraint::getMixY() { + return _mixY; +} + +void TransformConstraint::setMixY(float inValue) { + _mixY = inValue; +} + +void TransformConstraint::setMixScaleX(float inValue) { + _mixScaleX = inValue; +} + +float TransformConstraint::getMixScaleX() { + return _mixScaleX; +} + +float TransformConstraint::getMixScaleY() { + return _mixScaleY; +} + +void TransformConstraint::setMixScaleY(float inValue) { + _mixScaleY = inValue; +} + +float TransformConstraint::getMixShearY() { + return _mixShearY; +} + +void TransformConstraint::setMixShearY(float inValue) { + _mixShearY = inValue; +} + +void TransformConstraint::applyAbsoluteWorld() { + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; + bool translate = mixX != 0 || mixY != 0; + Bone &target = *_target; + float ta = target._a, tb = target._b, tc = target._c, td = target._d; + float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; + float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; + + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + if (mixRotate != 0) { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + float r = MathUtil::atan2(tc, ta) - MathUtil::atan2(c, a) + offsetRotation; + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r *= mixRotate; + float cos = MathUtil::cos(r), sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + } + + if (translate) { + float tx, ty; + target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); + bone._worldX += (tx - bone._worldX) * mixX; + bone._worldY += (ty - bone._worldY) * mixY; + } + + if (mixScaleX > 0) { + float s = MathUtil::sqrt(bone._a * bone._a + bone._c * bone._c); + if (s != 0) s = (s + (MathUtil::sqrt(ta * ta + tc * tc) - s + _data._offsetScaleX) * mixScaleX) / s; + bone._a *= s; + bone._c *= s; + } + + if (mixScaleY > 0) { + float s = MathUtil::sqrt(bone._b * bone._b + bone._d * bone._d); + if (s != 0) s = (s + (MathUtil::sqrt(tb * tb + td * td) - s + _data._offsetScaleY) * mixScaleY) / s; + bone._b *= s; + bone._d *= s; + } + + if (mixShearY > 0) { + float b = bone._b, d = bone._d; + float by = MathUtil::atan2(d, b); + float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta) - (by - MathUtil::atan2(bone._c, bone._a)); + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r = by + (r + offsetShearY) * mixShearY; + float s = MathUtil::sqrt(b * b + d * d); + bone._b = MathUtil::cos(r) * s; + bone._d = MathUtil::sin(r) * s; + } + + bone.updateAppliedTransform(); + } +} + +void TransformConstraint::applyRelativeWorld() { + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; + bool translate = mixX != 0 || mixY != 0; + Bone &target = *_target; + float ta = target._a, tb = target._b, tc = target._c, td = target._d; + float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; + float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + if (mixRotate != 0) { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + float r = MathUtil::atan2(tc, ta) + offsetRotation; + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r *= mixRotate; + float cos = MathUtil::cos(r), sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + } + + if (translate) { + float tx, ty; + target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); + bone._worldX += tx * mixX; + bone._worldY += ty * mixY; + } + + if (mixScaleX != 0) { + float s = (MathUtil::sqrt(ta * ta + tc * tc) - 1 + _data._offsetScaleX) * mixScaleX + 1; + bone._a *= s; + bone._c *= s; + } + if (mixScaleY != 0) { + float s = (MathUtil::sqrt(tb * tb + td * td) - 1 + _data._offsetScaleY) * mixScaleY + 1; + bone._b *= s; + bone._d *= s; + } + + if (mixShearY > 0) { + float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta); + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + float b = bone._b, d = bone._d; + r = MathUtil::atan2(d, b) + (r - MathUtil::Pi / 2 + offsetShearY) * mixShearY; + float s = MathUtil::sqrt(b * b + d * d); + bone._b = MathUtil::cos(r) * s; + bone._d = MathUtil::sin(r) * s; + } + + bone.updateAppliedTransform(); + } +} + +void TransformConstraint::applyAbsoluteLocal() { + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; + Bone &target = *_target; + + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + float rotation = bone._arotation; + if (mixRotate != 0) { + float r = target._arotation - rotation + _data._offsetRotation; + r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360; + rotation += r * mixRotate; + } + + float x = bone._ax, y = bone._ay; + x += (target._ax - x + _data._offsetX) * mixX; + y += (target._ay - y + _data._offsetY) * mixY; + + float scaleX = bone._ascaleX, scaleY = bone._ascaleY; + if (mixScaleX != 0 && scaleX != 0) + scaleX = (scaleX + (target._ascaleX - scaleX + _data._offsetScaleX) * mixScaleX) / scaleX; + if (mixScaleY != 0 && scaleY != 0) + scaleY = (scaleY + (target._ascaleY - scaleY + _data._offsetScaleY) * mixScaleY) / scaleY; + + float shearY = bone._ashearY; + if (mixShearY != 0) { + float r = target._ashearY - shearY + _data._offsetShearY; + r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360; + bone._shearY += r * mixShearY; + } + + bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); + } +} + +void TransformConstraint::applyRelativeLocal() { + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; + Bone &target = *_target; + + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + float rotation = bone._arotation + (target._arotation + _data._offsetRotation) * mixRotate; + float x = bone._ax + (target._ax + _data._offsetX) * mixX; + float y = bone._ay + (target._ay + _data._offsetY) * mixY; + float scaleX = bone._ascaleX * (((target._ascaleX - 1 + _data._offsetScaleX) * mixScaleX) + 1); + float scaleY = bone._ascaleY * (((target._ascaleY - 1 + _data._offsetScaleY) * mixScaleY) + 1); + float shearY = bone._ashearY + (target._ashearY + _data._offsetShearY) * mixShearY; + + bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); + } +} + +bool TransformConstraint::isActive() { + return _active; +} + +void TransformConstraint::setActive(bool inValue) { + _active = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp new file mode 100644 index 0000000..da634f6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -0,0 +1,122 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +#include + +using namespace spine; + +TransformConstraintData::TransformConstraintData(const String &name) : ConstraintData(name), + _target(NULL), + _mixRotate(0), + _mixX(0), + _mixY(0), + _mixScaleX(0), + _mixScaleY(0), + _mixShearY(0), + _offsetRotation(0), + _offsetX(0), + _offsetY(0), + _offsetScaleX(0), + _offsetScaleY(0), + _offsetShearY(0), + _relative(false), + _local(false) { +} + +Vector &TransformConstraintData::getBones() { + return _bones; +} + +BoneData *TransformConstraintData::getTarget() { + return _target; +} + +float TransformConstraintData::getMixRotate() { + return _mixRotate; +} + +float TransformConstraintData::getMixX() { + return _mixX; +} + +float TransformConstraintData::getMixY() { + return _mixY; +} + +float TransformConstraintData::getMixScaleX() { + return _mixScaleX; +} + +float TransformConstraintData::getMixScaleY() { + return _mixScaleY; +} + +float TransformConstraintData::getMixShearY() { + return _mixShearY; +} + +float TransformConstraintData::getOffsetRotation() { + return _offsetRotation; +} + +float TransformConstraintData::getOffsetX() { + return _offsetX; +} + +float TransformConstraintData::getOffsetY() { + return _offsetY; +} + +float TransformConstraintData::getOffsetScaleX() { + return _offsetScaleX; +} + +float TransformConstraintData::getOffsetScaleY() { + return _offsetScaleY; +} + +float TransformConstraintData::getOffsetShearY() { + return _offsetShearY; +} + +bool TransformConstraintData::isRelative() { + return _relative; +} + +bool TransformConstraintData::isLocal() { + return _local; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp new file mode 100644 index 0000000..c0ffd31 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -0,0 +1,161 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(TransformConstraintTimeline, CurveTimeline) + +TransformConstraintTimeline::TransformConstraintTimeline(size_t frameCount, size_t bezierCount, + int transformConstraintIndex) : CurveTimeline(frameCount, + TransformConstraintTimeline::ENTRIES, + bezierCount), + _transformConstraintIndex( + transformConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_TransformConstraint << 32) | transformConstraintIndex}; + setPropertyIds(ids, 1); +} + +void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + TransformConstraint *constraintP = skeleton._transformConstraints[_transformConstraintIndex]; + TransformConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + TransformConstraintData &data = constraint._data; + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._mixRotate = data._mixRotate; + constraint._mixX = data._mixX; + constraint._mixY = data._mixY; + constraint._mixScaleX = data._mixScaleX; + constraint._mixScaleY = data._mixScaleY; + constraint._mixShearY = data._mixShearY; + return; + case MixBlend_First: + constraint._mixRotate += (data._mixRotate - constraint._mixRotate) * alpha; + constraint._mixX += (data._mixX - constraint._mixX) * alpha; + constraint._mixY += (data._mixY - constraint._mixY) * alpha; + constraint._mixScaleX += (data._mixScaleX - constraint._mixScaleX) * alpha; + constraint._mixScaleY += (data._mixScaleY - constraint._mixScaleY) * alpha; + constraint._mixShearY += (data._mixShearY - constraint._mixShearY) * alpha; + return; + default: + return; + } + } + + float rotate, x, y, scaleX, scaleY, shearY; + int i = Animation::search(_frames, time, TransformConstraintTimeline::ENTRIES); + int curveType = (int) _curves[i / TransformConstraintTimeline::ENTRIES]; + switch (curveType) { + case TransformConstraintTimeline::LINEAR: { + float before = _frames[i]; + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + scaleX = _frames[i + SCALEX]; + scaleY = _frames[i + SCALEY]; + shearY = _frames[i + SHEARY]; + float t = (time - before) / (_frames[i + ENTRIES] - before); + rotate += (_frames[i + ENTRIES + ROTATE] - rotate) * t; + x += (_frames[i + ENTRIES + X] - x) * t; + y += (_frames[i + ENTRIES + Y] - y) * t; + scaleX += (_frames[i + ENTRIES + SCALEX] - scaleX) * t; + scaleY += (_frames[i + ENTRIES + SCALEY] - scaleY) * t; + shearY += (_frames[i + ENTRIES + SHEARY] - shearY) * t; + break; + } + case TransformConstraintTimeline::STEPPED: { + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + scaleX = _frames[i + SCALEX]; + scaleY = _frames[i + SCALEY]; + shearY = _frames[i + SHEARY]; + break; + } + default: { + rotate = getBezierValue(time, i, ROTATE, curveType - BEZIER); + x = getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER); + y = getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER); + scaleX = getBezierValue(time, i, SCALEX, curveType + BEZIER_SIZE * 3 - BEZIER); + scaleY = getBezierValue(time, i, SCALEY, curveType + BEZIER_SIZE * 4 - BEZIER); + shearY = getBezierValue(time, i, SHEARY, curveType + BEZIER_SIZE * 5 - BEZIER); + } + } + + if (blend == MixBlend_Setup) { + constraint._mixRotate = data._mixRotate + (rotate - data._mixRotate) * alpha; + constraint._mixX = data._mixX + (x - data._mixX) * alpha; + constraint._mixY = data._mixY + (y - data._mixY) * alpha; + constraint._mixScaleX = data._mixScaleX + (scaleX - data._mixScaleX) * alpha; + constraint._mixScaleY = data._mixScaleY + (scaleY - data._mixScaleY) * alpha; + constraint._mixShearY = data._mixShearY + (shearY - data._mixShearY) * alpha; + } else { + constraint._mixRotate += (rotate - constraint._mixRotate) * alpha; + constraint._mixX += (x - constraint._mixX) * alpha; + constraint._mixY += (y - constraint._mixY) * alpha; + constraint._mixScaleX += (scaleX - constraint._mixScaleX) * alpha; + constraint._mixScaleY += (scaleY - constraint._mixScaleY) * alpha; + constraint._mixShearY += (shearY - constraint._mixShearY) * alpha; + } +} + +void TransformConstraintTimeline::setFrame(size_t frame, float time, float mixRotate, float mixX, float mixY, + float mixScaleX, float mixScaleY, float mixShearY) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + ROTATE] = mixRotate; + _frames[frame + X] = mixX; + _frames[frame + Y] = mixY; + _frames[frame + SCALEX] = mixScaleX; + _frames[frame + SCALEY] = mixScaleY; + _frames[frame + SHEARY] = mixShearY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp new file mode 100644 index 0000000..72179a3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -0,0 +1,218 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(TranslateTimeline, CurveTimeline2) + +TranslateTimeline::TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_X << 32) | boneIndex, + ((PropertyId) Property_Y << 32) | boneIndex}; + setPropertyIds(ids, 2); +} + +TranslateTimeline::~TranslateTimeline() { +} + +void TranslateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_x = bone->_data._x; + bone->_y = bone->_data._y; + return; + case MixBlend_First: + bone->_x += (bone->_data._x - bone->_x) * alpha; + bone->_y += (bone->_data._y - bone->_y) * alpha; + default: { + } + } + return; + } + + float x = 0, y = 0; + int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES); + int curveType = (int) _curves[i / CurveTimeline2::ENTRIES]; + switch (curveType) { + case CurveTimeline::LINEAR: { + float before = _frames[i]; + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before); + x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t; + y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t; + break; + } + case CurveTimeline::STEPPED: { + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + break; + } + default: { + x = getBezierValue(time, i, CurveTimeline2::VALUE1, curveType - CurveTimeline::BEZIER); + y = getBezierValue(time, i, CurveTimeline2::VALUE2, + curveType + CurveTimeline::BEZIER_SIZE - CurveTimeline::BEZIER); + } + } + + switch (blend) { + case MixBlend_Setup: + bone->_x = bone->_data._x + x * alpha; + bone->_y = bone->_data._y + y * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_x += (bone->_data._x + x - bone->_x) * alpha; + bone->_y += (bone->_data._y + y - bone->_y) * alpha; + break; + case MixBlend_Add: + bone->_x += x * alpha; + bone->_y += y * alpha; + } +} + +RTTI_IMPL(TranslateXTimeline, CurveTimeline1) + +TranslateXTimeline::TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1( + frameCount, bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_X << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +TranslateXTimeline::~TranslateXTimeline() { +} + +void TranslateXTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_x = bone->_data._x; + return; + case MixBlend_First: + bone->_x += (bone->_data._x - bone->_x) * alpha; + default: { + } + } + return; + } + + float x = getCurveValue(time); + switch (blend) { + case MixBlend_Setup: + bone->_x = bone->_data._x + x * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_x += (bone->_data._x + x - bone->_x) * alpha; + break; + case MixBlend_Add: + bone->_x += x * alpha; + } +} + +RTTI_IMPL(TranslateYTimeline, CurveTimeline1) + +TranslateYTimeline::TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1( + frameCount, bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_Y << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +TranslateYTimeline::~TranslateYTimeline() { +} + +void TranslateYTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_y = bone->_data._y; + return; + case MixBlend_First: + bone->_y += (bone->_data._y - bone->_y) * alpha; + default: { + } + } + return; + } + + float y = getCurveValue(time); + switch (blend) { + case MixBlend_Setup: + bone->_y = bone->_data._y + y * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_y += (bone->_data._y + y - bone->_y) * alpha; + break; + case MixBlend_Add: + bone->_y += y * alpha; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Triangulator.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Triangulator.cpp new file mode 100644 index 0000000..c85b688 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Triangulator.cpp @@ -0,0 +1,289 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +using namespace spine; + +Triangulator::~Triangulator() { + ContainerUtil::cleanUpVectorOfPointers(_convexPolygons); + ContainerUtil::cleanUpVectorOfPointers(_convexPolygonsIndices); +} + +Vector &Triangulator::triangulate(Vector &vertices) { + size_t vertexCount = vertices.size() >> 1; + + Vector &indices = _indices; + indices.clear(); + indices.ensureCapacity(vertexCount); + indices.setSize(vertexCount, 0); + for (size_t i = 0; i < vertexCount; ++i) { + indices[i] = i; + } + + Vector &isConcaveArray = _isConcaveArray; + isConcaveArray.ensureCapacity(vertexCount); + isConcaveArray.setSize(vertexCount, 0); + for (size_t i = 0, n = vertexCount; i < n; ++i) { + isConcaveArray[i] = isConcave(i, vertexCount, vertices, indices); + } + + Vector &triangles = _triangles; + triangles.clear(); + triangles.ensureCapacity(MathUtil::max((int) 0, (int) vertexCount - 2) << 2); + + while (vertexCount > 3) { + // Find ear tip. + size_t previous = vertexCount - 1, i = 0, next = 1; + + // outer: + while (true) { + if (!isConcaveArray[i]) { + int p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + float p1x = vertices[p1], p1y = vertices[p1 + 1]; + float p2x = vertices[p2], p2y = vertices[p2 + 1]; + float p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (size_t ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcaveArray[ii]) continue; + + int v = indices[ii] << 1; + float &vx = vertices[v], vy = vertices[v + 1]; + if (positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (positiveArea(p2x, p2y, p3x, p3y, vx, vy)) { + goto break_outer;// break outer; + } + } + } + } + break; + } + break_outer: + + if (next == 0) { + do { + if (!isConcaveArray[i]) break; + i--; + } while (i > 0); + break; + } + + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + + // Cut ear tip. + triangles.add(indices[(vertexCount + i - 1) % vertexCount]); + triangles.add(indices[i]); + triangles.add(indices[(i + 1) % vertexCount]); + indices.removeAt(i); + isConcaveArray.removeAt(i); + vertexCount--; + + int previousIndex = (vertexCount + i - 1) % vertexCount; + int nextIndex = i == vertexCount ? 0 : i; + isConcaveArray[previousIndex] = isConcave(previousIndex, vertexCount, vertices, indices); + isConcaveArray[nextIndex] = isConcave(nextIndex, vertexCount, vertices, indices); + } + + if (vertexCount == 3) { + triangles.add(indices[2]); + triangles.add(indices[0]); + triangles.add(indices[1]); + } + + return triangles; +} + +Vector *> &Triangulator::decompose(Vector &vertices, Vector &triangles) { + Vector *> &convexPolygons = _convexPolygons; + for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) + _polygonPool.free(convexPolygons[i]); + convexPolygons.clear(); + + Vector *> &convexPolygonsIndices = _convexPolygonsIndices; + for (size_t i = 0, n = convexPolygonsIndices.size(); i < n; ++i) + _polygonIndicesPool.free(convexPolygonsIndices[i]); + convexPolygonsIndices.clear(); + + Vector *polygonIndices = _polygonIndicesPool.obtain(); + polygonIndices->clear(); + + Vector *polygon = _polygonPool.obtain(); + polygon->clear(); + + // Merge subsequent triangles if they form a triangle fan. + int fanBaseIndex = -1, lastwinding = 0; + for (size_t i = 0, n = triangles.size(); i < n; i += 3) { + int t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + float x1 = vertices[t1], y1 = vertices[t1 + 1]; + float x2 = vertices[t2], y2 = vertices[t2 + 1]; + float x3 = vertices[t3], y3 = vertices[t3 + 1]; + + // If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan). + bool merged = false; + if (fanBaseIndex == t1) { + size_t o = polygon->size() - 4; + Vector &p = *polygon; + int winding1 = winding(p[o], p[o + 1], p[o + 2], p[o + 3], x3, y3); + int winding2 = winding(x3, y3, p[0], p[1], p[2], p[3]); + if (winding1 == lastwinding && winding2 == lastwinding) { + polygon->add(x3); + polygon->add(y3); + polygonIndices->add(t3); + merged = true; + } + } + + // Otherwise make this triangle the new base. + if (!merged) { + if (polygon->size() > 0) { + convexPolygons.add(polygon); + convexPolygonsIndices.add(polygonIndices); + } else { + _polygonPool.free(polygon); + _polygonIndicesPool.free(polygonIndices); + } + + polygon = _polygonPool.obtain(); + polygon->clear(); + polygon->add(x1); + polygon->add(y1); + polygon->add(x2); + polygon->add(y2); + polygon->add(x3); + polygon->add(y3); + polygonIndices = _polygonIndicesPool.obtain(); + polygonIndices->clear(); + polygonIndices->add(t1); + polygonIndices->add(t2); + polygonIndices->add(t3); + lastwinding = winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + + if (polygon->size() > 0) { + convexPolygons.add(polygon); + convexPolygonsIndices.add(polygonIndices); + } + + // Go through the list of polygons and try to merge the remaining triangles with the found triangle fans. + for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) { + polygonIndices = convexPolygonsIndices[i]; + + if (polygonIndices->size() == 0) continue; + int firstIndex = (*polygonIndices)[0]; + int lastIndex = (*polygonIndices)[polygonIndices->size() - 1]; + + polygon = convexPolygons[i]; + size_t o = polygon->size() - 4; + Vector &p = *polygon; + float prevPrevX = p[o], prevPrevY = p[o + 1]; + float prevX = p[o + 2], prevY = p[o + 3]; + float firstX = p[0], firstY = p[1]; + float secondX = p[2], secondY = p[3]; + int winding0 = winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + + for (size_t ii = 0; ii < n; ++ii) { + if (ii == i) continue; + + Vector *otherIndicesP = convexPolygonsIndices[ii]; + Vector &otherIndices = *otherIndicesP; + + if (otherIndices.size() != 3) continue; + + int otherFirstIndex = otherIndices[0]; + int otherSecondIndex = otherIndices[1]; + int otherLastIndex = otherIndices[2]; + + Vector *otherPolyP = convexPolygons[ii]; + Vector &otherPoly = *otherPolyP; + + float x3 = otherPoly[otherPoly.size() - 2], y3 = otherPoly[otherPoly.size() - 1]; + + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue; + + int winding1 = winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + int winding2 = winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding0 && winding2 == winding0) { + otherPoly.clear(); + otherIndices.clear(); + polygon->add(x3); + polygon->add(y3); + polygonIndices->add(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + + // Remove empty polygons that resulted from the merge step above. + for (int i = (int) convexPolygons.size() - 1; i >= 0; --i) { + polygon = convexPolygons[i]; + if (polygon->size() == 0) { + convexPolygons.removeAt(i); + _polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.removeAt(i); + _polygonIndicesPool.free(polygonIndices); + } + } + + return convexPolygons; +} + +bool Triangulator::isConcave(int index, int vertexCount, Vector &vertices, Vector &indices) { + int previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + int current = indices[index] << 1; + int next = indices[(index + 1) % vertexCount] << 1; + + return !positiveArea(vertices[previous], vertices[previous + 1], + vertices[current], vertices[current + 1], + vertices[next], vertices[next + 1]); +} + +bool Triangulator::positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; +} + +int Triangulator::winding(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) { + float px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Updatable.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Updatable.cpp new file mode 100644 index 0000000..4193473 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/Updatable.cpp @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(Updatable) + +Updatable::Updatable() { +} + +Updatable::~Updatable() { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp new file mode 100644 index 0000000..61fd227 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -0,0 +1,171 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include + +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL(VertexAttachment, Attachment) + +VertexAttachment::VertexAttachment(const String &name) : Attachment(name), _worldVerticesLength(0), + _deformAttachment(this), _id(getNextID()) { +} + +VertexAttachment::~VertexAttachment() { +} + +void VertexAttachment::computeWorldVertices(Slot &slot, Vector &worldVertices) { + computeWorldVertices(slot, 0, _worldVerticesLength, worldVertices, 0); +} + +void VertexAttachment::computeWorldVertices(Slot &slot, float *worldVertices) { + computeWorldVertices(slot, 0, _worldVerticesLength, worldVertices, 0); +} + +void VertexAttachment::computeWorldVertices(Slot &slot, size_t start, size_t count, Vector &worldVertices, + size_t offset, size_t stride) { + computeWorldVertices(slot, start, count, worldVertices.buffer(), offset, stride); +} + +void VertexAttachment::computeWorldVertices(Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride) { + count = offset + (count >> 1) * stride; + Skeleton &skeleton = slot._bone._skeleton; + Vector *deformArray = &slot.getDeform(); + Vector *vertices = &_vertices; + Vector &bones = _bones; + if (bones.size() == 0) { + if (deformArray->size() > 0) vertices = deformArray; + + Bone &bone = slot._bone; + float x = bone._worldX; + float y = bone._worldY; + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + for (size_t vv = start, w = offset; w < count; vv += 2, w += stride) { + float vx = (*vertices)[vv]; + float vy = (*vertices)[vv + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + + int v = 0, skip = 0; + for (size_t i = 0; i < start; i += 2) { + int n = bones[v]; + v += n + 1; + skip += n; + } + + Vector &skeletonBones = skeleton.getBones(); + if (deformArray->size() == 0) { + for (size_t w = offset, b = skip * 3; w < count; w += stride) { + float wx = 0, wy = 0; + int n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + Bone *boneP = skeletonBones[bones[v]]; + Bone &bone = *boneP; + float vx = (*vertices)[b]; + float vy = (*vertices)[b + 1]; + float weight = (*vertices)[b + 2]; + wx += (vx * bone._a + vy * bone._b + bone._worldX) * weight; + wy += (vx * bone._c + vy * bone._d + bone._worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } else { + for (size_t w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + float wx = 0, wy = 0; + int n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + Bone *boneP = skeletonBones[bones[v]]; + Bone &bone = *boneP; + float vx = (*vertices)[b] + (*deformArray)[f]; + float vy = (*vertices)[b + 1] + (*deformArray)[f + 1]; + float weight = (*vertices)[b + 2]; + wx += (vx * bone._a + vy * bone._b + bone._worldX) * weight; + wy += (vx * bone._c + vy * bone._d + bone._worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } +} + +int VertexAttachment::getId() { + return _id; +} + +Vector &VertexAttachment::getBones() { + return _bones; +} + +Vector &VertexAttachment::getVertices() { + return _vertices; +} + +size_t VertexAttachment::getWorldVerticesLength() { + return _worldVerticesLength; +} + +void VertexAttachment::setWorldVerticesLength(size_t inValue) { + _worldVerticesLength = inValue; +} + +VertexAttachment *VertexAttachment::getDeformAttachment() { + return _deformAttachment; +} + +void VertexAttachment::setDeformAttachment(VertexAttachment *attachment) { + _deformAttachment = attachment; +} + +int VertexAttachment::getNextID() { + static int nextID = 0; + return nextID++; +} + +void VertexAttachment::copyTo(VertexAttachment *other) { + other->_bones.clearAndAddAll(this->_bones); + other->_vertices.clearAndAddAll(this->_vertices); + other->_worldVerticesLength = this->_worldVerticesLength; + other->_deformAttachment = this->_deformAttachment; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/VertexEffect.cpp b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/VertexEffect.cpp new file mode 100644 index 0000000..81e74d9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.0/spine-cpp/spine-cpp/src/spine/VertexEffect.cpp @@ -0,0 +1,157 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifdef SPINE_UE4 +#include "SpinePluginPrivatePCH.h" +#endif + +#include +#include +#include + +using namespace spine; + +JitterVertexEffect::JitterVertexEffect(float jitterX, float jitterY) : _jitterX(jitterX), _jitterY(jitterY) { +} + +void JitterVertexEffect::begin(Skeleton &skeleton) { + SP_UNUSED(skeleton); +} + +void JitterVertexEffect::transform(float &x, float &y, float &u, float &v, Color &light, Color &dark) { + SP_UNUSED(u); + SP_UNUSED(v); + SP_UNUSED(light); + SP_UNUSED(dark); + float jitterX = _jitterX; + float jitterY = _jitterY; + x += MathUtil::randomTriangular(-jitterX, jitterX); + y += MathUtil::randomTriangular(-jitterX, jitterY); +} + +void JitterVertexEffect::end() { +} + +void JitterVertexEffect::setJitterX(float jitterX) { + _jitterX = jitterX; +} + +float JitterVertexEffect::getJitterX() { + return _jitterX; +} + +void JitterVertexEffect::setJitterY(float jitterY) { + _jitterY = jitterY; +} + +float JitterVertexEffect::getJitterY() { + return _jitterY; +} + +SwirlVertexEffect::SwirlVertexEffect(float radius, Interpolation &interpolation) : _centerX(0), + _centerY(0), + _radius(radius), + _angle(0), + _worldX(0), + _worldY(0), + _interpolation(interpolation) { +} + +void SwirlVertexEffect::begin(Skeleton &skeleton) { + _worldX = skeleton.getX() + _centerX; + _worldY = skeleton.getY() + _centerY; +} + +void SwirlVertexEffect::transform(float &positionX, float &positionY, float &u, float &v, Color &light, Color &dark) { + SP_UNUSED(u); + SP_UNUSED(v); + SP_UNUSED(light); + SP_UNUSED(dark); + + float x = positionX - _worldX; + float y = positionY - _worldY; + float dist = (float) MathUtil::sqrt(x * x + y * y); + if (dist < _radius) { + float theta = _interpolation.interpolate(0, _angle, (_radius - dist) / _radius); + float cos = MathUtil::cos(theta), sin = MathUtil::sin(theta); + positionX = cos * x - sin * y + _worldX; + positionY = sin * x + cos * y + _worldY; + } +} + +void SwirlVertexEffect::end() { +} + +void SwirlVertexEffect::setCenterX(float centerX) { + _centerX = centerX; +} + +float SwirlVertexEffect::getCenterX() { + return _centerX; +} + +void SwirlVertexEffect::setCenterY(float centerY) { + _centerY = centerY; +} + +float SwirlVertexEffect::getCenterY() { + return _centerY; +} + +void SwirlVertexEffect::setRadius(float radius) { + _radius = radius; +} + +float SwirlVertexEffect::getRadius() { + return _radius; +} + +void SwirlVertexEffect::setAngle(float angle) { + _angle = angle * MathUtil::Deg_Rad; +} + +float SwirlVertexEffect::getAngle() { + return _angle; +} + +void SwirlVertexEffect::setWorldX(float worldX) { + _worldX = worldX; +} + +float SwirlVertexEffect::getWorldX() { + return _worldX; +} + +void SwirlVertexEffect::setWorldY(float worldY) { + _worldY = worldY; +} + +float SwirlVertexEffect::getWorldY() { + return _worldY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1 b/DateToSpine/third_party/spine-runtimes/4.1 deleted file mode 160000 index 77a5db0..0000000 --- a/DateToSpine/third_party/spine-runtimes/4.1 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 77a5db0ec6d16331f5efbaa7662bba9355bd3424 diff --git a/DateToSpine/third_party/spine-runtimes/4.1/CHANGELOG.md b/DateToSpine/third_party/spine-runtimes/4.1/CHANGELOG.md new file mode 100644 index 0000000..bee9d97 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/CHANGELOG.md @@ -0,0 +1,1365 @@ +# 4.1 + +## C +* **Additions** + * Support for sequences. + * Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + * Added CMake parameter `SPINE_SANITIZE` which will enable sanitizers on macOS and Linux. + * Added `SPINE_MAJOR_VERSION`, `SPINE_MINOR_VERSION`, and `SPINE_VERSION_STRING`. Parsing skeleton .JSON and .skel files will report an error if the skeleton version does not match the runtime version. +* **Breaking changes** + * `spRegionAttachment` and `spMeshAttachment` now contain a `spTextureRegion*` instead of encoding region fields directly. + * `sp_AttachmentLoader_newRegionAttachment()` and `spAttachmentLoader_newMeshAttachment()` now take an additional `Sequence*` parameter. + * `spMeshAttachment_updateUVs()` was renamed to `spMeshAttachment_updateRegion()`. + * `spRegionAttachment_updateOffset()` was renamed to `spRegionAttachment_updateRegion()`, `spRegionAttachment_setUVs()` was merged into `spRegionAttachment_updateRegion()`. + * `spSlot_getAttachmentTime()` and `spSlot_setAttachmentTime()` have been removed. + * `spVertexAttachment->deformAttachment` was renamed to `spVertexAttachment->timelineAttachment`. + * `spSkeleton_update()` has been removed. + * `spSkeleton->time` has been removed. + * `spVertexEffect` has been removed. + +### SFML + * Updated example to use SFML 2.5.1. + * Added dragon example. + +## C++ +* **Additions** + * Support for sequences. + * Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + * Added CMake parameter `SPINE_SANITIZE` which will enable sanitizers on macOS and Linux. + * Added `SPINE_MAJOR_VERSION`, `SPINE_MINOR_VERSION`, and `SPINE_VERSION_STRING`. Parsing skeleton .JSON and .skel files will report an error if the skeleton version does not match the runtime version. + * Added `SkeletonBounds::getBoundingBox()`, `SkeletonBounds::getPolygons()`, and `SkeletonBounds::getBoundingBoxes()`. +* **Breaking changes** + * `RegionAttachment` and `MeshAttachment` no longer implement `HasRendererObject`. + * `RegionAttachment` and `MeshAttachment` now contain a `TextureRegion*` instead of encoding region fields directly. + * `AttachmentLoader::newRegionAttachment()` and `AttachmentLoader::newMeshAttachment()` now take an additional `Sequence*` parameter. + * `MeshAttachment::updateUVs()` was renamed to `MeshAttachment::updateRegion()`. + * `RegionAttachment::updateOffset()` was renamed to `RegionAttachment::updateRegion()`, `RegionAttachment::setUVs()` was merged into `updateRegion()`. + * `Slot::getAttachmentTime()` and `Slot::setAttachmentTime()` have been removed. + * `VertexAttachment::getDeformAttachment()` was renamed to `VertexAttachment::getTimelineAttachment()`. + * `Skeleton::update()` has been removed. + * `Skeleton::getTime()` has been removed. + * `VertexEffect` has been removed. + +### Cocos2d-x + +### SFML + * Updated example to use SFML 2.5.1. + * Added dragon example. + +### UE4 + * Updated example project to UE 4.27 + +## C# ## + +* **Additions** + * Full support for sequences. + * Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + * `RegionAttachment` and `MeshAttachment` now provide a `Region` property. Use this property instead of the removed `RendererObject` property (see section *Breaking Changes* below). + +* **Breaking changes** + * Removed `RendererObject` property from `RegionAttachment` and `MeshAttachment`. Use `attachment.Region` property instead. Removed removed `IHasRendererObject` interface. Use `IHasTextureRegion` instead. + * Replaced `RegionAttachment.UpdateOffset` and `MeshAttachment.UpdateUVs` with `Attachment.UpdateRegion`. The caller must ensure that the attachment's region is not `null`. + * Removed `AttachmentRegionExtensions` methods `Attachment.SetRegion`, `MeshAttachment.SetRegion` and `RegionAttachment.SetRegion(region, update)`. Use `attachment.Region = region; if (update) attachment.UpdateRegion()` instead. + * `AttachmentLoader.NewRegionAttachment()` and `AttachmentLoader.NewMeshAttachment()` take an additional `Sequence` parameter. + * `VertexAttachment.DeformAttachment` property has been replaced with `VertexAttachment.TimelineAttachment`. + * `RegionAttachment.ComputeWorldVertices()` takes a `Slot` instead of a `Bone` as the first argument. + * Removed `Skeleton.Update(float deltaTime)` method. + * Removed `Slot.AttachmentTime` property. + * Removed extension method `AtlasRegion.GetSpineAtlasRect()` parameter `includeRotate` (with default value `true`). Most likely this method was never used with `includeRotate=false` in user code so no changes are required. + * `AtlasRegion.PackedWidth` and `AtlasRegion.PackedHeight` are swapped compared to 4.0 when packing rotation is equal to 90 degrees. Most likely this property was never accessed in user code so no changes are required. + +### Unity + +* **Officially supported Unity versions are 2017.1-2023.1**. + +* **Additions** + * `SpineAtlasAsset.CreateRuntimeInstance` methods now provide an optional `newCustomTextureLoader` parameter (defaults to `null`) which can be set to e.g. `(a) => new YourCustomTextureLoader(a)` to use your own `TextureLoader` subclass instead of `MaterialsTextureLoader`. + * `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic` now provide an Inspector parameter `Advanced` - `Animation Update` with modes `In Update` **(previous behaviour, the default)**, `In FixedUpdate` and `Manual Update`. This allows to update animation in `FixedUpdate` when using the `SkeletonRootMotion` component (which is the recommended combination now, issuing a warning otherwise). The reason is that when root motion leads to a collision with a physics collider, it can introduce jittery excess movement when updating animation in `Update` due to more `Update` calls following a single `FixedUpdate` call. + * Added `SkeletonRootMotion` properties `PreviousRigidbodyRootMotion` and `AdditionalRigidbody2DMovement`. Setting or querying these movement vectors can be necessary when multiple scripts call `Rigidbody2D.MovePosition` on the same object where the last call overwrites the effect of preceding ones. + * `BoneFollower` and `BoneFollowerGraphic` now provide an additional `Follow Parent World Scale` parameter to allow following simple scale of parent bones (rotated/skewed scale can't be supported). + * Improved `Advanced - Fix Prefab Override MeshFilter` property for `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`), now providing an additional option to use a global value which can be set in `Edit - Preferences - Spine`. + * Timeline naming improvements: `Spine AnimationState Clip` Inspector parameter `Custom Duration` changed and inverted to `Default Mix Duration` for more clarity. Shortened all Timeline add track menu entries from: `Spine.Unity.Playables - ` to `Spine - `, `Spine Animation State Track` to `SkeletonAnimation Track`, `Spine AnimationState Graphic Track` to `SkeletonGraphic Track`, and `Spine Skeleton Flip Track` to `Skeleton Flip Track`. + * Timeline track appearance and Inspector: Tracks now show icons and track colors to make them easier to distinguish. When a Track is selected, the Inspector now shows an editable track name which was previously only editable at the Timeline asset. + * Added example component `SkeletonRenderTexture` to render a `SkeletonRenderer` to a `RenderTexture`, mainly for proper transparency. Added an example scene named `RenderTexture FadeOut Transparency` that demonstrates usage for a fadeout transparency effect. + * Added another fadeout example component named `SkeletonRenderTextureFadeout` which takes over transparency fadeout when enabled. You can use this component as-is, attach it in disabled state and enable it to start a fadeout effect. + * Timeline clips now offer an additional `Alpha` parameter for setting a custom constant mix alpha value other than 1.0, just as `TrackEntry.Alpha`. Defaults to 1.0. + * `GetRemappedClone` copying from `Sprite` now provides additional `pmaCloneTextureFormat` and `pmaCloneMipmaps` parameters to explicitly specify the texture format of a newly created PMA texture. + * Spine property Inspector fields (`Animation Name`, `Bone Name`, `Slot` and similar) now display the name in red when the respective animation/bone/etc no longer exists at the skeleton data. This may be helpful when such items have been renamed or deleted. + * Added `UnscaledTime` property at `SkeletonAnimation` as well, behaving like `SkeletonGraphic.UnscaledTime`. If enabled, AnimationState uses unscaled game time (`Time.unscaledDeltaTime`), running animations independent of e.g. game pause (`Time.timeScale`). + * `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic` now provide an additional `OnAnimationRebuild` callback delegate which is issued after both the skeleton and the animation state have been initialized. + * Timeline `SkeletonAnimation Track` and `SkeletonGraphic Track` now provide an `Unscaled Time` property. Whenever starting a new animation clip of this track, `SkeletonAnimation.UnscaledTime` or `SkeletonGraphic.UnscaledTime` will be set to this value. This allows you to play back Timeline clips either in normal game time or unscaled game time. Note that `PlayableDirector.UpdateMethod` is ignored and replaced by this property, which allows more fine-granular control per Timeline track. + * Added `SkeletonRootMotion` callback delegates `ProcessRootMotionOverride` and `PhysicsUpdateRootMotionOverride` to customize how root motion is applied. The new property `disableOnOverride` determines whether the callback will be issued in addition or instead of normally applying root motion. Added property `rootMotionScaleRotation` to allow scaling rotational root-motion to match e.g. a 90 degree rotation to a custom target angle. + * Added outline shader parameter `Advanced - Opaque Alpha` which can be used to exclude problematic semi-transparent areas, which may receive an undesired large outline color overlay otherwise. + * Added Spine Preferences setting `Prefabs` - `Optimize Preview Meshes`. When enabled, Spine prefab preview meshes will be removed in a pre-build step to reduce build size. This increases build time as all prefabs in the project will be processed. Defaults to false to not slow down builds substantially every time. + * Added Spine Preferences setting `Reload SkeletonData after Play`. When enabled, the shared `SkeletonData` of all skeletons in the active scene is reloaded (from the `.json` or `.skel.bytes` file) after exiting play-mode. You can disable this setting to avoid the reloading delay if you can ensure that there are no (accidental) modifications to the shared `SkeletonData` during play-mode (otherwise it would carry over its effect into subsequent plays). Defaults to `true` (the safe setting), which maintains existing behaviour. + * Added `SkeletonAnimationMulti` sample component methods `SetActiveSkeleton(int index)` and getter property `SkeletonAnimations` to more easily apply changes at all SkeletonAnimation instances instead of only the active one. + * PMA textures now have `sRGB (Color Texture)` disabled by default, the preset template `PMATexturePreset.preset` has been adjusted accordingly. As PMA textures are only allowed with Gamma color space, `sRGB (Color Texture)` shall be disabled to prevent border artifacts when mipmaps are enabled. In Gamma color space having this setting disabled has no drawbacks, only benefits. + * `SkeletonRenderTexture` and `SkeletonGraphicRenderTexture` components now support automatic down-scaling when required size on screen exceeds `Max Render Texture Size`. + * Added `Spine/SkeletonGraphic Fill` shader to provide functionality of `Spine/Skeleton Fill` shader for `SkeletonGraphic`. + * Lit Spine URP shaders (`Universal Render Pipeline/Spine/Sprite` and `Universal Render Pipeline/Spine/Skeleton Lit`) now support `Forward+` rendering path as introduced by Unity 2022.2 and URP version 14. + * `SkeletonGraphic` now supports automatic scaling based on its `RectTransform` bounds. Automatic scaling can be enabled by setting the added `Layout Scale Mode` Inspector property to either `Width Controls Height`, `Height Controls Width`, `FitInParent` or `EnvelopeParent`. It is set to `None` by default to keep previous behaviour and avoid breaking existing projects. To modify the reference layout bounds, hit the additional `Edit Layout Bounds` toggle button to switch into edit mode, adjust the bounds or hit `Match RectTransform with Mesh`, and hit the button again when done adjusting. The skeleton will now be scaled accordingly to fit the reference layout bounds to the object's `RectTransform`. + * Added previously missing unlit URP 2D shader variant, available under `Universal Render Pipeline/2D/Spine/Skeleton`. + * Added support for light cookies at `Universal Render Pipeline/Spine/Sprite` shader. + * Timeline extension package: An additional Spine preferences parameter `Timeline` - `Default Mix Duration` has been added, setting newly added `SpineAnimationStateClip` clips accordingly, defaults to false. This Spine preferences parameter can be enabled to default to the previous behaviour before this update. + * Tint Black: Added support for [Tint Black](http://en.esotericsoftware.com/spine-slots#Tint-black) functionality at all Spine URP shaders (2D and 3D shaders) and at all standard pipeline `Spine/Sprite` shaders. This feature can be enabled via the `Tint Black` material parameter in the Inspector. Note: The URP Sprite shaders provided in the Spine URP Shaders extension UPM package require the latest version of the spine-unity runtime (package version 4.1.12, 2023-05-31 or newer) to display the added material parameters in the Inspector GUI. + * Added `SkeletonGraphic.MeshScale` property to allow access to calculated mesh scale. `MeshScale` is based on (1) Canvas pixels per unit, and (2) `RectTransform` bounds when using `Layout Scale Mode` other than `None` at `SkeletonGraphic` which scales the skeleton mesh to fit the parent `RectTransform` bounds accordingly. + * Added `updateSeparatorPartScale` property to `SkeletonGraphic` to let render separator parts follow the scale (lossy scale) of the `SkeletonGraphic` GameObject. Defaults to `false` to maintain existing behaviour. + * Added experimental `EditorSkeletonPlayer` component to allow Editor playback of the initial animation set at `SkeletonAnimation` or `SkeletonGraphic` components. Add this component to your skeleton GameObject to enable the in-editor animation preview. Allows configurations for continuous playback when selected, deselected, and alternative single-frame preview by setting `Fixed Track Time` to any value other than 0. Limitations: At skeletons with variable material count the Inspector preview may be too unresponsive. It is then recommended to disable the `EditorSkeletonPlayer` component (at the top of the Inspector) to make it responsive again, then you can disable `Play When Selected` and re-enable the component to preview playback only when deselected. + * Added example component `RenderCombinedMesh` to render a combined mesh of multiple meshes or submeshes. This is required by `OutlineOnly` shaders to render a combined outline when using `SkeletonRenderSeparator` or multiple atlas pages which would normally lead to outlines around individual parts. To add a combined outline to your SkeletenRenderer: + 1) Add a child GameObject and move it a bit back (e.g. position Z = 0.01). + 2) Add a `RenderCombinedMesh` component, provided in the `Spine Examples/Scripts/Sample Components` directory. + 3) Copy the original material, add *_Outline* to its name and set the shader to your outline-only shader like `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly` or `Spine/Outline/OutlineOnly-ZWrite`. + 4) Assign this *_Outline* material at the new child GameObject's `MeshRenderer` component. + If you are using `SkeletonRenderSeparator` and need to enable and disable the `SkeletonRenderSeparator` component at runtime, you can increase the `RenderCombinedMesh` `Reference Renderers` array by one and assign the `SkeletonRenderer` itself at the last entry after the parts renderers. Disabled `MeshRenderer` components will be skipped when combining the final mesh, so the combined mesh is automatically filled from the desired active renderers. + * Timeline extension package: Added static `EditorEvent` callback to allow editor scripts to react to animation events outside of play-mode. Register to the events via `Spine.Unity.Playables.SpineAnimationStateMixerBehaviour.EditorEvent += YourCallback;`. + * URP Shaders: Added `Depth Write` property to shaders `Universal Render Pipeline/Spine/Skeleton` and `Universal Render Pipeline/Spine/Skeleton Lit`. Defaults to false to maintain existing behaviour. + * Added `Animation Update` mode (called `UpdateTiming` in code) `In Late Update` for `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic`. This allows you to update the `SkeletonMecanim` skeleton in the same frame that the Mecanim Animator updated its state, which happens between `Update` and `LateUpdate`. + * URP Shaders: Added URP "Blend Mode" shader variants for both URP 3D and URP 2D renderers. They are listed under shader name "Universal Render Pipeline/Spine/Blend Modes/" and "Universal Render Pipeline/2D/Spine/Blend Modes/" respectively. + * URP Shaders: Added support for [Tint Black](http://en.esotericsoftware.com/spine-slots#Tint-black) functionality at "Blend Modes" Spine URP shaders (2D and 3D shaders). + +* **Breaking changes** + * Made `SkeletonGraphic.unscaledTime` parameter protected, use the new property `UnscaledTime` instead. + * `SkeletonGraphic` `OnRebuild` callback delegate is now issued after the skeleton has been initialized, before the `AnimationState` component is initialized. This makes behaviour consistent with `SkeletonAnimation` and `SkeletonMecanim` component behaviour. Use the new callback `OnAnimationRebuild` if you want to receive a callback after the `SkeletonGraphic` `AnimationState` has been initialized. + +* **Changes of default values** + +* **Deprecated** + * Shader macro `RETURN_UNLIT_IF_ADDITIVE_SLOT` in `spine-unity/Shaders/Sprite/CGIncludes/ShaderShared.cginc` has been deprecated and will be removed in spine-unity 4.2. Use RETURN_UNLIT_IF_ADDITIVE_SLOT_TINT instead. + +* **Restructuring (Non-Breaking)** + * Moved Spine URP Shaders Examples directory from the main package directory to Samples which can be installed via the Unity Package Manager. To import, select the `Spine Universal RP Shaders` package in the Package Manager window, expand `Samples` at the bottom and hit `Import` next to `Examples`. This follows the standard [samples guideline](https://docs.unity3d.com/Manual/cus-samples.html) and prevents warning messages about unexpectedly altered immutable assets. + +### XNA/MonoGame +* **Breaking change**: Removed spine-xna in favor of spine-monogame. See https://github.com/EsotericSoftware/spine-runtimes/issues/1949 +* Added new spine-monogame solution. See [spine-monogame/README.md](spine-monogame/README.md) for updated instructions on how to use spine-monogame. + +## Java +* **Additions** + * Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + * Support for sequences. +* **Breaking changes** + * `AttachmentLoader#newRegionAttachment()` and `AttachmentLoader#newMeshAttachment()` take an additional `Sequence` parameter. + * `Slot#setAttachmentTime()` and `Slot#getAttachmentTime()` have been removed. + * `VertexAttachment#setDeformAttachment()` and `VertexAttachment#getDeformAttachment()` have been replaced with `VertexAttachment#setTimelineAttachment()` and `VertexAttachment#getTimelineAttachment()`. + * `RegionAttachment#updateOffset()` has been renamed to `RegionAttachment#updateRegion()`. The caller must ensure that the attachment's region is not `null`. + * `RegionAttachment#computeWorldVertices()` takes a `Slot` instead of a `Bone` as the first argument. + * `VertexEffect` has been removed. + + +### libGDX +* `spine-libgdx`, `spine-libgdx-tests`, and `spine-skeletonviewer` are now fully Gradle-ified. +* `spine-skeletonviewer` now supports quickly loading skeletons by dragging and dropping `.json` or `.skel` skeleton files onto the window. + +## Typescript/Javascript +* **Additions** + * full support for sequences. + * Added `Promise` based `AssetManager.loadAll()`. Allows synchronous waiting via `await assetManager.loadAll()`, simplifying loader logic in applications. + * Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + * Full support for sequences. +* **Breaking changes** + * `AttachmentLoader#newRegionAttachment()` and `AttachmentLoader#newMeshAttachment()` take an additional `Sequence` parameter. + * `Slot#attachmentTime` and has been removed. + * `VertexAttachment#deformAttachment` has been replaced with `VertexAttachment#timelineAttachment`. + * `RegionAttachment#updateOffset()` has been renamed to `RegionAttachment#updateRegion()`. The caller must ensure that the attachment's region is not `null`. + * `RegionAttachment#computeWorldVertices()` takes a `Slot` instead of a `Bone` as the first argument. + * Removed `PlayerEditor`. + * `VertexEffect` has been removed. + * Removed `RegionAttachment.rendererObject`. + * Renamed `TextureRegion.renderObject` to `TextureRegion.texture`. + + +### WebGL backend + * `PolygonBatcher` can now disable culling automatically if the static variable `PolygonBatcher.disableCulling` is set to true. + * Added `SpineCanvas`, a simpler way to render a scene via spine-webgl. See `spine-ts/spine-webgl/examples/barebones.html` and `spine-ts/spine-webgl/examples/mix-and-match.html`. + * Added `SpineCanavs.dispose()` to halt the updating and rendering of the canvas. + +### Canvas backend + * Improved example. + +### Three.js backend + * Added orbital controls to THREJS example. + * `SkeletonMesh` takes an optional `SkeletonMeshMaterialCustomizer`, allowing modification of materials used by `SkeletonMesh`. + * Added `SkeletonMeshMaterial.alphaTest`, when > 0, alpha testing will be performed and fragments will not be written to the depth buffer, if depth writes are enabled. + +### Player + * Added `SpinePlayer.dispose()` to explicitely dispose of all resources the player holds on to. + +# 4.0 + +## AS3 +**NOTE: Spine 4.0 will be the last release supporting spine-as3. Starting from Spine 4.1, spine-as3 will no longer be supported or maintained.** +* Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. +* Expose non-essential colors on bones, bounding box, clipping, and path attachments. +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +* Added support for reverse animation playback via `TrackEntry.reverse`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. + +### Starling +**NOTE: Spine 4.0 will be the last release supporting spine-starling. Starting from Spine 4.1, spine-starling will no longer be supported or maintained.** +* Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. +* Updated to Starling 2.6 and Air SDK 33. + +## C +* **Breaking change:** Removed `SPINE_SHORT_NAMES` define and C++ constructors. +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `spAnimationState_clearNext()` which removes the given `spTrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `spAtlasRegion.keyValues`. +* Added support for reverse animation playback via `spTrackEntry.reverse`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. + +### Cocos2d-Objc +**NOTE: Spine 4.0 will be the last release supporting spine-cocos2d-objc. Starting from Spine 4.1, spine-cocos2d-objc will no longer be supported or maintained.** + +### SFML +* Added `ikDemo()` in `main.cpp`. to illustrate how to drive a bone and IK chain through mouse movement. + +## C++ +* Removed dependency on STL throughout the code base, cutting down on the LOC that need parsing by 66%. +* Exposed `x` and `y` on `SkeletonData` through getters and setters. +* Expose non-essential colors on bones, bounding box, clipping, and path attachments. +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +* Added support for reverse animation playback via `TrackEntry.reverse`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. +* spine-cpp now requires C++11. + +### Cocos2d-x +* Added `IKExample` scene to illustrate how to drive a bone and IK chain through mouse movement. +* Added `SkeletonAnimation::setPreUpdateWorldTransformsListener()` and `SkeletonAnimation::setPostUpdateWorldTransformsListener()`. This allows users to modify bone transforms and other skeleton properties before and after the world transforms of all bones are calculated. See the `IKExample` for a usage example. + +### SFML +* Added `ikDemo()` in `main.cpp`. to illustrate how to drive a bone and IK chain through mouse movement. + +### UE4 +* `SpineWidget` now supports the full widget transform, including rendering scale/shear. +* Materials on `SkeletonRendererComponent` are now blueprint read and writeable. This allows setting dynamic material instances at runtime. +* Added `InitialSkin` property to `USpineWidget`. This allows previewing different skins in the UMG Designer. Initial skins can still be overridden via blueprint events such as `On Initialized`. +* **Breaking change:** `SpineWidget` no longer has the `Scale` property. Instead the size x/y properties can be used. +* Added `SetSlotColor` on `USpineSkeletonComponent` to easily set the color of a slot via blueprints. +* Changed mixes set on an `SkeletonDataAsset` will now be applied to instances of `USpineSkeletonComponent`. +* Generated normals are now correctly flipped for back faces. +* Modifying parent materials updates material instances accordingly. +* Only `.json` files that are actually encoding Spine skeletons will be loaded. Other `.json` files will be left to other importers. +* Updated example project to UE 4.27. + + +## C# ## +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +* Added support for reverse animation playback via `TrackEntry.Reverse`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. +* **Breaking change:** Removed `SkeletonData` and `Skeleton` methods: `FindBoneIndex`, `FindSlotIndex`. Bones and slots have an `Index` field that should be used instead. Be sure to check for e.g. `bone == null` accordingly before accessing `bone.Index`. + +### Unity + +* **Officially supported Unity versions are 2017.1-2022.1**. +* **Breaking changes** + * Removed all `Spine.Unity.AttachmentTools.SkinUtilities` Skin extension methods. These have become obsoleted and error-prone since the introduction of the new Skin API in 3.8. To fix any compile errors, replace any usage of `Skin` extension methods with their counterparts, e.g. replace occurrances of `skin.AddAttachments()` with `skin.AddSkin()`. Please see the example scene `Mix and Match Skins` on how to use the new Skin API to combine skins, or the updated old example scenes `Mix and Match` and `Mix and Match Equip` on how you can update an existing project using the old workflow. If you are using `skeletonAnimation.Skeleton.UnshareSkin()` in your code, you can replace it with `Skin customSkin = new Skin("custom skin"); customSkin.AddSkin(skeletonAnimation.Skeleton.Skin);`. + * `Skin.GetAttachments()` has been replaced by `Skin.Attachments`, returning an `ICollection`. This makes access more consistent and intuitive. To fix any compile errors, replace any occurrances of `Skin.GetAttachments()` by `Skin.Attachments`. + * Removed redundant `Spine.Unity.AttachmentTools.AttachmentCloneExtensions` extension methods `Attachment.GetCopy()` and `Attachment.GetLinkedMesh()`. To fix any compile errors, replace any occurrances with `Attachment.Copy()` and `Attachment.NewLinkedMesh()`. + * Removed `Spine.Unity.AttachmentTools.AttachmentRegionExtensions` extension methods `Attachment.GetRegion()`. Use `Attachment.RendererObject as AtlasRegion` instead. + * Removed redundant `Spine.SkeletonExtensions` extension methods: + Replace: + * `Skeleton.SetPropertyToSetupPose()` + * `Skeleton.SetDrawOrderToSetupPose()` + * `Skeleton.SetSlotAttachmentsToSetupPose()` + * `Skeleton.SetSlotAttachmentToSetupPose()` + + with `Skeleton.SetSlotsToSetupPose()`. + Replace: + * `Slot.SetColorToSetupPose()` + * `Slot.SetAttachmentToSetupPose()` + + with `Slot.SetToSetupPose()`. + + Also removed less commonly used extension methods: + `TrackEntry.AllowImmediateQueue()`, `Animation.SetKeyedItemsToSetupPose()` and `Attachment.IsRenderable()`. + + * **`SkeletonGraphic` now no longer uses a `RawImage` component at each submesh renderer** GameObject when `allowMultipleCanvasRenderers` is true. Instead, a new custom component `SkeletonSubmeshGraphic` is used which is more resource friendly. Replacement of these components will be performed automatically through editor scripting, saving scenes or prefabs will persist the upgrade. + * **Linear color space:** Previously Slot colors were not displayed the same in Unity as in the Spine Editor. This is now fixed at all shaders, including URP and LWRP shaders. See section *Additions* below for more details. If you have tweaked Slot colors to look correct in `Linear` color space in Unity but incorrect in Spine, you might want to adjust the tweaked colors. Slot colors displayed in Unity should now match colors displayed in the Spine Editor when configured to display as `Linear` color space in the Spine Editor Settings. + * **Additive Slots have always been lit** before they were written to the target buffer. Now all lit shaders provide an additional parameter `Light Affects Additive` which defaults to `false`, as it is the more intuitive default value. You can enable the old behaviour by setting this parameter to `true`. + * **Corrected blending behaviour of all `Sprite` shaders** in `Premultiply Alpha` blend mode (including URP and LWRP packages). Previously vertex color alpha was premultiplied again, even though `Premultiply Alpha` blend mode assumes PMA texture and PMA vertex color input. Slot-alpha blending will thus be correctly lighter after upgrading to 4.0. If you have compensated this problem by disabling `Advanced - PMA Vertex Colors` you can now re-enable this parameter, also allowing for rendering Additive slots in a single pass. + * **Corrected all `Outline` shaders outline thickness** when `Advanced - Sample 8 Neighbourhood` is disabled (thus using `4 Neighbourhood`). Previously weighting was incorrectly thick (4x as thick) compared to 8 neighbourhood, now it is more consistent. This might require adjustment of all your outline materials where `Sample 8 Neighbourhood` is disabled to restore the previous outline thickness, by adjusting the `Outline Threshold` parameter through adding a `/4` to make the threshold 4 times smaller. + * Reverted changes: `BoneFollower` property `followLocalScale` has intermediately been renamed to `followScale` but was renamed back to `followLocalScale`. Serialized values (scenes and prefabs) will automatically be upgraded, only code accessing `followScale` needs to be adapted. + * Fixed Timeline not pausing (and resuming) clip playback on Director pause, this is now the default behaviour. If you require the old behaviour (e.g. to continue playing an idle animation during Director pause), there is now an additional parameter `Don't Pause with Director` provided that can be enabled for each Timeline clip. + * Fixed Timeline `Spine AnimationState Clips` ignoring empty space on the Timeline after a clip's end. Timeline clips now also offer `Don't End with Clip` and `Clip End Mix Out Duration` parameters if you prefer the old behaviour of previous versions. By default when empty space follows the clip on the timeline, the empty animation is set on the track with a MixDuration of `Clip End Mix Out Duration`. Set `Don't End with Clip` to `true` to continue playing the clip's animation instead and mimic the old 3.8 behaviour. If you prefer pausing the animation instead of mixing out to the empty animation, set `Clip End Mix Out Duration` to a value less than 0, then the animation is paused instead. + +* **Additions and Improvements** + * Additional **Fix Draw Order** parameter at SkeletonRenderer, defaults to `disabled` (previous behaviour). + Applies only when 3+ submeshes are used (2+ materials with alternating order, e.g. "A B A"). + If `true`, MaterialPropertyBlocks are assigned at each material to prevent aggressive batching of submeshes + by e.g. the LWRP renderer, leading to incorrect draw order (e.g. "A1 B A2" changed to "A1A2 B"). + You can leave this parameter disabled when everything is drawn correctly to save the additional performance cost. + * **Additional Timeline features.** SpineAnimationStateClip now provides a `Speed Multiplier`, a start time offset parameter `Clip In`, support for blending successive animations by overlapping tracks. An additional `Use Blend Duration` parameter *(defaults to true)* allows for automatic synchronisation of MixDuration with the current overlap blend duration. An additional Spine preferences parameter `Use Blend Duration` has been added which can be disabled to default to the previous behaviour before this update. + * Additional `SpriteMask and RectMask2D` example scene added for demonstration of mask setup and interaction. + * `Real physics hinge chains` for both 2D and 3D physics. The [SkeletonUtilityBone](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) Inspector provides an interface to create 2D and 3D hinge chains. Previously created chains have only been respecting gravity, but not momentum of the skeleton or parent bones. The new physics rig created when pressing `Create 3D Hinge Chain` and `Create 2D Hinge Chain` creates a more complex setup that also works when flipping the skeleton. Note that the chain root node is no longer parented to bones of the skeleton. This is a requirement in Unity to have momentum applied properly - do not reparent the chain root to bones of your skeleton, or you will loose any momentum applied by the skeleton's movement. + * `Outline rendering functionality for all shaders.` Every shader now provides an additional set of `Outline` parameters to enable custom outline rendering. When outline rendering is enabled via the `Material` inspector, it automatically switches the shader to the respective `Spine/Outline` shader variant. Outlines are generated by sampling neighbour pixels, so be sure to add enough transparent padding when exporting your atlas textures to fit the desired outline width. In order to enable outline rendering at a skeleton, it is recommended to first prepare an additional outline material copy and then switch the material of the target skeleton to this material. This prevents unnecessary additional runtime material copies and drawcalls. Material switching can be prepared via a [SkeletonRendererCustomMaterials](http://esotericsoftware.com/spine-unity#SkeletonRendererCustomMaterials) component and then enabled or disabled at runtime. Alternatively, you can also directly modify the `SkeletonRenderer.CustomMaterialOverride` property. + Outline rendering is fully supported on `SkeletonGraphic` shaders as well. + * Added `SkeletonRenderer.EditorSkipSkinSync` scripting API property to be able to set custom skins in editor scripts. Enable this property when overwriting the Skeleton's skin from an editor script. Without setting this parameter, changes will be overwritten by the next inspector update. Only affects Inspector synchronisation of skin with `initialSkinName`, not startup initialization. + * `AtlasUtilities.GetRepackedAttachments()` and `AtlasUtilities.GetRepackedSkin()` provide support for additional texture channels such as normal maps via the optional parameter `additionalTexturePropertyIDsToCopy `. See the spine-unity runtime documentation, section [Combining Skins - Advanced - Runtime Repacking with Normalmaps](http://esotericsoftware.com/spine-unity#Combining-Skins) for further info and example usage code. + * `BoneFollower` can now optionally follow (uniform) world scale of the reference bone. There is now a `Mode` dropdown selector in the Inspector which can be set to either `Local` or `World Uniform`. + * All `Spine/SkeletonGraphic` shaders now provide a parameter `CanvasGroup Compatible` which can be enabled to support `CanvasGroup` alpha blending. For correct results, you should then disable `Pma Vertex Colors` in the `SkeletonGraphic` Inspector, in section `Advanced` (otherwise Slot alpha will be applied twice). + * **Now supporting Universal Render Pipeline (URP), including the 2D Renderer pipeline, through an additional UPM package.** + * **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + * a) the `Packages` directory in your project where it will automatically be loaded, or + * b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + The Project panel should now show an entry `Spine Universal RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + * **Usage:** The package provides two shaders specifically built for the universal render pipeline: + * `Universal Render Pipeline/Spine/Skeleton`, as a universal variant of the `Spine/Skeleton` shader, + * `Universal Render Pipeline/Spine/Skeleton Lit`, as a universal variant of the `Spine/Skeleton Lit` shader, + * `Universal Render Pipeline/Spine/Sprite`, as a universal variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the universal render pipeline, + * `Universal Render Pipeline/2D/Spine/Skeleton Lit`, as a universal 2D Renderer variant of the `Spine/Skeleton Lit` shader, and + * `Universal Render Pipeline/2D/Spine/Sprite`, as a universal 2D Renderer variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders. + The shaders can be assigned to materials as usual and will respect your settings of the assigned `UniversalRenderPipelineAsset` under `Project Settings - Graphics`. + * **Restrictions** As all Spine shaders, the URP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + * **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.urp-shaders-3.8/Examples/URP Shaders.unity` that demonstrates usage of the URP shaders. + * Spine Preferences now provide an **`Atlas Texture Settings`** parameter for applying customizable texture import settings at all newly imported Spine atlas textures. + When exporting atlas textures from Spine with `Premultiply alpha` enabled (the default), you can leave it at `PMATexturePreset`. If you have disabled `Premultiply alpha`, set it to the included `StraightAlphaTexturePreset` asset. You can also create your own `TextureImporter` `Preset` asset and assign it here (include `PMA` or `Straight` in the name). In Unity versions before 2018.3 you can use `Texture2D` template assets instead of the newer `Preset` assets. Materials created for imported textures will also have the `Straight Alpha Texture` parameter configured accordingly. + * All `Sprite` shaders (including URP and LWRP extension packages) now provide an additional `Fixed Normal Space` option `World-Space`. PReviously options were limited to `View-Space` and `Model-Space`. + * `SkeletonGraphic` now fully supports [`SkeletonUtility`](http://esotericsoftware.com/spine-unity#SkeletonUtility) for generating a hierarchy of [`SkeletonUtilityBones`](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) in both modes `Follow` and `Override`. This also enables creating hinge chain physics rigs and using `SkeletonUtilityConstraints` such as `SkeletonUtilityGroundConstraint` and `SkeletonUtilityEyeConstraint` on `SkeletonGraphic`. + * Added **native support for slot blend modes** `Additive`, `Multiply` and `Screen` with automatic assignment at newly imported skeleton assets. `BlendModeMaterialAssets` are now obsolete and replaced by the native properties at `SkeletonDataAsset`. The `SkeletonDataAsset` Inspector provides a new `Blend Modes - Upgrade` button to upgrade an obsolete `BlendModeMaterialAsset` to the native blend modes properties. This upgrade will be performed automatically on imported and re-imported assets. + * `BoneFollower` and `BoneFollowerGraphic` components now provide better support for following bones when the skeleton's Transform is not the parent of the follower's Transform. Previously e.g. rotating a common parent Transform did not lead to the desired result, as well as negatively scaling a skeleton's Transform when it is not a parent of the follower's Transform. + * **Linear color space:** Previously Slot colors were not displayed the same in Unity as in the Spine Editor (when configured to display as `Linear` color space in Spine Editor Settings). This is now fixed at all shaders, including URP and LWRP shaders. + * All Spine shaders (also including URP and LWRP shaders) now support `PMA Vertex Colors` in combination with `Linear` color space. Thus when using Spine shaders, you should always enable `PMA Vertex Colors` at the `SkeletonRenderer` component. This allows using single pass `Additive` Slots rendering. Note that textures shall still be exported as `Straight alpha` when using `Linear` color space, so combine `PMA Vertex Colors` with `Straight Texture`. All `Sprite` shaders now provide an additional blend mode for this, named `PMA Vertex, Straight Texture` which shall be the preferred Sprite shader blend mode in `Linear` color space. + * Additive Slots have always been lit before they were written to the target buffer. Now all lit shaders provide an additional parameter `Light Affects Additive` which defaults to `false`, as it is the more intuitive default value. You can enable the old behaviour by setting this parameter to `true`. + * `SkeletonRootMotion` and `SkeletonMecanimRootMotion` components now support arbitrary bones in the hierarchy as `Root Motion Bone`. Previously there were problems when selecting a non-root bone as `Root Motion Bone`. `Skeleton.ScaleX` and `.ScaleY` and parent bone scale is now respected as well. + * URP and LWRP `Sprite` and `SkeletonLit` shaders no longer require `Advanced - Add Normals` enabled to properly cast and receive shadows. It is recommended to disable `Add Normals` if normals are otherwise not needed. + * Added an example component `RootMotionDeltaCompensation` located in `Spine Examples/Scripts/Sample Components` which can be used for applying simple delta compensation. You can enable and disable the component to toggle delta compensation of the currently playing animation on and off. + * `SkeletonRagdoll` and `SkeletonRagdoll2D` now support bone scale at any bone in the skeleton hierarchy. This includes negative scale and root bone scale. + * `Attachment.GetRemappedClone(Sprite)` method now provides an additional optional parameter `useOriginalRegionScale`. When set to `true`, the replaced attachment's scale is used instead of the Sprite's `Pixel per Unity` setting, allowing for more consistent scaling. *Note:* When remapping Sprites, be sure to set the Sprite's `Mesh Type` to `Full Rect` and not `Tight`, otherwise the scale will be wrong. + * `SkeletonGraphic` now **supports all Slot blend modes** when `Advanced - Multiple Canvas Renderers` is enabled in the Inspector. The `SkeletonGraphic` Inspector now provides a `Blend Mode Materials` section where you can assign `SkeletonGraphic` materials for each blend mode, or use the new default materials. New `SkeletonGraphic` shaders and materials have been added for each blend mode. The `BlendModes.unity` example scene has been extended to demonstrate this new feature. For detailed information see the [`SkeletonGraphic documentation page`](http://esotericsoftware.com/spine-unity#Parameters). + * Timeline clips now also offer `Don't End with Clip` and `Clip End Mix Out Duration` parameters. By default when empty space follows the clip on the timeline, the empty animation is set on the track with a MixDuration of `Clip End Mix Out Duration`. Set `Don't End with Clip` to `true` to continue playing the clip's animation instead and mimic the old 3.8 behaviour. If you prefer pausing the animation instead of mixing out to the empty animation, set `Clip End Mix Out Duration` to a value less than 0, then the animation is paused instead. + * Prefabs containing `SkeletonRenderer`, `SkeletonAnimation` and `SkeletonMecanim` now provide a proper Editor preview, including the preview thumbnail. + * `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`) now provide a property `Advanced - Fix Prefab Override MeshFilter`, which when enabled fixes the prefab always being marked as changed. It sets the MeshFilter's hide flags to `DontSaveInEditor`. Unfortunately this comes at the cost of references to the `MeshFilter` by other components being lost, therefore this parameter defaults to `false` to keep the safe existing behaviour. + * `BoundingBoxFollower` and `BoundingBoxFollowerGraphic` now provide previously missing `usedByEffector` and `usedByComposite` parameters to be set at all generated colliders. + * `BoneFollower` and `BoneFollowerGraphic` now provide an additional `Follow Parent World Scale` parameter to allow following simple scale of parent bones (rotated/skewed scale can't be supported). + * Improved `Advanced - Fix Prefab Override MeshFilter` property for `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`), now providing an additional option to use a global value which can be set in `Edit - Preferences - Spine`. + * Timeline naming improvements: `Spine AnimationState Clip` Inspector parameter `Custom Duration` changed and inverted to `Default Mix Duration` for more clarity. Shortened all Timeline add track menu entries from: `Spine.Unity.Playables - ` to `Spine - `, `Spine Animation State Track` to `SkeletonAnimation Track`, `Spine AnimationState Graphic Track` to `SkeletonGraphic Track`, and `Spine Skeleton Flip Track` to `Skeleton Flip Track`. + * Timeline track appearance and Inspector: Tracks now show icons and track colors to make them easier to distinguish. When a Track is selected, the Inspector now shows an editable track name which was previously only editable at the Timeline asset. + * Added example component `SkeletonRenderTexture` to render a `SkeletonRenderer` to a `RenderTexture`, mainly for proper transparency. Added an example scene named `RenderTexture FadeOut Transparency` that demonstrates usage for a fadeout transparency effect. + * Added another fadeout example component named `SkeletonRenderTextureFadeout` which takes over transparency fadeout when enabled. You can use this component as-is, attach it in disabled state and enable it to start a fadeout effect. + * Timeline clips now offer an additional `Alpha` parameter for setting a custom constant mix alpha value other than 1.0, just as `TrackEntry.Alpha`. Defaults to 1.0. + * `SkeletonGraphic` now provides additional render callback delegates `OnInstructionsPrepared`, `AssignMeshOverrideSingleRenderer` and `AssignMeshOverrideMultipleRenderers`. `OnInstructionsPrepared` is raised at the end of LateUpdate after render instructions are done, target renderers are prepared, and the mesh is ready to be generated. The two `AssignMeshOverride` delegates allow separate code to take over mesh and material assignment of a `SkeletonGraphic` component. + * Added example component `SkeletonGraphicRenderTexture` to render a `SkeletonGraphic` to a `RenderTexture` (similar as `SkeletonRenderTexture`), mainly for proper transparency. Extended example scene `RenderTexture FadeOut Transparency` accordingly. + +* **Changes of default values** + +* **Deprecated** + +* **Restructuring (Non-Breaking)** + +### XNA/MonoGame +* Added normalmap support via `SpineEffectNormalmap` and support for loading multiple texture layers following a suffix-pattern. Please see the example code on how to use them. +* Added `Z` property to `SkeletonRenderer` to provide a constant Z offset that's added to all vertices. +* Added `ZSpacing` property to `SkeletonRenderer` to allow specifying the distance on the z-axis between attachments. +* SkeletonDebugRenderer bone color attributes are now public and modifiable by user. + + +## Java +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `Region.names` and `Region.values`. +* Added support for reverse animation playback via `TrackEntry.getReverse()` and `TrackEntry.setReverse()`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. +* **Breaking change:** Removed `SkeletonData` and `Skeleton` methods: `findBoneIndex`, `findSlotIndex`. Bones and slots have an `index` field that should be used instead. + +### libGDX +* Exposed colors in `SkeletonRendererDebug`. +* Updated to libGDX 1.10.0. + +## Lua +* Expose non-essential colors on bones, bounding box, clipping, and path attachments. +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +* Added support for reverse animation playback via `TrackEntry.reverse`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. + +### Love2D + +### Corona +* **Breaking change:** spine-corona has been renamed to spine-solar2d. Change your `require "spine-corona.spine"` statements to `require "spine-solar2d.spine"` + +## Typescript/Javascript +* **Breaking change:** refactored to ECMAScript modules. See this [blog post](http://esotericsoftware.com/blog/spine-goes-npm) as well as the updated [README.md](spine-ts/README.md). +* **Breaking change:** the `build/` folder and compiled artifacts are no longer part of the repository. Instead, `npm run build` in `spine-ts/` to generate ECMAScript modules and IIFE modules in `spine-/dist`. +* **Breaking change:** the `.npmignore` and `package.json` files in the root directory have been deleted. Use the corresponding files in `spine-ts/` instead, or better, depend on the packages from the NPM registry. +* Updated runtime to be compatible with TypeScript 3.6.3. +* Added `AssetManager#setRawDataURI(path, data)`. Allows to set raw data URIs for a specific path, which in turn enables embedding assets into JavaScript/HTML. +* Expose non-essential colors on bones, bounding box, clipping, and path attachments. +* Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +* Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +* Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +* Added support for reverse animation playback via `TrackEntry.reverse`. +* Added proportional spacing mode support for path constraints. +* Added support for uniform scaling for two bone IK. +* Fixed applying a constraint reverting changes from other constraints. +* `AssetManager` constructor now takes an option `Downloader` instance. Used to download assets only once and share them between `AssetManager` instances. +* Added web worker support to `AssetManager`. +* Added various default parameters to `AnimationState` methods for ease of use. +* Added `SpineCanvas`, a simpler way to render a scene via spine-webgl. See `spine-ts/spine-webgl/examples/barebones.html` and `spine-ts/spine-webgl/examples/mix-and-match.html`. + +### WebGL backend +* **Breaking change:** removed `SharedAssetManager`. Use `AssetManager` with a shared `Downloader` instance instead. +* **Breaking change:** the global object `spine.webgl` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.webgl.` in your source code with `spine.`. + +### Canvas backend +* Renderer now accounts for whitespace stripping. +* **Breaking change:** the global object `spine.canvas` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.canvas.` in your source code with `spine.`. + +### Three.js backend +* `SkeletonMesh` now takes an optional `SkeletonMeshMaterialParametersCustomizer` function that allows you to modify the `ShaderMaterialParameters` before the material is finalized. Use it to modify things like THREEJS' `Material.depthTest` etc. See #1590. +* **Breaking change:** the global object `spine.canvas` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.threejs.` in your source code with `spine.`. +* **Breaking change:** the default fragment shader of `SkeletonMeshMaterial` now explicitely discards fragments with alpha < 0.5. See https://github.com/EsotericSoftware/spine-runtimes/issues/1985 +* **Breaking change:** reversal of the previous breaking change: the default fragment shader of `SkeletonMeshMaterial` does no longer discard fragments with alpha < 0.5. Pass a `SkeletonMeshMaterialParametersCustomizer` to the `SkeletonMesh` constructor, and modify `parameters.alphaTest` to be > 0. + +### Player +* Added `SpinePlayerConfig.rawDataURIs`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. See the example for a demonstration. +* Added `SpinePlayerConfig.frame`. If set, the callback is called each frame, before the skeleton is posed or drawn. +* Added `SpinePlayerConfig.update`. If set, the callback is called each frame, just after the skeleton is posed. +* Added `SpinePlayerConfig.draw`. If set, the callback is called each frame, just after the skeleton is drawn. +* Added `SpinePlayerConfig.downloader`. The `spine.Downloader` instance can be shared between players so assets are only downloaded once. +* If `SpinePlayerConfig.jsonURL` ends with an anchor, the anchor text is used to find the skeleton in the specified JSON file. +* Added `SpinePlayer.dispose()`, disposes all CPU and GPU side resources, removes all listeners, and removes the player DOM from the parent. + +# 3.8 + +## AS3 +* **Breaking changes** + * Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + * Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + * Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. + +* **Additions** + * Added `SkeletonBinary` to load binary `.skel` files. See `MixAndMatchExample.as` in `spine-startling-example`. + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin#getAttachments()`. Returns all attachments in the skin. + * Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `Skin#addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin#copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### Starling +* Added `MixAndMatchExample.as` to demonstrate the new Skin API additions and how to load binary `.skel` files. +* Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. + +## C +* **Breaking changes** + * Renamed `spSlot#attachmentVertices` to `spSlot#deform`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `spSkin_addAttachment()` to `Skin#spSkin_addAttachment()`. + * Removed `spVertexAttachment_applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `spDeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `spMeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * Added `x` and `y` coordinates for setup pose AABB in `spSkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `spSkin_getAttachments()`. Returns all attachments in the skin. + * Added `spSkin_getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `spSkin_addSkin(spSkin* skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `spSkin_copySkin(spSkin* skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `spVertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * All attachments inserted into skins are reference counted. When the last skin referencing an attachment is disposed, the attachment will also be disposed. + * Added `spAttachment_copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `spMeshAttachment_newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### Cocos2d-Objc +* Added mix-and-match example to demonstrate the new Skin API. +* Added `IKExample`. +* Added `SkeletonAnimation preUpdateWorldTransformsListener` and `SkeletonAnimation postUpdateWorldTransformsListener`. When set, these callbacks will be invokved before and after the skeleton's `updateWorldTransforms()` method is called. See the `IKExample` how it can be used. + +### SFML +* Added mix-and-match example to demonstrate the new Skin API. +* Added `IKExample`. + +## C++ +* **Breaking Changes** + * Renamed `Slot::getAttachmentVertices()` to `Slot::getDeform()`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin::addAttachment()` to `Skin::setAttachment()`. + * Removed `VertexAttachment::applyDeform()` and replaced it with `VertexAttachment::getDeformAttachment()`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `_inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * `AnimationState` and `TrackEntry` now also accept a subclass of `AnimationStateListenerObject` as a listener for animation events in the overloaded `setListener()` method. + * `SkeletonBinary` and `SkeletonJson` now parse and set all non-essential data like audio path. + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin#getAttachments()`. Returns all attachments in the skin. + * Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `Skin#addSkin(Skin &skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin#copySkin(Skin &skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * All attachments inserted into skins are reference counted. When the last skin referencing an attachment is disposed, the attachment will also be disposed. + * Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + * Exposed `x` and `y` on `SkeletonData` through getters and setters. + +### Cocos2d-x +* Updated to cocos2d-x 3.17.1 +* Added mix-and-match example to demonstrate the new Skin API. +* Exmaple project requires Visual Studio 2019 on Windows +* Added `IKExample`. +* Added `SkeletonAnimation::setPreUpdateWorldTransformsListener()` and `SkeletonAnimation::setPreUpdateWorldTransformsListener()`. When set, these callbacks will be invokved before and after the skeleton's `updateWorldTransforms()` method is called. See the `IKExample` how it can be used. + +### SFML +* Added mix-and-match example to demonstrate the new Skin API. + +### UE4 +* Added `bAutoPlaying` flag to `USpineSkeletonAnimationComponent`. When `false`, the component will not update the internal animation state and skeleton. +* Updated example project to UE 4.22. +* (Re-)Importing Spine assets will perform a version compatibility check and alert users about mismatches in editor mode. +* `USpineSkeletonRendererComponent` allows passing a `USpineSkeletonComponent` to update it. This way, the renderer component can be used without a skeleton component on the same actor. +* Added blueprint-callable methods to `SpineSkeletonComponent` and `SpineSkeletonAnimationComponent` to query and set skins, and enumerate bones, slots, and animations. +* Extended skeleton data editor preview. The preview now shows bones, slots, animations, and skins found in the skeleton data. See this [blog post](http://esotericsoftware.com/blog/Unreal-Engine-4-quality-of-life-improvements). +* Added preview animation and skin fields, allowing you to preview animations and skins right in the editor. See this [blog post](http://esotericsoftware.com/blog/Unreal-Engine-4-quality-of-life-improvements). +* Removed dependency on `RHI`, `RenderCore`, and `ShaderCore`. +* Re-importing atlases and their textures now works consistently in all situations. +* Added mix-and-match example to demonstrate the new Skin API. +* Materials on `SkeletonRendererComponent` are now blueprint read and writeable. This allows setting dynamic material instances at runtime. +* Added `InitialSkin` property to `USpineWidget`. This allows previewing different skins in the UMG Designer. Initial skins can still be overridden via blueprint events such as `On Initialized`. +* `USpineWidget` will now report its own desired size based on the setup pose dimensions of the skeleton. This is used when selecting `Size to content` on a `USpineWidget` in the designer. +* Updated example project to UE 5.2. + +## C# ## +* **Breaking changes** + * **Changed `IkConstraintData.Bones` type from `List` to `ExposedList`** for unification reasons. *Note: this modification will most likely not affect user code.* + * Renamed `Slot.AttachmentVertices` to `Slot.Deform`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin.AddAttachment()` to `Skin.SetAttachment()`. + * Removed `FindAttachmentsForSlot(int slotIndex, List attachments)` and `FindNamesForSlot (int slotIndex, List names)` and replaced it with `Skin.GetAttachments(int slotIndex, List attachments)` which returns the combined `SkinEntry` object holding both name and attachment. + * Removed `VertexAttachment.ApplyDeform()` and replaced it with `VertexAttachment.DeformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin.GetAttachments()`. Returns all attachments in the skin. + * Added `Skin.GetAttachments(int slotIndex, List attachments)`. Returns all attachements in the skin for the given slot index. This method replaces `FindAttachmentsForSlot` and `FindNamesForSlot`. + * Added `Skin.AddSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin.CopySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment.Copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment.NewLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### Unity + +* **Breaking changes** + * **Officially supported Unity versions are 2017.1-2020.2**. + * **Spine `.asmdef` files are again active by default**. They have previously been deactivated to `.txt` extension which is now no longer necessary. + * **Removed PoseSkeleton() and PoseWithAnimation()** extension methods to prevent issues where animations are not mixed out. Problem was that these methods did not set AnimationState, leaving incorrect state at e.g. attachments enabled at slots when starting subsequent animations. As a replacement you can use `AnimationState.ClearTrack(0);` followed by `var entry = AnimationState.SetAnimation(0, animation, loop); entry.TrackTime = time` to achieve similar behaviour. + * **The `Shadow alpha cutoff` shader parameter is now respecting slot-color alpha** values at all Spine shaders. A fragment's texture color alpha is multiplied with slot-color alpha before the result is tested against the `Shadow alpha cutoff` threshold. + * **Removed redundant `Attachment.GetClone()` and `MeshAttachment.GetLinkedClone()` extension methods**. Use methods `Attachment.Copy` and `MeshAttachment.NewLinkedMesh()` instead. + * **Renamed extension method `Attachment.GetClone(bool cloneMeshesAsLinked)` to `Attachment.GetCopy(bool cloneMeshesAsLinked)`** to follow the naming scheme of the Spine API. + * `SkeletonDataAsset.atlasAssets` is now an array of the base class `AtlasAssetBase` instead of `SpineAtlasAsset`, which provides `IEnumerable<> Materials` instead of `List<> materials`. Replace any access via `atlasAsset.materials[0]` with `atlasAsset.Materials.First()` and add a `using System.Linq;` statement. + * **Changed `MeshAttachment.GetLinkedMesh()` method signatures:** removed optional parameters `bool inheritDeform = true, bool copyOriginalProperties = false`. + * Changed namespace `Spine.Unity.Modules` to `Spine.Unity` and `Spine.Unity.Examples` after restructuring (see section below) in respective classes: + * When receiving namespace related errors, replace using statements of `using Spine.Unity.Modules.AttachmentTools;` with `using Spine.Unity.AttachmentTools;`. You can remove `using Spine.Unity.Modules;` statements when a `using Spine.Unity` statement is already present in the file. + * `AttachmentTools`, `SkeletonPartsRenderer`, `SkeletonRenderSeparator`, `SkeletonRendererCustomMaterials` changed to namespace `Spine.Unity`. + * `SkeletonGhost`, `SkeletonGhostRenderer`, `AtlasRegionAttacher`, `SkeletonGraphicMirror`, `SkeletonRagdoll`, `SkeletonRagdoll2D`, `SkeletonUtilityEyeConstraint`, `SkeletonUtilityGroundConstraint`, `SkeletonUtilityKinematicShadow` changed to namespace `Spine.Unity.Examples`. + * Split `Editor/Utility/SpineEditorUtilities` class into multiple files with partial class qualifier. + * Nested classes `SpineEditorUtilities.AssetUtility` and `SpineEditorUtilities.EditorInstantiation` are now no longer nested. If you receive namespace related errors, replace any occurrance of + * `SpineEditorUtilities.AssetUtility` with `AssetUtility` and + * `SpineEditorUtilities.EditorInstantiation` with `EditorInstantiation`. + * **Timeline Support has been moved to a separate UPM Package** Previously the Spine Timeline integration was located in the `Modules/Timeline` directory and was deactivated by default, making it necessary to activate it via the Spine Preferences. Now the Timeline integration has been moved to an additional UPM package which can be found under `Modules/com.esotericsoftware.spine.timeline`. + * **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + a) the `Packages` directory in your project where it will automatically be loaded, or + b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + The Project panel should now show an entry `Spine Timeline Extensions` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + * `SkeletonMecanim`'s `Layer Mix Mode` enum name `MixMode.SpineStyle` has been renamed to `MixMode.Hard`. This is most likely not set via code and thus unlikely to be a problem. Serialized scenes and prefabs are unaffected. + * `SkeletonRootMotion` and `SkeletonMecanimRootMotion` components now support arbitrary bones in the hierarchy as `Root Motion Bone`. Previously there were problems when selecting a non-root bone as `Root Motion Bone`. `Skeleton.ScaleX` and `.ScaleY` and parent bone scale is now respected as well. + +* **Additions** + * **Spine Preferences stored in Assets/Editor/SpineSettings.asset** Now Spine uses the new `SettingsProvider` API, storing settings in a SpineSettings.asset file which can be shared with team members. Your old preferences are automatically migrated to the new system. + * Added support for Unity's SpriteMask to `SkeletonAnimation` and `SkeletonMecanim`. All mask interaction modes are supported. See this [blog post](http://esotericsoftware.com/blog/Unity-SpriteMask-and-RectMask2D-support). + * Added support for Unity's RectMask2D to SkeletonGraphics. See this [blog post](http://esotericsoftware.com/blog/Unity-SpriteMask-and-RectMask2D-support). + * Added `Create 2D Hinge Chain` button at `SkeletonUtilityBone` inspector, previously only `Create 3D Hinge Chain` was available. + * **Now supporting Lightweight Render Pipeline (LWRP) through an additional UPM package.** + * **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + * a) the `Packages` directory in your project where it will automatically be loaded, or + * b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + > If you are using git and Unity 2019.2 or newer versions and receive an error that dependencies could not be resolved by the package manager (only higher versions of Unity's `Lightweight RP` package are available, e.g. `6.9.0` and up), please copy the prepared package-UNITYVERSION.json file for your Unity version (e.g. `package-2019.2.json`) over the existing package.json file to change the dependency accordingly. Unfortunately Unity's Package Manager does not provide a way to specify a version range for a dependency like "5.7.2 - 6.9.0" yet, so this manual step is necessary for git users. + + The Project panel should now show an entry `Spine Lightweight RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + * **Usage:** The package provides two shaders specifically built for the lightweight render pipeline: + * `Lightweight Render Pipeline/Spine/Skeleton`, as a lightweight variant of the `Spine/Skeleton` shader, + * `Lightweight Render Pipeline/Spine/Skeleton Lit`, as a lightweight variant of the `Spine/Skeleton Lit` shader and + * `Lightweight Render Pipeline/Spine/Sprite`, as a lightweight variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the lightweight render pipeline. The shaders can be assigned to materials as usual and will respect your settings of the assigned `LightweightRenderPipelineAsset` under `Project Settings - Graphics`. + * **Restrictions** As all Spine shaders, the LWRP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + * **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.lwrp-shaders-3.8/Examples/LWRP Shaders.unity` that demonstrates usage of the LWRP shaders. + * Added `Spine/Skeleton Lit ZWrite` shader. This variant of the `Spine/Skeleton Lit` shader writes to the depth buffer with configurable depth alpha threshold. Apart from that it is identical to `Spine/Skeleton Lit`. + * Additional yield instructions to wait for animation track events `End`, `Complete` and `Interrupt`. + * `WaitForSpineAnimationComplete` now proves an additional `bool includeEndEvent` parameter, defaults to `false` (previous behaviour). + * Added a new `WaitForSpineAnimationEnd` yield instruction. + * Added a new generic `WaitForSpineAnimation` yield instruction which can be configured to wait for any combination of animation track events. It is now used as base class for `WaitForSpineAnimationComplete` and `WaitForSpineAnimationEnd`. + * Additional **Fix Draw Order** parameter at SkeletonRenderer, defaults to `disabled` (previous behaviour). + Applies only when 3+ submeshes are used (2+ materials with alternating order, e.g. "A B A"). + If true, MaterialPropertyBlocks are assigned at each material to prevent aggressive batching of submeshes + by e.g. the LWRP renderer, leading to incorrect draw order (e.g. "A1 B A2" changed to "A1A2 B"). + You can leave this parameter disabled when everything is drawn correctly to save the additional performance cost. + * **Additional Timeline features.** SpineAnimationStateClip now provides a `Speed Multiplier`, a start time offset parameter `Clip In`, support for blending successive animations by overlapping tracks. An additional `Use Blend Duration` parameter *(defaults to true)* allows for automatic synchronisation of MixDuration with the current overlap blend duration. An additional Spine preferences parameter `Use Blend Duration` has been added which can be disabled to default to the previous behaviour before this update. + * Additional `SpriteMask and RectMask2D` example scene added for demonstration of mask setup and interaction. + * `Real physics hinge chains` for both 2D and 3D physics. The [SkeletonUtilityBone](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) Inspector provides an interface to create 2D and 3D hinge chains. Previously created chains have only been respecting gravity, but not momentum of the skeleton or parent bones. The new physics rig created when pressing `Create 3D Hinge Chain` and `Create 2D Hinge Chain` creates a more complex setup that also works when flipping the skeleton. Note that the chain root node is no longer parented to bones of the skeleton. This is a requirement in Unity to have momentum applied properly - do not reparent the chain root to bones of your skeleton, or you will loose any momentum applied by the skeleton's movement. + * `Outline rendering functionality for all shaders.` Every shader now provides an additional set of `Outline` parameters to enable custom outline rendering. When outline rendering is enabled via the `Material` inspector, it automatically switches the shader to the respective `Spine/Outline` shader variant. Outlines are generated by sampling neighbour pixels, so be sure to add enough transparent padding when exporting your atlas textures to fit the desired outline width. In order to enable outline rendering at a skeleton, it is recommended to first prepare an additional outline material copy and then switch the material of the target skeleton to this material. This prevents unnecessary additional runtime material copies and drawcalls. Material switching can be prepared via a [SkeletonRendererCustomMaterials](http://esotericsoftware.com/spine-unity#SkeletonRendererCustomMaterials) component and then enabled or disabled at runtime. Alternatively, you can also directly modify the `SkeletonRenderer.CustomMaterialOverride` property. + Outline rendering is fully supported on `SkeletonGraphic` shaders as well. + * Added `SkeletonRenderer.EditorSkipSkinSync` scripting API property to be able to set custom skins in editor scripts. Enable this property when overwriting the Skeleton's skin from an editor script. Without setting this parameter, changes will be overwritten by the next inspector update. Only affects Inspector synchronisation of skin with `initialSkinName`, not startup initialization. + * All `Spine/SkeletonGraphic` shaders now provide a parameter `CanvasGroup Compatible` which can be enabled to support `CanvasGroup` alpha blending. For correct results, you should then disable `Pma Vertex Colors` in the `SkeletonGraphic` Inspector, in section `Advanced` (otherwise Slot alpha will be applied twice). + * **Now supporting Universal Render Pipeline (URP), including the 2D Renderer pipeline, through an additional UPM package.** + * **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + * a) the `Packages` directory in your project where it will automatically be loaded, or + * b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + The Project panel should now show an entry `Spine Universal RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + * **Usage:** The package provides two shaders specifically built for the universal render pipeline: + * `Universal Render Pipeline/Spine/Skeleton`, as a universal variant of the `Spine/Skeleton` shader, + * `Universal Render Pipeline/Spine/Skeleton Lit`, as a universal variant of the `Spine/Skeleton Lit` shader, + * `Universal Render Pipeline/Spine/Sprite`, as a universal variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the universal render pipeline, + * `Universal Render Pipeline/2D/Spine/Skeleton Lit`, as a universal 2D Renderer variant of the `Spine/Skeleton Lit` shader, and + * `Universal Render Pipeline/2D/Spine/Sprite`, as a universal 2D Renderer variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders. + The shaders can be assigned to materials as usual and will respect your settings of the assigned `UniversalRenderPipelineAsset` under `Project Settings - Graphics`. + * **Restrictions** As all Spine shaders, the URP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + * **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.urp-shaders-3.8/Examples/URP Shaders.unity` that demonstrates usage of the URP shaders. + * Spine Preferences now provide an **`Atlas Texture Settings`** parameter for applying customizable texture import settings at all newly imported Spine atlas textures. + When exporting atlas textures from Spine with `Premultiply alpha` enabled (the default), you can leave it at `PMATexturePreset`. If you have disabled `Premultiply alpha`, set it to the included `StraightAlphaTexturePreset` asset. You can also create your own `TextureImporter` `Preset` asset and assign it here (include `PMA` or `Straight` in the name). In Unity versions before 2018.3 you can use `Texture2D` template assets instead of the newer `Preset` assets. Materials created for imported textures will also have the `Straight Alpha Texture` parameter configured accordingly. + * All `Sprite` shaders (including URP and LWRP extension packages) now provide an additional `Fixed Normal Space` option `World-Space`. PReviously options were limited to `View-Space` and `Model-Space`. + * `SkeletonGraphic` now fully supports [`SkeletonUtility`](http://esotericsoftware.com/spine-unity#SkeletonUtility) for generating a hierarchy of [`SkeletonUtilityBones`](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) in both modes `Follow` and `Override`. This also enables creating hinge chain physics rigs and using `SkeletonUtilityConstraints` such as `SkeletonUtilityGroundConstraint` and `SkeletonUtilityEyeConstraint` on `SkeletonGraphic`. + * Added `OnMeshAndMaterialsUpdated` callback event to `SkeletonRenderer` and `SkeletonGraphic`. It is issued at the end of `LateUpdate`, before rendering. + * Added `Skeleton-OutlineOnly` single pass shader to LWRP and URP extension modules. It can be assigned to materials as `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly`. This allows for separate outline child *GameObjects* that reference the existing Mesh of their parent, and re-draw the mesh using this outline shader. + * Added example component `RenderExistingMesh` to render a mesh again with different materials, as required by the new `Skeleton-OutlineOnly` shaders. + In URP the outline has to be rendered via a separate GameObject as URP does not allow multiple render passes. To add an outline to your SkeletenRenderer: + 1) Add a child GameObject and move it a bit back (e.g. position Z = 0.01). + 2) Add a `RenderExistingMesh` component, provided in the `Spine Examples/Scripts/Sample Components` directory. + 3) Copy the original material, add *_Outline* to its name and set the shader to `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly`. + 4) Assign this *_Outline* material at the `RenderExistingMesh` component under *Replacement Materials*. + * Added `Outline Shaders URP` example scene to URP extension module to demonstrate the above additions. + * Added support for Unity's [`SpriteAtlas`](https://docs.unity3d.com/Manual/class-SpriteAtlas.html) as atlas provider (as an alternative to `.atlas.txt` and `.png` files) alongside a skeleton data file. There is now an additional `Spine SpriteAtlas Import` tool window accessible via `Window - Spine - SpriteAtlas Import`. Additional information can be found in a new section on the [spine-unity documentation page](http://esotericsoftware.com/spine-unity#Advanced---Using-Unity-SpriteAtlas-as-Atlas-Provider). + * Added support for **multiple atlas textures at `SkeletonGraphic`**. You can enable this feature by enabling the parameter `Multiple CanvasRenders` in the `Advanced` section of the `SkeletonGraphic` Inspector. This automatically creates the required number of child `CanvasRenderer` GameObjects for each required draw call (submesh). + * Added support for **Render Separator Slots** at `SkeletonGraphic`. Render separation can be enabled directly in the `Advanced` section of the `SkeletonGraphic` Inspector, it does not require any additional components (like `SkeletonRenderSeparator` or `SkeletonPartsRenderer` for `SkeletonRenderer` components). When enabled, additional separator GameObjects will be created automatically for each separation part, and `CanvasRenderer` GameObjects re-parented to them accordingly. The separator GameObjects can be moved around and re-parented in the hierarchy according to your requirements to achieve the desired draw order within your `Canvas`. A usage example can be found in the updated `Spine Examples/Other Examples/SkeletonRenderSeparator` scene. + * Added `SkeletonGraphicCustomMaterials` component, providing functionality to override materials and textures of a `SkeletonGraphic`, similar to `SkeletonRendererCustomMaterials`. Note: overriding materials or textures per slot is not provided due to structural limitations. + * Added **Root Motion support** for `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic` via new components `SkeletonRootMotion` and `SkeletonMecanimRootMotion`. The `SkeletonAnimation` and `SkeletonGraphic` component Inspector now provides a line `Root Motion` with `Add Component` and `Remove Component` buttons to add/remove the new `SkeletonRootMotion` component to your GameObject. The `SkeletonMecanim` Inspector detects whether root motion is enabled at the `Animator` component and adds a `SkeletonMecanimRootMotion` component automatically. + * `SkeletonMecanim` now provides an additional `Custom MixMode` parameter under `Mecanim Translator`. It is enabled by default in version 3.8 to maintain current behaviour, using the set `Mix Mode` for each Mecanim layer. When disabled, `SkeletonMecanim` will use the recommended `MixMode` according to the layer blend mode. Additional information can be found in the [Mecanim Translator section](http://esotericsoftware.com/spine-unity#Parameters-for-animation-blending-control) on the spine-unity documentation pages. + * Added **SkeletonGraphic Timeline support**. Added supprot for multi-track Timeline preview in the Editor outside of play mode (multi-track scrubbing). See the [Timeline-Extension-UPM-Package](http://esotericsoftware.com/spine-unity#Timeline-Extension-UPM-Package) section of the spine-unity documentation for more information. + * Added support for double-sided lighting at all `SkeletonLit` shaders (including URP and LWRP packages). + * Added frustum culling update mode parameters `Update When Invisible` (Inspector parameter) and `UpdateMode` (available via code) to all Skeleton components. This provides a simple way to disable certain updates when the `Renderer` is no longer visible (outside all cameras, culled in frustum culling). The new `UpdateMode` property allows disabling updates at a finer granularity level than disabling the whole component. Available modes are: `Nothing`, `OnlyAnimationStatus`, `EverythingExceptMesh` and `FullUpdate`. + * Added a new `Spine/Outline/OutlineOnly-ZWrite` shader to provide correct outline-only rendering. Note: the shader requires two render passes and is therefore not compatible with URP. The `Spine Examples/Other Examples/Outline Shaders` example scene has been updated to demonstrate the new shader. + * Added `OnMeshAndMaterialsUpdated` callback event to `SkeletonRenderSeparator` and `SkeletonPartsRenderer`. It is issued at the end of `LateUpdate`, before rendering. + * Added `Root Motion Scale X/Y` parameters to `SkeletonRootMotionBase` subclasses (`SkeletonRootMotion` and `SkeletonMecanimRootMotion`). Also providing `AdjustRootMotionToDistance()` and other methods to allow for easy delta compensation. Delta compensation can be used to e.g. stretch a jump to a given distance. Root motion can be adjusted at the start of an animation or every frame via `skeletonRootMotion.AdjustRootMotionToDistance(targetPosition - transform.position, trackIndex);`. + * Now providing a `Canvas Group Tint Black` parameter at the `SkeletonGraphic` Inspector in the `Advanced` section. When using the `Spine/SkeletonGraphic Tint Black` shader you can enable this parameter to receive proper blending results when using `Additive` blend mode under a `CanvasGroup`. Be sure to also have the parameter `CanvasGroup Compatible` enabled at the shader. Note that the normal `Spine/SkeletonGraphic` does not support `Additive` blend mode at a `CanvasGroup`, as it requires additional shader channels to work. + * Added `Mix and Match Skins` example scene to demonstrate how the 3.8 Skin API and combining skins can be used for a wardrobe and equipment use case. + * Spine Timeline Extensions: Added `Hold Previous` parameter at `SpineAnimationStateClip`. + * Added more warning messages at incompatible SkeletonRenderer/SkeletonGraphic Component vs Material settings. They appear both as an info box in the Inspector as well as upon initialization in the Console log window. The Inspector box warnings can be disabled via `Edit - Preferences - Spine`. + * Now providing `BeforeApply` update callbacks at all skeleton animation components (`SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic`). + * Added `BoundingBoxFollowerGraphic` component. This class is a counterpart of `BoundingBoxFollower` that can be used with `SkeletonGraphic`. + * Added Inspector context menu functions `SkeletonRenderer - Add all BoundingBoxFollower GameObjects` and `SkeletonGraphic - Add all BoundingBoxFollowerGraphic GameObjects` that automatically generate bounding box follower GameObjects for every `BoundingBoxAttachment` for all skins of a skeleton. + * `GetRemappedClone()` now provides an additional parameter `pivotShiftsMeshUVCoords` for `MeshAttachment` to prevent uv shifts at a non-central Sprite pivot. This parameter defaults to `true` to maintain previous behaviour. + * `SkeletonRenderer` components now provide an additional update mode `Only Event Timelines` at the `Update When Invisible` property. This mode saves additional timeline updates compared to update mode `Everything Except Mesh`. + * Now all URP (Universal Render Pipeline) and LWRP (Lightweight Render Pipeline) shaders support SRP (Scriptable Render Pipeline) batching. See [Unity SRPBatcher documentation pages](https://docs.unity3d.com/Manual/SRPBatcher.html) for additional information. + * Sprite shaders now provide four `Diffuse Ramp` modes as an Inspector Material parameter: `Hard`, `Soft`, `Old Hard` and `Old Soft`. In spine-unity 3.8 it defaults to `Old Hard` to keep the behaviour of existing projects unchanged. From 4.0 on it defaults to `Hard` for newly created materials while existing ones remain unchanged. Note that `Old Hard` and `Old Soft` ramp versions were using only the right half of the ramp texture, and additionally multiplying the light intensity by 2, both leading to brighter lighting than without a ramp texture active. The new ramp modes `Hard` and `Soft` use the full ramp texture and do not modify light intensity, being consistent with lighting without a ramp texture active. + * Added **native support for slot blend modes** `Additive`, `Multiply` and `Screen` with automatic assignment at newly imported skeleton assets. `BlendModeMaterialAssets` are now obsolete and replaced by the native properties at `SkeletonDataAsset`. The `SkeletonDataAsset` Inspector provides a new `Blend Modes - Upgrade` button to upgrade an obsolete `BlendModeMaterialAsset` to the native blend modes properties. This upgrade will be performed automatically on imported and re-imported assets in Unity 2020.1 and newer to prevent reported `BlendModeMaterialAsset` issues in these Unity versions. spine-unity 4.0 and newer will automatically perform this upgrade regardless of the Unity version. + * `BoneFollower` and `BoneFollowerGraphic` components now provide better support for following bones when the skeleton's Transform is not the parent of the follower's Transform. Previously e.g. rotating a common parent Transform did not lead to the desired result, as well as negatively scaling a skeleton's Transform when it is not a parent of the follower's Transform. + * URP and LWRP `Sprite` and `SkeletonLit` shaders no longer require `Advanced - Add Normals` enabled to properly cast and receive shadows. It is recommended to disable `Add Normals` if normals are otherwise not needed. + * Added an example component `RootMotionDeltaCompensation` located in `Spine Examples/Scripts/Sample Components` which can be used for applying simple delta compensation. You can enable and disable the component to toggle delta compensation of the currently playing animation on and off. + * Root motion delta compensation now allows to only adjust X or Y components instead of both. Adds two parameters to `SkeletonRootMotionBase.AdjustRootMotionToDistance()` which default to adjusting both X and Y as before. The `RootMotionDeltaCompensation` example component exposes these parameters as public attributes. + * Root motion delta compensation now allows to also add translation root motion to e.g. adjust a horizontal jump upwards or downwards over time. This is necessary because a Y root motion of zero cannot be scaled to become non-zero. + * `Attachment.GetRemappedClone(Sprite)` method now provides an additional optional parameter `useOriginalRegionScale`. When set to `true`, the replaced attachment's scale is used instead of the Sprite's `Pixel per Unity` setting, allowing for more consistent scaling. *Note:* When remapping Sprites, be sure to set the Sprite's `Mesh Type` to `Full Rect` and not `Tight`, otherwise the scale will be wrong. + +* **Changes of default values** + * `SkeletonMecanim`'s `Layer Mix Mode` now defaults to `MixMode.MixNext` instead of `MixMode.MixAlways`. + * `BlendModeMaterialAsset` and it's instance `Default BlendModeMaterials.asset` now have `Apply Additive Material` set to `true` by default in order to apply all blend modes by default. + +* **Deprecated** + * Deprecated `Modules/SlotBlendModes/SlotBlendModes` component. Changed namespace from `Spine.Unity.Modules` to `Spine.Unity.Deprecated`. Moved to `Deprecated/SlotBlendModes`. + +* **Restructuring (Non-Breaking)** + + Note: The following changes will most likely not affect users of the Spine-Unity runtime as the API remains unchanged and no references are invalidated. + * Removed duplicates of `.cginc` files in `Modules/Shaders/Sprite` that were also present in the `Modules/Shaders/Sprite/CGIncludes` directory. + * Moved shaders from `Modules/Shaders` to `Shaders` directory. + * Moved shaders from `Modules/SkeletonGraphic/Shaders` to `Shaders/SkeletonGraphic`. + * Renamed shader `Shaders/Spine-SkeletonLit.shader` to `Shaders/Spine-Skeleton-Lit.shader`. + * Moved components from `SkeletonGraphic` to `Components` and `Components/Following` except for `SkeletonGraphicMirror` which was moved to `Spine Examples/Scripts/Sample Components`. + * Moved `BoneFollower`, `BoneFollowerGraphic` and `PointFollower` from `Components` directory to `Components/Following`. + * Moved `BoundingBoxFollower` component from `Modules/BoundingBoxFollower` to `Components/Following`. + * Moved `Modules/SkeletonRenderSeparator` directory to `Components/SkeletonRenderSeparator`. + * Moved `Modules/CustomMaterials` directory to `Components/SkeletonRendererCustomMaterials`. + * Moved `Asset Types/BlendModeMaterialsAsset.cs` class, `Shaders/BlendModes/Default BlendModeMaterials.asset` and materials from `Shaders/BlendModes` to `SkeletonDataModifierAssets/BlendModeMaterials` directory. + * Moved `Modules/Ghost` directory to `Spine Examples/Scripts/Sample Components/Ghost`. + * Moved `Modules/SkeletonUtility Modules` directory to `Spine Examples/Scripts/Sample Components/SkeletonUtility Modules`. + * Moved `Modules/AnimationMatchModifier` directory to `Spine Examples/Scripts/MecanimAnimationMatchModifier`. + * Moved `SkeletonRagdoll` and `SkeletonRagdoll2D` components from `Modules/Ragdoll` directory to `Spine Examples/Scripts/Sample Components/SkeletonUtility Modules`. + * Moved `AttachmentTools.cs` to `Utility` directory. + * Split the file `AttachmentTools` into 5 separate files for each contained class. No namespace or other API changes performed. + * Split the file `Mesh Generation/SpineMesh` into 4 separate files for each contained class. No namespace or other API changes performed. + * Moved `SkeletonExtensions.cs` to `Utility` directory. + * Moved `Modules/YieldInstructions` directory to `Utility/YieldInstructions`. + * Moved corresponding editor scripts of the above components to restructured directories as well. + * Renamed inspector editor class `PointFollowerEditor` to `PointFollowerInspector` for consistency reasons. + +### XNA/MonoGame +* Updated to latest MonoGame version 3.7.1 +* Rewrote example project to be cleaner and better demonstrate basic Spine features. +* Added mix-and-match example to demonstrate the new Skin API. +* Added normalmap support via `SpineEffectNormalmap` and support for loading multiple texture layers following a suffix-pattern. Please see the example code on how to use them. + +## Java +* **Breaking changes** + * Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + * Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * `JsonRollback` tool now converts from 3.8 JSON to 3.7. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin#getAttachments()`. Returns all attachments in the skin. + * Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `Skin#addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin#copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### libGDX +* `SkeletonViewer` can load a skeleton by specifying it as the first argument on the command line. +* Added mix-and-match example to demonstrate the new Skin API. + +## Lua +* **Breaking changes** + * Renamed `Slot:getAttachmentVertices()` to `Slot#deform`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin:addAttachment()` to `Skin#setAttachment()`. + * Removed `VertexAttachment:applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed the `.json` file format to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +* **Additions** + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin:getAttachments()`. Returns all attachments in the skin. + * Added `Skin:getAttachments(slotIndex)`. Returns all attachements in the skin for the given slot index. + * Added `Skin:addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin:copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment:copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment:newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + +### Love2D +* Added support for 0-1 RGBA color component range change in Löve 0.11+. Older Löve versions using the 0-255 range are still supported! +* Added mix-and-match example to demonstrate the new Skin API. + +### Corona +* Added mix-and-match example to demonstrate the new Skin API. + +## Typescript/Javascript +* **Breaking changes** + * Renamed `MixDirection.in/out` to `MixDirection.mixIn/mixOut` as it was crashing a JS compressor. + * Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + * Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + * Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + * Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + * Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + * Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + * Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + * Updated runtime to be compatible with TypeScript 3.6.3. + +* **Additions** + * Added support for loading binary data via `AssetManager#loadBinary()`. `AssetManager#get()` will return a `Uint8Array` for such assets. + * Added support for loading binaries via new `SkeletonBinary`. Parses a `Uint8Array`. + * Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + * Added support for rotated mesh region UVs. + * Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + * Improved Skin API to make it easier to handle mix-and-match use cases. + * Added `Skin#getAttachments()`. Returns all attachments in the skin. + * Added `Skin#getAttachments(slotIndex: number)`. Returns all attachements in the skin for the given slot index. + * Added `Skin#addSkin(skin: Skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + * Added `Skin#copySkin(skin: Skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + * Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + * Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + * Added IK softness. + * Added `AssetManager.setRawDataURI(path, data)`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. + * Added `AssetManager.loadAll()` to allow Promise/async/await based waiting for completion of asset load. See the `spine-canvas` examples. + * Added `Skeleton.getBoundRect()` helper method to calculate the bouding rectangle of the current pose, returning the result as `{ x, y, width, height }`. Note that this method will create temporary objects which can add to garbage collection pressure. + +### WebGL backend +* `Input` can now take a partially defined implementation of `InputListener`. +* Added mix-and-match example to demonstrate the new Skin API. + +### Canvas backend + +### Three.js backend +* `SkeletonMesh` now takes an optional `SkeletonMeshMaterialParametersCustomizer` function that allows you to modify the `ShaderMaterialParameters` before the material is finalized. Use it to modify things like THREEJS' `Material.depthTest` etc. See #1590. + +### Player +* `SpinePlayer#setAnimation()` can now be called directly to set the animation being displayed. +* The player supports loading `.skel` binary skeleton files by setting the `SpinePlayerConfig#skelUrl` field instead of `SpinePlayerConfig#jsonUrl`. +* Added `SpinePlayerConfig#rawDataURIs`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. See the example for a demonstration. + +# 3.7 + +## AS3 +* **Breaking changes** + * The completion event will fire for looped 0 duration animations every frame. + * `MixPose` is now called `MixBlend` + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Starling +* Added support for vertex effects. See `RaptorExample.as` +* Added 'getTexture()' method to 'StarlingTextureAtlasAttachmentLoader' +* Breaking change: if a skeleton requires two color tinting, you have to enable it via `SkeletonSprite.twoColorTint = true`. In this case the skeleton will use the `TwoColorMeshStyle`, which internally uses a different vertex layout and shader. This means that skeletons with two color tinting enabled will break batching and hence increase the number of draw calls in your app. +* Added `VertexEffect` and implementations `JitterEffect` and `SwirlEffect`. Allows you to modify vertices before they are submitted for drawing. See Starling changes. +* Fix issues with StarlingAtlasAttachmentLoader, see https://github.com/EsotericSoftware/spine-runtimes/issues/939 +* Fix issues with region trimming support, see https://github.com/EsotericSoftware/spine-runtimes/commit/262bc26c64d4111002d80e201cb1a3345e6727df +* Added support for overriding `StarlingAtlasAttachmentLoader#getTexture()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/ea7dbecb98edc74e439aa9ef90dcf6eed865f718 +* Texture atlas operations are no longer handled in `Starling#newRegionAttachment` and `Starling#newMeshAttachment` but delegated to the atlas. +* Added sample for additive animation blending, see https://github.com/EsotericSoftware/spine-runtimes/blob/6a556de01429878df47bb276a97959a8bdbbe32f/spine-starling/spine-starling-example/src/spine/examples/OwlExample.as +* Added sample on how to use bounding box attachment vertices https://github.com/EsotericSoftware/spine-runtimes/commit/e20428b02699226164fa73ba4b12f7d029ae6f4d +* Fully transparent meshes are not submitted for rendering. +* No hit-tests are performed when a skeleton is invisible. + +## C +* **Breaking changes** + * Listeners on `spAnimationState` and `spTrackEntry` will now also be called if a track entry gets disposed as part of disposing an animation state. + * The completion event will fire for looped 0 duration animations every frame. + * The spine-cocos2dx and spine-ue4 runtimes are now based on spine-cpp. See below for changes. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 + * `spMeshAttachment` has two new fields `regionTextureWith` and `regionTextureHeight`. These must be set in custom attachment loader. See `AtlasAttachmentLoader`. +* **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `spTransformConstraintData`. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `spVertexEffect` and corresponding implementations `spJitterVertexEffect` and `spSwirlVertexEffect`. Create/dispose through the corresponding `spXXXVertexEffect_create()/dispose()` functions. Set on framework/engine specific renderer. + * Functions in `extension.h` are not prefixed with `_sp` instead of just `_` to avoid interference with other libraries. + * Introduced `SP_API` macro. Every spine-c function is prefixed with this macro. By default, it is an empty string. Can be used to markup spine-c functions with e.g. ``__declspec` when compiling to a dll or linking to that dll. + * Added `void *userData` to `spAnimationState`to be consumed in callbacks. + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `spTrackEntry->mixBlend = SP_MIXBLEND_ADD)` on each track. To specify the blend percentage, set `spTrackEntry->alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Optimized attachment lookup to give a 40x speed-up. See https://github.com/EsotericSoftware/spine-runtimes/commit/cab81276263890b65d07fa2329ace16db1e365ff + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `spTrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Cocos2d-Objc +* Added vertex effect support to modify vertices of skeletons on the CPU. See `RaptorExample.m`. +* Explanation how to handle ARC, see https://github.com/EsotericSoftware/spine-runtimes/commit/a4f122b08c5e2a51d6aad6fc5a947f7ec31f2eb8 +* The super class `::update()` method of `SkeletonRenderer` is now called, see https://github.com/EsotericSoftware/spine-runtimes/commit/f7bb98185236a6d8f35bfefc70afe4f31e9ec9d2 +* Added improved tint-black shader. + +### SFML +* `spine-sfml.h` no longer defines `SPINE_SHORT_NAMES` to avoid collisions with other APIs. See #1058. +* Added support for vertex effects. See raptor example. +* Added premultiplied alpha support to `SkeletonDrawable`. Use `SkeletonDrawable::setUsePremultipliedAlpha()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/34086c1f41415309b2ecce86055f6656fcba2950 +* Added additive animation blending sample, see https://github.com/EsotericSoftware/spine-runtimes/blob/b7e712d3ca1d6be3ebcfe3254dc2cea9c44dda71/spine-sfml/example/main.cpp#L369 + +## C++ +* ** Additions ** + * Added C++ Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. + * Added parsing of non-essential data (fps, images path, audio path) to for `.json`/`.skel` parsers. + +### Cocos2d-x +* Added ETC1 alpha support, thanks @halx99! Does not work when two color tint is enabled. +* Added `spAtlasPage_setCustomTextureLoader()` which let's you do texture loading manually. Thanks @jareguo. +* Added `SkeletonRenderer:setSlotsRange()` and `SkeletonRenderer::createWithSkeleton()`. This allows you to split rendering of a skeleton up into multiple parts, and render other nodes in between. See `SkeletonRendererSeparatorExample.cpp` for an example. +* Fully transparent attachments will not be rendered, improving rendering performance. +* Added improved tint-black shader. +* Updated to cocos2d-x 3.16 +* The skeleton setup pose and world transform are now calculated on initialization to avoid flickering on start-up. +* Updated to cocos2d-x 3.17.1 +* **Breaking change**: Switched from [spine-c](spine-c) to [spine-cpp](spine-cpp) as the underlying Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. + * Added `Cocos2dAttachmentLoader` to be used when constructing an `Atlas`. Used by default by `SkeletonAnimation` and `SkeletonRenderer` when creating instances via the `createXXX` methods. + * All C structs and enums `spXXX` have been replaced with their C++ equivalents `spine::XXX` in all public interfaces. + * All instantiations via `new` of C++ classes from spine-cpp should contain `(__FILE__, __LINE__)`. This allows the tracking of instantations and detection of memory leaks via the `spine::DebugExtension`. + +### SFML +* Create a second SFML backend using [spine-cpp](spine-cpp/). See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. +* Added support for vertex effects. See raptor example. +* Added premultiplied alpha support to `SkeletonDrawable`. Use `SkeletonDrawable::setUsePremultipliedAlpha()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/34086c1f41415309b2ecce86055f6656fcba2950 +* Added additive animation blending sample, see https://github.com/EsotericSoftware/spine-runtimes/blob/b7e712d3ca1d6be3ebcfe3254dc2cea9c44dda71/spine-sfml/example/main.cpp#L369 + +### UE4 + * spine-c is now exposed from the plugin shared library on Windows via __declspec. + * Updated to Unreal Engine 4.18 + * Added C++ example, see https://github.com/EsotericSoftware/spine-runtimes/commit/15011e81b7061495dba45e28b4d3f4efb10d7f40 + * `SkeletonRendererComponent` generates collision meshes by default. + * Disabled generation of collision meshes by `SkeletonRendererComponent`. Both `ProceduralMeshComponent` and `RuntimeMeshComponent` have a bug that generates a new PhysiX file every frame per component. Users are advised to add a separate collision shape to the root scene component of an actor instead. + * Using UE4 `FMemory` allocator by default. This should fix issues on some consoles. + * **Breaking change** moved away from `RuntimeMeshComponent`, as its maintainance has seized, back to `ProceduralMeshComponent`. Existing projects should just work. However, if you run into issues, you may have to remove the old `SpineSkeletonRendererComponent` and add a new one to your existing actors. + * **Breaking change** due to the removal of `RuntimeMeshComponent` and reversal to `ProceduralMeshComponent`, two color tinting is currently not supported. `ProceduralMeshComponent` does not support enough vertex attributes for us to encode the second color in the vertex stream. You can remove the `RuntimeMeshComponent/` directory from your plugins directory and remove the component from any `build.cs` files that may reference it. + * **Breaking change**: Switched from [spine-c](spine-c) to [spine-cpp](spine-cpp) as the underlying Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. + * All C structs and enums `spXXX` have been replaced with their C++ equivalents `spine::XXX` in all public interfaces. + * All instantiations via `new` of C++ classes from spine-cpp should contain `(__FILE__, __LINE__)`. This allows the tracking of instantations and detection of memory leaks via the `spine::DebugExtension`. +* Updated to Unreal Engine 4.20 (samples require 4.17+), see the `spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.build.cs` file on how to compile in 4.20 with the latest UBT API changes. +* Updated to Unreal Engine 4.21 (samples require 4.21). +* **Breaking change**: `UBoneDriverComponent` and `UBoneFollowerComponent` are now `USceneComponent` instead of `UActorComponent`. They either update only themselves, or also the owning `UActor`, depending on whether the new flag `UseComponentTransform` is set. See https://github.com/EsotericSoftware/spine-runtimes/pull/1175 +* Added query methods for slots, bones, skins and animations to `SpineSkeletonComponent` and `UTrackEntry`. These allow you to query these objects by name in both C++ and blueprints. +* Added `Preview Animation` and `Preview Skin` properties to `SpineSkeletonAnimationComponent`. Enter an animation or skin name to live-preview it in the editor. Enter an empty string to reset the animation or skin. + +## C# ## +* **Breaking changes** + * The completion event will fire for looped 0 duration animations every frame. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#MixBlend = MixBlend.add` on each track. To specify the blend percentage, set `TrackEntry#Alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Unity +* **Runtime and Editor, and Assembly Definition** Files and folders have been reorganized into "Runtime" and "Editor". Each of these have an `.asmdef` file that defines these separately as their own assembly in Unity *(Note: Spine `.asmdef` files are currently deactivated to `.txt` extension, see below)*. For projects not using assembly definition, you may delete the `.asmdef` files. These assembly definitions will be ignored by older versions of Unity that don't support it. + * In this scheme, the entirety of the base spine-csharp runtime is inside the "Runtime" folder, to be compiled in the same assembly as spine-unity so they can continue to share internal members. +* **Spine `.asmdef` files are now deactivated (using `.txt` extension) by default** This prevents problems when updating Spine through unitypackages, overwriting the Timeline reference entry in `spine-unity.asmdef` (added automatically when enabling Unity 2019 Timeline support, see `Timeline Support for Unity 2019`), causing compile errors. In case you want to enable the `.asmdef` files, rename the files: + `Spine/Runtime/spine-unity.txt` to `Spine/Runtime/spine-unity.asmdef` and + `Spine/Editor/spine-unity-editor.txt` to `Spine/Editor/spine-unity-editor.asmdef`. +* **SkeletonAnimator is now SkeletonMecanim** The Spine-Unity Mecanim-driven component `SkeletonAnimator` has been renamed `SkeletonMecanim` to make it more autocomplete-friendly and more obvious at human-glance. The .meta files and guids should remain intact so existing projects and prefabs should not break. However, user code needs to be updated to use `SkeletonMecanim`. +* **SpineAtlasAsset** The existing `AtlasAsset` type has been renamed to `SpineAtlasAsset` to signify that it specifically uses a Spine/libGDX atlas as its source. Serialization should be intact but user code will need to be updated to refer to existing atlases as `SpineAtlasAsset`. + * **AtlasAssetBase** `SpineAtlasAsset` now has an abstract base class called `SpineAtlasAsset`. This is the base class to derive when using alternate atlas sources. Existing SkeletonDataAsset field "atlasAssets" now have the "AtlasAssetBase" type. Serialization should be intact, but user code will need to be updated to refer to the atlas assets accordingly. + * This change is in preparation for alternate atlas options such as Unity's SpriteAtlas. +* **Optional Straight Alpha for shaders** Spine-Unity's included Unity shaders now have a `_STRAIGHT_ALPHA_INPUT` shader_feature, toggled as a checkbox in the Material's inspector. This allows the Material to use a non-premultiplied alpha/straight alpha input texture. + * The following shaders now have the "Straight Alpha Texture" checkbox when used on a material: + * `Spine/Skeleton` + * `Spine/Skeleton Tint Black` + * `Spine/Skeleton Lit` + * `Spine/Skeleton Tint` + * `Spine/Skeleton Fill` + * `Spine/SkeletonGraphic (Premultiply Alpha)` was renamed to `Spine/SkeletonGraphic` + * `Spine/SkeletonGraphic Tint Black (Premultiply Alpha)` was renamed to `Spine/SkeletonGraphic Tint Black` + * `Spine/Skeleton PMA Multiply` + * `Spine/Skeleton PMA Screen` + * Dedicated straight alpha shaders were removed from the runtime. + * `Spine/Straight Alpha/Skeleton Fill` + * `Spine/Straight Alpha/Skeleton Tint` +* **Detection of Incorrect Texture Settings** Especially when atlas textures are exported with setting `Premultiply alpha` enabled, it is important to configure Unity's texture import settings correctly. By default, you will now receive warnings where texture settings are expected to cause incorrect rendering. + * The following rules apply: + * `sRGB (Color Texture)` shall be disabled when `Generate Mip Maps` is enabled, otherwise you will receive white border outlines. + * `Alpha Is Transparency` shall be disabled on `Premultiply alpha` textures, otherwise you will receive light ghosting artifacts in transparent areas. + * These warnings can be disabled in `Edit - Preferences - Spine`. +* **Sprite Mask Support for all Included Shaders** The `Skeleton Animation` and `Skeleton Mecanim` components now provide an additional `Mask Interaction` field in the Inspector, covering identical functionality as Unity's built in `Sprite Renderer` component: + * `Mask Interaction` modes: + * `None` - The sprite will not interact with the masking system. Default behavior. + * `Visible Inside Mask` - The sprite will be visible only in areas where a mask is present. + * `Visible Outside Mask` - The sprite will be visible only in areas where no mask is present. + * `Automatically Generated Materials` When switching `Mask Interaction` modes in the Inspector outside of Play mode, the required additional material assets are generated for the respective `Stencil Compare` parameters - with file suffixes `'_InsideMask'` and `'_OutsideMask'`, placed in the same folder as the original materials. By default all generated materials are kept as references by the `Skeleton Animation` component for switching at runtime. + These materials can be managed and optimized via the `SkeletonAnimation`'s `Advanced` section: + * Using the `Clear` button you can clear the reference to unneeded materials, + * Using the `Delete` button the respective assets are deleted as well as references cleared. Note that other `Skeleton Animation` GameObjects might still reference the materials, so use with caution! + * With the `Set` button you can again assign a link to the respective materials to prepare them for runtime use. If the materials were not present or have been deleted, they are generated again based on the default materials. + * When switching `Mask Interaction` mode at runtime, the previously prepared materials are switched active automatically. When the respective materials have not been prepared, material copies of the default materials are created on the fly. Note that these materials are not shared between similar `Skeleton Animation` GameObjects, so it is recommended to use the generated material assets where possible. + * **Every shader now exposes the `Stencil Compare` parameter** for further customization. This way you have maximum flexibility to use custom mechanisms to switch materials at runtime if you should ever need more than the three materials generated by `Skeleton Animation`'s `Mask Interaction` parameter. Reference `Stencil Compare` values are: + * `CompareFunction.Disabled` for `Mask Interaction - None` + * `CompareFunction.LessEqual` for `Mask Interaction - Visible Inside Mask` + * `CompareFunction.Greater` for `Mask Interaction - Visible Outside Mask` +* **RectMask2D Support for SkeletonGraphic** Both `SkeletonGraphic` shaders '`Spine/SkeletonGraphic`' and '`Spine/SkeletonGraphic Tint Black`' now respect masking areas defined via Unity's `RectMask2D` component. +* **Timeline Support for Unity 2019** using the existing Timeline components. By default, all Spine Timeline components are deactivated in Unity 2019 and **can be activated via the Spine Preferences menu**. This step became necessary because in Unity 2019, Timeline has been moved to a separate Package and is no longer included in the Unity core. Please visit `Edit - Preferences - Spine` and at `Timeline Package Support` hit `Enable` to automatically perform all necessary steps to activate the Timeline components. +This will automatically: + 1. download the Unity Timeline package + 2. activate the Spine Timeline components by setting the compile definition `SPINE_TIMELINE_PACKAGE_DOWNLOADED` for all platforms + 3. modify the `spine-unity.asmdef` file by adding the reference to the Unity Timeline library. +* Added `Create 2D Hinge Chain` functionality at `SkeletonUtilityBone` inspector, previously only `Create 3D Hinge Chain` was available. + +### XNA/MonoGame +* Added support for any `Effect` to be used by `SkeletonRenderer` +* Added support for `IVertexEffect` to modify vertices of skeletons on the CPU. `IVertexEffect` instances can be set on the `SkeletonRenderer`. See example project. +* Added `SkeletonDebugRenderer` +* Made `MeshBatcher` of SkeletonRenderer accessible via a getter. Allows user to batch their own geometry together with skeleton meshes for maximum batching instead of using XNA SpriteBatcher. + +## Java +* **Breaking changes** + * Skeleton attachments: Moved update of attached skeleton out of libGDX `SkeletonRenderer`, added overloaded method `Skeleton#updateWorldTransform(Bone)`, used for `SkeletonAttachment`. You now MUST call this new method with the bone of the parent skeleton to which the child skeleton is attached. See `SkeletonAttachmentTest` for and example. + * The completion event will fire for looped 0 duration animations every frame. + * `MixPose` is now called `MixBlend`. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added `EventData#audioPath` field. This field contains the file name of the audio file used for the event. + * Added convenience method to add all attachments from one skin to another, see https://github.com/EsotericSoftware/spine-runtimes/commit/a0b7bb6c445efdfac12b0cdee2057afa3eff3ead + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### libGDX +* Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect` and `VertexEffectTest`. +* Added improved tint-black shader. +* Improved performance by avoiding batch flush when not switching between normal and additive rendering with PMA +* Improvements to skeleton viewer. +* `TwoColorPolygonBatch` implements the `Batch` interface, allowing to the be used with other libGDX classes that require a batcher for drawing, potentially improving performance. See https://github.com/EsotericSoftware/spine-runtimes/commit/a46b3d1d0c135d51f9bef9ca17a5f8e5dda69927 +* Added `SkeletonDrawable` to render skeletons in scene2d UI https://github.com/EsotericSoftware/spine-runtimes/commit/b93686c185e2c9d5466969a8e07eee573ebe4b97 + +## Lua +* **Breaking changes** + * The completion event will fire for looped 0 duration animations every frame. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added `JitterEffect` and `SwirlEffect` and support for vertex effects in Corona and Love + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry:setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry.alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Love2D +* Added support for vertex effects. Set an implementation like "JitterEffect" on `Skeleton.vertexEffect`. See `main.lua` for an example. + +### Corona +* Added support for vertex effects. Set an implementation like "JitterEffect" on `SkeletonRenderer.vertexEffect`. See `main.lua` for an example + +## Typescript/Javascript +* **Breaking changes** + * The completion event will fire for looped 0 duration animations every frame. + * Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + * Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +* **Additions** + * Added `AssetManager.loadTextureAtlas`. Instead of loading the `.atlas` and corresponding image files manually, you can simply specify the location of the `.atlas` file and AssetManager will load the atlas and all its images automatically. `AssetManager.get("atlasname.atlas")` will then return an instance of `spine.TextureAtlas`. + * Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. See https://github.com/EsotericSoftware/spine-runtimes/blob/f045d221836fa56191ccda73dd42ae884d4731b8/spine-ts/webgl/tests/test-additive-animation-blending.html for an example. + * Added work-around for iOS WebKit JIT bug, see https://github.com/EsotericSoftware/spine-runtimes/commit/c28bbebf804980f55cdd773fed9ff145e0e7e76c + * Support for stretchy IK + * Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + * `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + * Added `AssetManager#setRawDataURI(path, data)`. Allows to set raw data URIs for a specific path, which in turn enables embedding assets into JavaScript/HTML. + * `PolygonBatcher` will now disable `CULL_FACE` and restore the state as it was before rendering. + +### WebGL backend +* Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`, and the example which allows to set effects. +* Added `slotRangeStart` and `slotRangeEnd` parameters to `SkeletonRenderer#draw` and `SceneRenderer#drawSkeleton`. This allows you to render only a range of slots in the draw order. See `spine-ts/webgl/tests/test-slot-range.html` for an example. +* Added improved tint-black shader. +* Added `SceneRenderer#drawTextureUV()`, allowing to draw a texture with manually specified texture coordinates. +* Exposed all renderers in `SceneRenderer`. + +### Canvas backend +* Added support for shearing and non-uniform scaling inherited from parent bones. +* Added support for alpha tinting. + +### Three.js backend +* Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`. +* Added support for multi-page atlases + +### Widget backend + * Added fields `atlasContent`, `atlasPagesContent`, and `jsonContent` to `WidgetConfiguration` allowing you to directly pass the contents of the `.atlas`, atlas page `.png` files, and the `.json` file without having to do a request. See `README.md` and the example for details. + * `SpineWidget.setAnimation()` now takes an additional optional parameter for callbacks when animations are completed/interrupted/etc. + +# 3.6 + +## AS3 +* **Breaking changes** + * Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Made `Bone` fields `_a`, `_b`, `_c`, `_d`, `_worldX` and `_worldY` public, removed underscore prefix. + * Removed `VertexAttachment.computeWorldVertices` overload, changed `VertexAttachment.computeWorldVertices2` to `VertexAttachment.computeWorldVertices`, added `stride` parameter. + * Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + * Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + * Replaced `r`, `g`, `b`, `a` fields with instances of new `Color` class in `RegionAttachment`, `MeshAttachment`, `Skeleton`, `SkeletonData`, `Slot` and `SlotData`. + * The completion event will fire for looped 0 duration animations every frame. + +* **Additions** + * Added `Skeleton.getBounds` from reference implementation. + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `VertexEffect` and implementations `JitterEffect` and `SwirlEffect`. Allows you to modify vertices before they are submitted for drawing. See Starling changes. + +### Starling + * Fixed renderer to work with 3.6 changes. + * Added support for two color tinting. + * Added support for clipping. + * Added support for rotated regions in texture atlas loaded via StarlingAtlasAttachmentLoader. + * Added support for vertex effects. See `RaptorExample.as` + * Added 'getTexture()' method to 'StarlingTextureAtlasAttachmentLoader' + * Breaking change: if a skeleton requires two color tinting, you have to enable it via `SkeletonSprite.twoColorTint = true`. In this case the skeleton will use the `TwoColorMeshStyle`, which internally uses a different vertex layout and shader. This means that skeletons with two color tinting enabled will break batching and hence increase the number of draw calls in your app. + +## C +* **Breaking changes** + * `spVertexAttachment_computeWorldVertices` and `spRegionAttachment_computeWorldVerticeS` now take new parameters to make it possible to directly output the calculated vertex positions to a vertex buffer. Removes the need for additional copies in the backends' respective renderers. + * Removed `spBoundingBoxAttachment_computeWorldVertices`, superseded by `spVertexAttachment_computeWorldVertices`. + * Removed `spPathAttachment_computeWorldVertices` and `spPathAttachment_computeWorldVertices1`, superseded by `spVertexAttachment_computeWorldVertices`. + * Removed `sp_MeshAttachment_computeWorldVertices`, superseded by `spVertexAttachment_computeWorldVertices`. + * Removed `spBone_worldToLocalRotationX` and `spBone_worldToLocalRotationY`. Replaced by `spBone_worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Replaced `r`, `g`, `b`, `a` fields with instances of new `spColor` struct in `spRegionAttachment`, `spMeshAttachment`, `spSkeleton`, `spSkeletonData`, `spSlot` and `spSlotData`. + * Removed `spVertexIndex`from public API. + * Listeners on `spAnimationState` or `spTrackEntry` will now be also called in case a track entry is disposed as part of dispoing the `spAnimationState`. + * The completion event will fire for looped 0 duration animations every frame. +* **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `spTransformConstraintData`. + * Added `spPointAttachment`, additional method `spAtlasAttachmentLoadeR_newPointAttachment`. + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `spBone_localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `spTwoColorTimeline` and additional fields on `spSlot` and `spSlotData`. + * Added `userData` field to `spTrackEntry`, so users can expose data in `spAnimationState` callbacks. + * Modified kvec.h used by SkeletonBinary.c to use Spine's MALLOC/FREE macros. That way there's only one place to inject custom allocators ([extension.h](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-c/spine-c/include/spine/extension.h)) [commit](https://github.com/EsotericSoftware/spine-runtimes/commit/c2cfbc6cb8709daa082726222d558188d75a004f) + * Added macros to define typed dynamic arrays, see `Array.h/.c` + * Added `spClippingAttachment` and respective enum. + * Added `spSkeletonClipper` and `spTriangulator`, used to implement software clipping of attachments. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `spVertexEffect` and corresponding implementations `spJitterVertexEffect` and `spSwirlVertexEffect`. Create/dispose through the corresponding `spXXXVertexEffect_create()/dispose()` functions. Set on framework/engine specific renderer. See changes for spine-c based frameworks/engines below. + * Functions in `extension.h` are not prefixed with `_sp` instead of just `_` to avoid interference with other libraries. + * Introduced `SP_API` macro. Every spine-c function is prefixed with this macro. By default, it is an empty string. Can be used to markup spine-c functions with e.g. ``__declspec` when compiling to a dll or linking to that dll. + +### Cocos2d-X + * Fixed renderer to work with 3.6 changes + * Optimized rendering by removing all per-frame allocation in `SkeletonRenderer`, resulting in 15% performance increase for large numbers of skeletons being rendered per frame. + * Added support for two color tinting. Tinting is enabled/disabled per `SkeletonRenderer`/`SkeletonAnimation` instance. Use `SkeletonRenderer::setTwoColorTint()`. Note that two color tinting requires the use of a non-standard shader and vertex format. This means that skeletons rendered with two color tinting will break batching. However, skeletons with two color tinting enabled and rendered after each other will be batched. + * Updated example to use Cocos2d-x 3.14.1. + * Added mesh debug rendering. Enable/Disable via `SkeletonRenderer::setDebugMeshesEnabled()`. + * Added support for clipping. + * SkeletonRenderer now combines the displayed color of the Node (cascaded from all parents) with the skeleton color for tinting. + * Added support for vertex effects. See `RaptorExample.cpp`. + * Added ETC1 alpha support, thanks @halx99! Does not work when two color tint is enabled. + * Added `spAtlasPage_setCustomTextureLoader()` which let's you do texture loading manually. Thanks @jareguo. + * Added `SkeletonRenderer:setSlotsRange()` and `SkeletonRenderer::createWithSkeleton()`. This allows you to split rendering of a skeleton up into multiple parts, and render other nodes in between. See `SkeletonRendererSeparatorExample.cpp` for an example. + +### Cocos2d-Objc + * Fixed renderer to work with 3.6 changes + * Added support for two color tinting. Tinting is enabled/disabled per `SkeletonRenderer/SkeletonAnimation.twoColorTint = true`. Note that two color tinted skeletons do not batch with other nodes. + * Added support for clipping. + +### SFML + * Fixed renderer to work with 3.6 changes. Sadly, two color tinting does not work, as the vertex format in SFML is fixed. + * Added support for clipping. + * Added support for vertex effects. See raptor example. + * Added premultiplied alpha support to `SkeletonDrawable`. + +### Unreal Engine 4 + * Fixed renderer to work with 3.6 changes + * Added new UPROPERTY to SpineSkeletonRendererComponent called `Color`. This allows to set the tint color of the skeleton in the editor, C++ and Blueprints. Under the hood, the `spSkeleton->color` will be set on every tick of the renderer component. + * Added support for clipping. + * Switched from built-in ProceduralMeshComponent to RuntimeMeshComponent by Koderz (https://github.com/Koderz/UE4RuntimeMeshComponent, MIT). Needed for more flexibility regarding vertex format, should not have an impact on existing code/assets. You need to copy the RuntimeMeshComponentPlugin from our repository in `spine-ue4\Plugins\` to your project as well! + * Added support for two color tinting. All base materials, e.g. SpineUnlitNormalMaterial, now do proper two color tinting. No material parameters have changed. + * Updated to Unreal Engine 4.16.1. Note that 4.16 has a regression which will make it impossible to compile plain .c files! + * spine-c is now exposed from the plugin shared library on Windows via __declspec. + +## C# +* **Breaking changes** + * `MeshAttachment.parentMesh` is now a private field to enforce using the `.ParentMesh` setter property in external code. The `MeshAttachment.ParentMesh` property is an appropriate replacement wherever `.parentMesh` was used. + * `Skeleton.GetBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + * Removed `Bone.WorldToLocalRotationX` and `Bone.WorldToLocalRotationY`. Replaced by `Bone.WorldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Added `stride` parameter to `VertexAttachment.ComputeWorldVertices`. + * Removed `RegionAttachment.Vertices` field. The vertices array is provided to `RegionAttachment.ComputeWorldVertices` by the API user now. + * Removed `RegionAttachment.UpdateWorldVertices`, added `RegionAttachment.ComputeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + * The completion event will fire for looped 0 duration animations every frame. + + * **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `NewPointAttachment` in `AttachmentLoader` interface. + * Added `ClippingAttachment`, additional method `NewClippingAttachment` in `AttachmentLoader` interface. + * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + * `AnimationState.Apply` returns a bool indicating if any timeline was applied or not. + * `Animation.Apply` and `Timeline.Apply`` now take enums `MixPose` and `MixDirection` instead of bools. + +### Unity + * Refactored renderer to work with new 3.6 features. + * **Two color tinting** is currently supported via extra UV2 and UV3 mesh vertex streams. To use Two color tinting, you need to: + * switch on "Tint Black" under "Advanced...", + * use the new `Spine/Skeleton Tint Black` shader, or your own shader that treats the UV2 and UV3 streams similarly. + * Additionally, for SkeletonGraphic, you can use `Spine/SkeletonGraphic Tint Black` (or the bundled SkeletonGraphicTintBlack material) or your own shader that uses UV2 and UV3 streams similarly. **Additional Shader Channels** TexCoord1 and TexCoord2 will need to be enabled from the Canvas component's inspector. These correspond to UV2 and UV3. + * **Clipping** is now supported. Caution: The SkeletonAnimation switches to slightly slower mesh generation code when clipping so limit your use of `ClippingAttachment`s when using on large numbers of skeletons. + * **SkeletonRenderer.initialFlip** Spine components such as SkeletonRenderer, SkeletonAnimation, SkeletonAnimator now has `initialFlipX` and `initialFlipY` fields which are also visible in the inspector under "Advanced...". It will allow you to set and preview a starting flip value for your skeleton component. This is applied immediately when the internal skeleton object is instantiated. + * **[SpineAttribute] Improvements** + * **Icons have been added to SpineAttributeDrawers**. This should make your default inspectors easier to understand at a glance. + * **Added Constraint Attributes** You can now use `[SpineIkConstraint]` `[SpineTransformConstraint]` `[SpinePathConstraint]` + * **SpineAttribute dataField** parameter can also now detect sibling fields within arrays and serializable structs/classes. + * **[SpineAttribute(includeNone:false)]** SpineAttributes now have an `includeNone` optional parameter to specify if you want to include or exclude a none ("") value option in the dropdown menu. Default is `includeNone:true`. + * **[SpineAttachment(skinField:"mySkin")]** The SpineAttachment attribute now has a skinField optional parameter to limit the dropdown items to attachments in a specific skin instead of the just default skin or all the skins in SkeletonData. + * **SkeletonDebugWindow**. Debugging tools have been moved from the SkeletonAnimation and SkeletonUtility component inspectors into its own utility window. You can access "Skeleton Debug" under the `Advanced...` foldout in the SkeletonAnimation inspector, or in SkeletonAnimation's right-click/context menu. + * **Skeleton Baking Window** The old Skeleton Baking feature is also now accessible through the SkeletonDataAsset's right-click/context menu. + * **AttachmentTools source material**. `AttachmentTools` methods can now accept a `sourceMaterial` argument to copy material properties from. + * **AttachmentTools Skin Extensions**. Using AttachmentTools, you can now add entries by slot name by also providing a skeleton argument. Also `Append(Skin)`, `RemoveAttachment` and `Clear` have been added. + * **BoneFollower and SkeletonUtilityBone Add RigidBody Button**. The BoneFollower and SkeletonUtilityBone component inspectors will now offer to add a `Rigidbody` or `Rigidbody2D` if it detects a collider of the appropriate type. Having a rigidbody on a moving transform with a collider fits better with the Unity physics systems and prevents excess calculations. It will not detect colliders on child objects so you have to add Rigidbody components manually accordingly. + * **SkeletonRenderer.OnPostProcessVertices** is a new callback that gives you a reference to the MeshGenerator after it has generated a mesh from the current skeleton pose. You can access `meshGenerator.VertexBuffer` or `meshGenerator.ColorBuffer` to modify these before they get pushed into the UnityEngine.Mesh for rendering. This can be useful for non-shader vertex effects. + * **Examples** + * **Examples now use properties**. The code in the example scripts have been switched over to using properties instead of fields to encourage their use for consistency. This is in anticipation of both users who want to move the Spine folders to the Unity Plugins folder (compiled as a different assembly), and of Unity 2017's ability to manually define different assemblies for shorter compilation times. + * **Mix And Match**. The mix-and-match example scene, code and data have been updated to reflect the current recommended setup for animation-compatible custom equip systems The underlying API has changed since 3.5 and the new API calls in MixAndMatch.cs is recommended. Documentation is in progress. + * **Sample Components**. `AtasRegionAttacher` and `SpriteAttacher` are now part of `Sample Components`, to reflect that they are meant to be used as sample code rather than production. A few other sample components have also been added. New imports of the unitypackage Examples folder will see a "Legacy" folder comprised of old sample components that no longer contain the most up-to-date and recommended workflows, but are kept in case old setups used them for production. + * **Spine folder**. In the unitypackage, the "spine-csharp" and "spine-unity" folders are now inside a "Spine" folder. This change will only affect fresh imports. Importing the unitypackage to update Spine-Unity in your existing project will update the appropriate files however you chose to arrange them, as long as the meta files are intact. + * **Breaking changes** + * The Sprite shaders module was updated to the latest version from the [source](https://github.com/traggett/UnitySpriteShaders/commits/master). Some changes were made to the underlying keyword structure. You may need to review the settings of your lit materials. Particularly, your Fixed Normals settings. + * The `Spine/Skeleton Lit` shader was switched over to non-fixed-function code. It now no longer requires mesh normals and has fixed normals at the shader level. + * The old MeshGenerator classes, interfaces and code in `Spine.Unity.MeshGeneration` are now deprecated. All mesh-generating components now share the class `Spine.Unity.MeshGenerator` defined in `SpineMesh.cs`. MeshGenerator is a serializable class. + * The `SkeletonRenderer.renderMeshes` optimization is currently non-functional. + * Old triangle-winding code has been removed from `SkeletonRenderer`. Please use shaders that have backface culling off. + * Render settings in `SkeletonGraphic` can now be accessed under `SkeletonGraphic.MeshGenerator.settings`. This is visible in the SkeletonGraphic inspector as `Advanced...` + * We will continue to bundle the unitypackage with the empty .cs files of deprecated classes until Spine 3.7 to ensure the upgrade process does not break. + * The [SpineAttachment(slotField:)] optional parameter found property value now acts as a Find(slotName) argument rather than Contains(slotName). + * `SkeletonAnimator` now uses a `SkeletonAnimator.MecanimTranslator` class to translate an Animator's Mecanim State Machine into skeleton poses. This makes code reuse possible for a Mecanim version of SkeletonGraphic. + * `SkeletonAnimator` `autoreset` and the `mixModes` array are now a part of SkeletonAnimator's MecanimTranslator `.Translator`. `autoReset` is set to `true` by default. Old prefabs and scene objects with Skeleton Animator may no longer have correct values set. + * Warnings and conditionals checking for specific Unity 5.2-and-below incompatibility have been removed. + +## XNA/MonoGame + * Added support for clipping + * Removed `RegionBatcher` and `SkeletonRegionRenderer`, renamed `SkeletonMeshRenderer` to `SkeletonRenderer` + * Added support for two color tint. For it to work, you need to add the `SpineEffect.fx` file to your content project, then load it via `var effect = Content.Load("SpineEffect");`, and set it on the `SkeletonRenderer`. See the example project for code. + * Added support for any `Effect` to be used by `SkeletonRenderer` + * Added support for `IVertexEffect` to modify vertices of skeletons on the CPU. `IVertexEffect` instances can be set on the `SkeletonRenderer`. See example project. + * Added `SkeletonDebugRenderer` + * Made `MeshBatcher` of SkeletonRenderer accessible via a getter. Allows user to batch their own geometry together with skeleton meshes for maximum batching instead of using XNA SpriteBatcher. + +## Java +* **Breaking changes** + * `Skeleton.getBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + * Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Added `stride` parameter to `VertexAttachment.computeWorldVertices`. + * Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + * Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + * Skeleton attachments: Moved update of attached skeleton out of libGDX `SkeletonRenderer`, added overloaded method `Skeleton#updateWorldTransform(Bone), used for `SkeletonAttachment`. You now MUST call this new method + with the bone of the parent skeleton to which the child skeleton is attached. See `SkeletonAttachmentTest` for and example. + * The completion event will fire for looped 0 duration animations every frame. + +* **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + +### libGDX + * Fixed renderer to work with 3.6 changes + * Added support for two color tinting. Use the new `TwoColorPolygonBatch` together with `SkeletonRenderer` + * Added support for clipping. See `SkeletonClipper`. Used automatically by `SkeletonRenderer`. Does not work when using a `SpriteBatch` with `SkeletonRenderer`. Use `PolygonSpriteBatch` or `TwoColorPolygonBatch` instead. + * Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect` and `VertexEffectTest`. + +## Lua +* **Breaking changes** + * Removed `Bone:worldToLocalRotationX` and `Bone:worldToLocalRotationY`. Replaced by `Bone:worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * `VertexAttachment:computeWorldVertices` now takes offsets and stride to allow compositing vertices directly in a vertex buffer to be send to the GPU. The compositing is now performed in the backends' respective renderers. This also affects the subclasses `MeshAttachment`, `BoundingBoxAttachment` and `PathAttachment`. + * Removed `RegionAttachment:updateWorldVertices`, added `RegionAttachment:computeWorldVertices`, which takes offsets and stride to allow compositing vertices directly in a vertex buffer to be send to the GPU. The compositing is now performed in the backends' respective renderers. + * Removed `MeshAttachment.worldVertices` field. Computation is now performed in each backends' respective renderer. The `uv` coordinates are now stored in `MeshAttachment.uvs`. + * Removed `RegionAttachment.vertices` field. Computation is now performed in each backends respective renderer. The `uv` coordinates for each vertex are now stored in the `RegionAttachment.uvs` field. + * The completion event will fire for looped 0 duration animations every frame. + * **Additions** + * Added `Bone:localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `JitterEffect` and `SwirlEffect` and support for vertex effects in Corona and Love + +### Love2D + * Fixed renderer to work with 3.6 changes + * Added support for two color tinting. Enable it via `SkeletonRenderer.new(true)`. + * Added clipping support. + * Added support for vertex effects. Set an implementation like "JitterEffect" on `Skeleton.vertexEffect`. See `main.lua` for an example. + +### Corona + * Fixed renderer to work with 3.6 changes. Sadly, two color tinting is not supported, as Corona doesn't let us change the vertex format needed and its doesn't allow to modify shaders in the way needed for two color tinting + * Added clipping support. + * Added support for vertex effects. Set an implementation like "JitterEffect" on `SkeletonRenderer.vertexEffect`. See `main.lua` for an example + +## Typescript/Javascript +* **Breaking changes** + * `Skeleton.getBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + * Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + * Removed `VertexAttachment.computeWorldVertices` overload, changed `VertexAttachment.computeWorldVerticesWith` to `VertexAttachment.computeWorldVertices`, added `stride` parameter. + * Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + * Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + * The completion event will fire for looped 0 duration animations every frame. + * Removed the Spine Widget in favor of [Spine Web Player](https://esotericsoftware.com/spine-player). + +* **Additions** + * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + * `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans + * Added `AssetManager.loadTextureAtlas`. Instead of loading the `.atlas` and corresponding image files manually, you can simply specify the location of the `.atlas` file and AssetManager will load the atlas and all its images automatically. `AssetManager.get("atlasname.atlas")` will then return an instance of `spine.TextureAtlas`. + * Added the [Spine Web Player](https://esotericsoftware.com/spine-player) + + +### WebGL backend + * Fixed WebGL context loss + * Added `Restorable` interface, implemented by any WebGL resource that needs restoration after a context loss. All WebGL resource classes (`Shader`, `Mesh`, `GLTexture`) implement this interface. + * Added `ManagedWebGLRenderingContext`. Handles setup of a `WebGLRenderingContext` given a canvas element and restoration of WebGL resources (`Shader`, `Mesh`, `GLTexture`) on WebGL context loss. WebGL resources register themselves with the `ManagedWebGLRenderingContext`. If the context is informed of a context loss and restoration, the registered WebGL resources' `restore()` method is called. The `restore()` method implementation on each resource type will recreate the GPU side objects. + * All classes that previously took a `WebGLRenderingContext` in the constructor now also allow a `ManagedWebGLRenderingContext`. This ensures existing applications do not break. + * To use automatic context restauration: + 1. Create or fetch a canvas element from the DOM + 2. Instantiate a `ManagedWebGLRenderingContext`, passing the canvas to the constructor. This will setup a `WebGLRenderingContext` internally and manage context loss/restoration. + 3. Pass the `ManagedWebGLRenderingContext` to the constructors of classes that you previously passed a `WebGLRenderingContext` to (`AssetManager`, `GLTexture`, `Mesh`, `Shader`, `PolygonBatcher`, `SceneRenderer`, `ShapeRenderer`, `SkeletonRenderer`, `SkeletonDebugRenderer`). + * Fixed renderer to work with 3.6 changes. + * Added support for two color tinting. + * Improved performance by using `DYNAMIC_DRAW` for vertex buffer objects and fixing bug that copied to much data to the GPU each frame in `PolygonBatcher`/`Mesh`. + * Added two color tinting support, enabled by default. You can disable it via the constructors of `SceneRenderer`, `SkeletonRenderer`and `PolygonBatcher`. Note that you will need to use a shader created via `Shader.newTwoColoredTexturedShader` shader with `SkeletonRenderer` and `PolygonBatcher` if two color tinting is enabled. + * Added clipping support + * Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`, and the example which allows to set effects. + * Added `slotRangeStart` and `slotRangeEnd` parameters to `SkeletonRenderer#draw` and `SceneRenderer#drawSkeleton`. This allows you to render only a range of slots in the draw order. See `spine-ts/webgl/tests/test-slot-range.html` for an example. + +### Canvas backend + * Fixed renderer to work for 3.6 changes. Sadly, we can't support two color tinting via the Canvas API. + * Added support for shearing and non-uniform scaling inherited from parent bones. + * Added support for alpha tinting. + +### Three.js backend + * Fixed renderer to work with 3.6 changes. Two color tinting is not supported. + * Added clipping support + * Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`. + * Added support for multi-page atlases + +### Widget backend + * Fixed WebGL context loss (see WebGL backend changes). Enabled automatically. + * Fixed renderer to work for 3.6 changes. Supports two color tinting & clipping (see WebGL backend changes for details). + * Added fields `atlasContent`, `atlasPagesContent`, and `jsonContent` to `WidgetConfiguration` allowing you to directly pass the contents of the `.atlas`, atlas page `.png` files, and the `.json` file without having to do a request. See `README.md` and the example for details. + * `SpineWidget.setAnimation()` now takes an additional optional parameter for callbacks when animations are completed/interrupted/etc. diff --git a/DateToSpine/third_party/spine-runtimes/4.1/CMakeLists.txt b/DateToSpine/third_party/spine-runtimes/4.1/CMakeLists.txt new file mode 100644 index 0000000..a1da43e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.17) +project(spine) + +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR} CACHE PATH "Install location" FORCE) +endif() +set(CMAKE_VERBOSE_MAKEFILE ON) +option(SPINE_SFML "Build spine SFML API" OFF) +option(SPINE_SANITIZE "Build with sanitization" OFF) +option(BUILD_TESTING "Build with testing" ON) + +if(MSVC) + message("MSCV detected") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + set (CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}") +else() + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wunused-value -Wno-variadic-macros -Wextra -pedantic -Wshadow -std=c99") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunused-value -Wno-variadic-macros -Wextra -Wnon-virtual-dtor -pedantic -Wshadow -std=c++11 -fno-exceptions -fno-rtti") + + if (${SPINE_SANITIZE}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize=undefined") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize=undefined") + endif() +endif() + +if((${SPINE_SFML}) OR (${CMAKE_CURRENT_BINARY_DIR} MATCHES "spine-sfml")) + if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(CMAKE_OSX_ARCHITECTURES x86_64) + set(ONLY_ACTIVE_ARCH NO) + endif() + add_subdirectory(spine-c) + add_subdirectory(spine-cpp) + add_subdirectory(spine-sfml/c) + add_subdirectory(spine-sfml/cpp) +elseif((${SPINE_SDL}) OR (${CMAKE_CURRENT_BINARY_DIR} MATCHES "spine-sdl")) + if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(CMAKE_OSX_ARCHITECTURES x86_64;arm64) + set(ONLY_ACTIVE_ARCH NO) + endif() + add_subdirectory(spine-c) + add_subdirectory(spine-cpp) + add_subdirectory(spine-sdl) +else() + add_subdirectory(spine-c) + add_subdirectory(spine-cpp) + if (${BUILD_TESTING}) + add_subdirectory(spine-cpp/spine-cpp-unit-tests) + endif() +endif() + +# Create config file that include the exported targets +configure_file(SpineConfig.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/SpineConfig.cmake" + @ONLY) \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.1/LICENSE b/DateToSpine/third_party/spine-runtimes/4.1/LICENSE new file mode 100644 index 0000000..1d809bd --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/LICENSE @@ -0,0 +1,26 @@ +Spine Runtimes License Agreement +Last updated July 28, 2023. Replaces all prior versions. + +Copyright (c) 2013-2023, Esoteric Software LLC + +Integration of the Spine Runtimes into software or otherwise creating +derivative works of the Spine Runtimes is permitted under the terms and +conditions of Section 2 of the Spine Editor License Agreement: +http://esotericsoftware.com/spine-editor-license + +Otherwise, it is permitted to integrate the Spine Runtimes into software or +otherwise create derivative works of the Spine Runtimes (collectively, +"Products"), provided that each user of the Products must obtain their own +Spine Editor license and redistribution of the Products in any form must +include this license and copyright notice. + +THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, +BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE +SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.1/README.md b/DateToSpine/third_party/spine-runtimes/4.1/README.md new file mode 100644 index 0000000..3245185 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/README.md @@ -0,0 +1,33 @@ +# Spine Runtimes + +This GitHub project hosts the Spine Runtimes which are needed to use [Spine](http://esotericsoftware.com/) 2D skeletal animation data with various game toolkits. + +## Licensing + +You are welcome to evaluate the Spine Runtimes and the examples we provide in this repository free of charge. + +You can integrate the Spine Runtimes into your software free of charge, but users of your software must have their own [Spine license](https://esotericsoftware.com/spine-purchase). Please make your users aware of this requirement! This option is often chosen by those making development tools, such as an SDK, game toolkit, or software library. + +In order to distribute your software containing the Spine Runtimes to others that don't have a Spine license, you need a [Spine license](https://esotericsoftware.com/spine-purchase) at the time of integration. Then you can distribute your software containing the Spine Runtimes however you like, provided others don't modify it or use it to create new software. If others want to do that, they'll need their own Spine license. + +For the official legal terms governing the Spine Runtimes, please read the [Spine Runtimes License Agreement](http://esotericsoftware.com/spine-runtimes-license) and Section 2 of the [Spine Editor License Agreement](http://esotericsoftware.com/spine-editor-license#s2). + +## Documentation + +See the [Spine Runtimes Guide](http://esotericsoftware.com/spine-runtimes-guide) for detailed information about using the Spine Runtimes. The Spine [documentation page](http://esotericsoftware.com/spine-documentation#runtimesTitle) provides further information about tools and data formats. For runtime specific documentation, refer to the `README.md` file in each runtime directory. + +## Bugs, enhancements, and tasks + +Review our backlog of bugs, enhancements, and tasks in the [spine-runtimes](https://github.com/EsotericSoftware/spine-runtimes/issues) and [spine-editor](https://github.com/EsotericSoftware/spine-editor/issues) issue trackers. Our [roadmap](http://esotericsoftware.com/spine-roadmap) provides a more convenient view of the same issue tracker information. + +## Versioning + +The default branch on GitHub is stable and works with data exported from the latest, non-beta version of the Spine editor. New development is done in an `X.X-beta` branch, which may be a work in progress. Important changes to the runtimes can be reviewed in the [CHANGELOG.md file](CHANGELOG.md). Occasionally the Spine Runtimes are [tagged](https://github.com/EsotericSoftware/spine-runtimes/releases) with the specific Spine editor version they work with. + +It is highly suggested to [freeze](http://esotericsoftware.com/spine-settings#Version) the Spine editor version to match the Spine Runtimes source being used and to update them in lock step. See the [Spine Runtimes Guide](http://esotericsoftware.com/spine-runtime-architecture#Versioning) for more information. + +## Contributing + +In order to merge your contributions, we need a signed [contributor license agreement (CLA)](http://esotericsoftware.com/licenses/cla.txt) from you. You can send a copy of the CLA to contact@esotericsoftware.com. + +When possible, it is best to base your contributions on the current beta branch (`X.X-beta`). Please be sure to follow the style and formatting you find in the respective runtime code to which you are contributing. diff --git a/DateToSpine/third_party/spine-runtimes/4.1/SpineConfig.cmake.in b/DateToSpine/third_party/spine-runtimes/4.1/SpineConfig.cmake.in new file mode 100644 index 0000000..601b05b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/SpineConfig.cmake.in @@ -0,0 +1 @@ +include("@CMAKE_CURRENT_BINARY_DIR@/spine-cpp/spine-cppTargets.cmake") \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/readme.txt b/DateToSpine/third_party/spine-runtimes/4.1/examples/readme.txt new file mode 100644 index 0000000..21ee01a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/examples/readme.txt @@ -0,0 +1,27 @@ +These example projects show off many of Spine's features. Below are a number +of other example resources that may prove useful. + +We have detailed documentation for how many of the example projects are built: +http://esotericsoftware.com/spine-examples + +See our online demos, which render Spine animations right in your browser: +http://esotericsoftware.com/spine-demos + +Learn how to use Spine with the Spine User Guide: +http://esotericsoftware.com/spine-user-guide +And the accompanying Spine User Guide videos: +https://www.youtube.com/playlist?list=PLwGl7Ikd_6GRFo7d0uRu_fN2RIlvkxW7b +And our other videos: +https://www.youtube.com/user/EsotericSoftware/videos + +Learn how to integrate Spine into your software: +http://esotericsoftware.com/spine-runtime-documentation + +Super Spineboy is a full example game using Spine and libgdx: +https://github.com/EsotericSoftware/spine-superspineboy + +Many companies around the world are doing great things with Spine: +http://esotericsoftware.com/spine-showcase + +Tag your tweets using #madewithspine to show up on our Twitter page: +http://esotericsoftware.com/madewithspine diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-ess.json b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-ess.json new file mode 100644 index 0000000..81688eb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-ess.json @@ -0,0 +1,3672 @@ +{ +"skeleton": { + "hash": "SmUDxzck41o", + "spine": "4.1.17", + "x": -221.27, + "y": -8.57, + "width": 470.72, + "height": 731.57, + "images": "./images/", + "audio": "" +}, +"bones": [ + { "name": "root" }, + { "name": "hip", "parent": "root", "y": 247.47 }, + { + "name": "torso", + "parent": "hip", + "length": 127.56, + "rotation": 103.82, + "x": -1.62, + "y": 4.9, + "color": "e0da19ff" + }, + { + "name": "front-upper-arm", + "parent": "torso", + "length": 69.45, + "rotation": 168.38, + "x": 103.76, + "y": 19.33, + "color": "00ff04ff" + }, + { + "name": "front-bracer", + "parent": "front-upper-arm", + "length": 40.57, + "rotation": 18.3, + "x": 68.8, + "y": -0.68, + "color": "00ff04ff" + }, + { + "name": "front-fist", + "parent": "front-bracer", + "length": 65.39, + "rotation": 12.43, + "x": 40.57, + "y": 0.2, + "color": "00ff04ff" + }, + { + "name": "front-thigh", + "parent": "hip", + "length": 74.81, + "rotation": -95.51, + "x": -17.46, + "y": -11.64, + "color": "00ff04ff" + }, + { + "name": "front-shin", + "parent": "front-thigh", + "length": 128.77, + "rotation": -2.21, + "x": 78.69, + "y": 1.6, + "color": "00ff04ff" + }, + { + "name": "front-foot", + "parent": "front-shin", + "length": 91.34, + "rotation": 77.91, + "x": 128.76, + "y": -0.34, + "color": "00ff04ff" + }, + { + "name": "rear-upper-arm", + "parent": "torso", + "length": 51.94, + "rotation": -169.56, + "x": 92.36, + "y": -19.22, + "color": "ff000dff" + }, + { "name": "rear-bracer", "parent": "rear-upper-arm", "length": 34.56, "rotation": 23.15, "x": 51.36, "color": "ff000dff" }, + { + "name": "gun", + "parent": "rear-bracer", + "length": 43.11, + "rotation": 5.35, + "x": 34.42, + "y": -0.45, + "color": "ff000dff" + }, + { "name": "gun-tip", "parent": "gun", "rotation": 6.83, "x": 201.05, "y": 52.14, "color": "ff000dff" }, + { + "name": "neck", + "parent": "torso", + "length": 25.45, + "rotation": -31.54, + "x": 127.5, + "y": -0.31, + "color": "e0da19ff" + }, + { + "name": "head", + "parent": "neck", + "length": 263.58, + "rotation": 23.18, + "x": 27.66, + "y": -0.26, + "color": "e0da19ff" + }, + { + "name": "rear-thigh", + "parent": "hip", + "length": 85.72, + "rotation": -72.54, + "x": 8.91, + "y": -5.63, + "color": "ff000dff" + }, + { + "name": "rear-shin", + "parent": "rear-thigh", + "length": 121.88, + "rotation": -19.83, + "x": 86.1, + "y": -1.33, + "color": "ff000dff" + }, + { + "name": "rear-foot", + "parent": "rear-shin", + "length": 82.57, + "rotation": 69.3, + "x": 121.46, + "y": -0.76, + "color": "ff000dff" + } +], +"slots": [ + { "name": "rear-upper-arm", "bone": "rear-upper-arm", "attachment": "rear-upper-arm" }, + { "name": "rear-bracer", "bone": "rear-bracer", "attachment": "rear-bracer" }, + { "name": "gun", "bone": "gun", "attachment": "gun" }, + { "name": "rear-foot", "bone": "rear-foot", "attachment": "rear-foot" }, + { "name": "rear-thigh", "bone": "rear-thigh", "attachment": "rear-thigh" }, + { "name": "rear-shin", "bone": "rear-shin", "attachment": "rear-shin" }, + { "name": "neck", "bone": "neck", "attachment": "neck" }, + { "name": "torso", "bone": "torso", "attachment": "torso" }, + { "name": "front-upper-arm", "bone": "front-upper-arm", "attachment": "front-upper-arm" }, + { "name": "head", "bone": "head", "attachment": "head" }, + { "name": "eye", "bone": "head", "attachment": "eye-indifferent" }, + { "name": "front-thigh", "bone": "front-thigh", "attachment": "front-thigh" }, + { "name": "front-foot", "bone": "front-foot", "attachment": "front-foot" }, + { "name": "front-shin", "bone": "front-shin", "attachment": "front-shin" }, + { "name": "mouth", "bone": "head", "attachment": "mouth-smile" }, + { "name": "goggles", "bone": "head", "attachment": "goggles" }, + { "name": "front-bracer", "bone": "front-bracer", "attachment": "front-bracer" }, + { "name": "front-fist", "bone": "front-fist", "attachment": "front-fist-closed" }, + { "name": "muzzle", "bone": "gun-tip", "blend": "additive" }, + { "name": "head-bb", "bone": "head" } +], +"skins": [ + { + "name": "default", + "attachments": { + "eye": { + "eye-indifferent": { "x": 85.72, "y": -28.18, "rotation": -70.63, "width": 93, "height": 89 }, + "eye-surprised": { "x": 85.72, "y": -28.18, "rotation": -70.63, "width": 93, "height": 89 } + }, + "front-bracer": { + "front-bracer": { "x": 12.03, "y": -1.68, "rotation": 79.6, "width": 58, "height": 80 } + }, + "front-fist": { + "front-fist-closed": { "x": 35.5, "y": 6, "rotation": 67.16, "width": 75, "height": 82 }, + "front-fist-open": { "x": 39.57, "y": 7.76, "rotation": 67.16, "width": 86, "height": 87 } + }, + "front-foot": { + "front-foot": { "x": 29.52, "y": 7.84, "rotation": 18.69, "width": 126, "height": 69 } + }, + "front-shin": { + "front-shin": { "x": 55.12, "y": -3.54, "rotation": 96.59, "width": 82, "height": 184 } + }, + "front-thigh": { + "front-thigh": { "x": 42.48, "y": 4.45, "rotation": 84.87, "width": 45, "height": 112 } + }, + "front-upper-arm": { + "front-upper-arm": { "x": 25.2, "y": 1.17, "rotation": 97.9, "width": 46, "height": 97 } + }, + "goggles": { + "goggles": { "x": 97.08, "y": 6.54, "rotation": -70.63, "width": 261, "height": 166 } + }, + "gun": { + "gun": { "x": 77.3, "y": 16.4, "rotation": 60.83, "width": 210, "height": 203 } + }, + "head": { + "head": { "x": 128.96, "y": 0.3, "rotation": -70.63, "width": 271, "height": 298 } + }, + "head-bb": { + "head": { + "type": "boundingbox", + "vertexCount": 6, + "vertices": [ -19.14, -70.3, 40.8, -118.07, 257.77, -115.62, 285.16, 57.18, 120.77, 164.95, -5.07, 76.95 ] + } + }, + "mouth": { + "mouth-grind": { "x": 23.69, "y": -32.24, "rotation": -70.63, "width": 93, "height": 59 }, + "mouth-oooo": { "x": 23.69, "y": -32.24, "rotation": -70.63, "width": 93, "height": 59 }, + "mouth-smile": { "x": 23.69, "y": -32.24, "rotation": -70.63, "width": 93, "height": 59 } + }, + "muzzle": { + "muzzle01": { + "x": 159.26, + "y": 5.83, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 133, + "height": 79 + }, + "muzzle02": { + "x": 191.23, + "y": 5.91, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 135, + "height": 84 + }, + "muzzle03": { + "x": 230.67, + "y": 6.02, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 166, + "height": 106 + }, + "muzzle04": { + "x": 218.54, + "y": 5.99, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 149, + "height": 90 + } + }, + "neck": { + "neck": { "x": 9.77, "y": -3.01, "rotation": -55.22, "width": 36, "height": 41 } + }, + "rear-bracer": { + "rear-bracer": { "x": 11.15, "y": -2.2, "rotation": 66.17, "width": 56, "height": 72 } + }, + "rear-foot": { + "rear-foot": { "x": 31.51, "y": 3.58, "rotation": 23.07, "width": 113, "height": 60 } + }, + "rear-shin": { + "rear-shin": { "x": 58.29, "y": -2.75, "rotation": 92.37, "width": 75, "height": 178 } + }, + "rear-thigh": { + "rear-thigh": { "x": 33.11, "y": -4.11, "rotation": 72.54, "width": 55, "height": 94 } + }, + "rear-upper-arm": { + "rear-upper-arm": { "x": 21.13, "y": 4.09, "rotation": 89.33, "width": 40, "height": 87 } + }, + "torso": { + "torso": { "x": 63.61, "y": 7.12, "rotation": -94.54, "width": 98, "height": 180 } + } + } + } +], +"events": { + "footstep": {} +}, +"animations": { + "aim": { + "bones": { + "front-fist": { + "rotate": [ + { "value": 36.08 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": -26.55 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "value": 62.31 } + ] + }, + "front-bracer": { + "rotate": [ + { "value": 9.11 } + ] + }, + "gun": { + "rotate": [ + { "value": -0.31 } + ] + } + } + }, + "death": { + "slots": { + "eye": { + "attachment": [ + { "name": "eye-surprised" }, + { "time": 0.4667, "name": "eye-indifferent" }, + { "time": 2.2333, "name": "eye-surprised" }, + { "time": 4.5333, "name": "eye-indifferent" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "name": "mouth-oooo" }, + { "time": 2.2333, "name": "mouth-grind" }, + { "time": 4.5333, "name": "mouth-oooo" } + ] + } + }, + "bones": { + "head": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.044, -2.83, 0.105, -14.97 ] + }, + { + "time": 0.1333, + "value": -21.89, + "curve": [ 0.158, -28.04, 0.2, -34.87 ] + }, + { + "time": 0.2333, + "value": -34.87, + "curve": [ 0.267, -34.87, 0.3, -34.22 ] + }, + { + "time": 0.3333, + "value": -33.33, + "curve": [ 0.356, -32.74, 0.374, -30.69 ] + }, + { + "time": 0.4, + "value": -27.7, + "curve": [ 0.433, -23.82, 0.467, -10.64 ] + }, + { + "time": 0.5, + "value": -10.64, + "curve": [ 0.522, -10.64, 0.544, -16.82 ] + }, + { + "time": 0.5667, + "value": -23.05, + "curve": [ 0.589, -29.28, 0.611, -49.33 ] + }, + { + "time": 0.6333, + "value": -55.92, + "curve": [ 0.678, -69.1, 0.722, -82.35 ] + }, + { + "time": 0.7667, + "value": -82.35, + "curve": [ 0.787, -78.36, 0.912, -75.47 ] + }, + { "time": 1, "value": -78.9 }, + { + "time": 2.2333, + "value": -78.72, + "curve": [ 2.289, -78.72, 2.345, -66.24 ] + }, + { + "time": 2.4, + "value": -58.4, + "curve": [ 2.434, -53.72, 2.468, -52.12 ] + }, + { + "time": 2.5, + "value": -51.96, + "curve": [ 2.683, -51.05, 2.856, -50.86 ] + }, + { + "time": 3.0333, + "value": -50.86, + "curve": [ 3.343, -50.86, 3.712, -53.09 ] + }, + { + "time": 3.9333, + "value": -55.94, + "curve": [ 4.2, -59.38, 4.463, -65.17 ] + }, + { + "time": 4.5333, + "value": -69.07, + "curve": [ 4.598, -72.69, 4.635, -81.74 ] + }, + { "time": 4.6667, "value": -85.29 } + ], + "scale": [ + { + "time": 0.5, + "curve": [ 0.511, 1, 0.522, 1.041, 0.511, 1, 0.522, 0.953 ] + }, + { + "time": 0.5333, + "x": 1.041, + "y": 0.953, + "curve": [ 0.556, 1.041, 0.589, 1.038, 0.544, 0.953, 0.589, 0.959 ] + }, + { + "time": 0.6, + "x": 1.033, + "y": 0.966, + "curve": [ 0.633, 1.018, 0.667, 0.989, 0.633, 0.989, 0.667, 1.014 ] + }, + { + "time": 0.7, + "x": 0.989, + "y": 1.014, + "curve": [ 0.733, 0.989, 0.8, 1, 0.733, 1.014, 0.8, 1 ] + }, + { "time": 0.8333 } + ] + }, + "neck": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.033, -2.83, 0.1, 12.35 ] + }, + { + "time": 0.1333, + "value": 12.35, + "curve": [ 0.158, 12.35, 0.267, 2.18 ] + }, + { + "time": 0.3333, + "value": -8.48, + "curve": [ 0.389, -17.37, 0.444, -46.28 ] + }, + { + "time": 0.5, + "value": -46.28, + "curve": [ 0.522, -46.28, 0.551, -12.18 ] + }, + { + "time": 0.5667, + "value": -2.91, + "curve": [ 0.591, 11.16, 0.611, 20.82 ] + }, + { + "time": 0.6333, + "value": 23.43, + "curve": [ 0.756, 37.76, 0.878, 47.9 ] + }, + { + "time": 1, + "value": 47.91, + "curve": [ 1.411, 47.95, 1.935, 47.95 ] + }, + { + "time": 2.2333, + "value": 47.95, + "curve": [ 2.322, 47.95, 2.432, 19.53 ] + }, + { + "time": 2.5, + "value": 18.51, + "curve": [ 2.666, 16, 2.767, 14.59 ] + }, + { + "time": 2.9, + "value": 14.59, + "curve": [ 3.156, 14.59, 3.425, 14.72 ] + }, + { + "time": 3.6667, + "value": 15.23, + "curve": [ 4.026, 16, 4.28, 17.21 ] + }, + { + "time": 4.4667, + "value": 18.51, + "curve": [ 4.527, 18.71, 4.61, 45.05 ] + }, + { "time": 4.6667, "value": 47.95 } + ] + }, + "torso": { + "rotate": [ + { + "value": -8.62, + "curve": [ 0.031, -16.41, 0.1, -26.52 ] + }, + { + "time": 0.1333, + "value": -26.52, + "curve": [ 0.167, -26.52, 0.233, 3.45 ] + }, + { + "time": 0.2667, + "value": 21.92, + "curve": [ 0.326, 54.76, 0.422, 108.54 ] + }, + { + "time": 0.5, + "value": 108.54, + "curve": [ 0.522, 108.54, 0.559, 79.42 ] + }, + { + "time": 0.5667, + "value": 76.67, + "curve": [ 0.577, 72.83, 0.633, 68.68 ] + }, + { + "time": 0.6667, + "value": 68.68, + "curve": [ 0.733, 68.68, 0.8, 74.71 ] + }, + { "time": 0.8667, "value": 74.71, "curve": "stepped" }, + { + "time": 2.3333, + "value": 74.71, + "curve": [ 2.58, 74.71, 2.79, 72.33 ] + }, + { + "time": 2.9667, + "value": 72, + "curve": [ 3.439, 71.12, 3.668, 70.89 ] + }, + { + "time": 4, + "value": 71.29, + "curve": [ 4.189, 71.52, 4.286, 72.55 ] + }, + { "time": 4.6667, "value": 74.71 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -35.85, + "curve": [ 0.024, -41.49, 0.089, -48.72 ] + }, + { + "time": 0.1333, + "value": -48.72, + "curve": [ 0.178, -48.72, 0.225, -18.52 ] + }, + { + "time": 0.2667, + "value": -2.77, + "curve": [ 0.313, 14.63, 0.356, 29.38 ] + }, + { + "time": 0.4, + "value": 42.91, + "curve": [ 0.411, 46.3, 0.422, 47.99 ] + }, + { + "time": 0.4333, + "value": 47.99, + "curve": [ 0.456, 47.99, 0.482, 40.58 ] + }, + { + "time": 0.5, + "value": 35.07, + "curve": [ 0.533, 24.91, 0.567, 12.21 ] + }, + { + "time": 0.6, + "value": 12.36, + "curve": [ 0.633, 12.52, 0.667, 35.68 ] + }, + { + "time": 0.7, + "value": 35.68, + "curve": [ 0.789, 35.68, 0.878, 20.08 ] + }, + { "time": 0.9667, "value": 12.28, "curve": "stepped" }, + { "time": 2.2333, "value": 12.28 }, + { + "time": 2.5667, + "value": 64.63, + "curve": [ 2.589, 66.48, 2.611, 69.77 ] + }, + { + "time": 2.6333, + "value": 70.2, + "curve": [ 2.756, 72.57, 2.878, 73.08 ] + }, + { + "time": 3, + "value": 73.04, + "curve": [ 3.189, 72.97, 3.378, 69.18 ] + }, + { + "time": 3.5667, + "value": 68.76, + "curve": [ 3.735, 68.38, 3.902, 72.6 ] + }, + { + "time": 4.0667, + "value": 72.12, + "curve": [ 4.224, 71.68, 4.378, 72.12 ] + }, + { + "time": 4.5333, + "value": 64.63, + "curve": [ 4.622, 60.34, 4.711, 42.63 ] + }, + { "time": 4.8, "value": 31.63 }, + { "time": 4.9333, "value": 10.72 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": -44.7, + "curve": [ 0.044, -44.7, 0.089, 52.3 ] + }, + { + "time": 0.1333, + "value": 52.3, + "curve": [ 0.178, 52.3, 0.227, 48.52 ] + }, + { + "time": 0.2667, + "value": 41.27, + "curve": [ 0.332, 29.13, 0.356, 21.33 ] + }, + { + "time": 0.4, + "value": 21.33, + "curve": [ 0.511, 21.33, 0.577, 177.32 ] + }, + { + "time": 0.6667, + "value": 178.37, + "curve": [ 0.703, 178.79, 0.822, 158.2 ] + }, + { "time": 0.9, "value": 158.2 } + ], + "translate": [ + { "time": 0.4 }, + { "time": 0.9, "x": -32.41, "y": 0.65 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 21.88, + "curve": [ 0.048, 21.49, 0.089, 20.61 ] + }, + { + "time": 0.1333, + "value": 11.49, + "curve": [ 0.156, 6.92, 0.178, -12.78 ] + }, + { + "time": 0.2, + "value": -19.19, + "curve": [ 0.222, -25.6, 0.244, -26.96 ] + }, + { + "time": 0.2667, + "value": -26.96, + "curve": [ 0.311, -26.96, 0.356, -25.04 ] + }, + { + "time": 0.4, + "value": -15.9, + "curve": [ 0.433, -9.05, 0.467, 21.01 ] + }, + { + "time": 0.5, + "value": 21.01, + "curve": [ 0.533, 21.01, 0.567, -6.78 ] + }, + { + "time": 0.6, + "value": -18.23, + "curve": [ 0.622, -25.86, 0.644, -36.22 ] + }, + { + "time": 0.6667, + "value": -36.22, + "curve": [ 0.689, -36.22, 0.72, 1.23 ] + }, + { + "time": 0.7333, + "value": 10.31, + "curve": [ 0.761, 28.71, 0.822, 44.2 ] + }, + { + "time": 0.8667, + "value": 44.2, + "curve": [ 0.911, 44.2, 1, -14.97 ] + }, + { "time": 1, "value": -18.88, "curve": "stepped" }, + { + "time": 2.2333, + "value": -18.88, + "curve": [ 2.389, -18.88, 2.544, -1.96 ] + }, + { + "time": 2.7, + "value": -1.96, + "curve": [ 2.811, -1.96, 2.923, -10.35 ] + }, + { + "time": 3.0333, + "value": -10.35, + "curve": [ 3.224, -10.35, 3.411, -1.76 ] + }, + { + "time": 3.6, + "value": -1.76, + "curve": [ 3.922, -1.76, 4.244, -1.96 ] + }, + { + "time": 4.5667, + "value": -1.96, + "curve": [ 4.644, -1.96, 4.722, 34.31 ] + }, + { + "time": 4.8, + "value": 34.31, + "curve": [ 4.844, 34.31, 4.889, -1.06 ] + }, + { "time": 4.9333, "value": -18.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -2.33, + "curve": [ 0.044, -1.82, 0.089, -0.79 ] + }, + { + "time": 0.1333, + "value": -0.79, + "curve": [ 0.178, -0.79, 0.222, -12.86 ] + }, + { + "time": 0.2667, + "value": -12.86, + "curve": [ 0.322, -12.86, 0.378, -5.51 ] + }, + { + "time": 0.4333, + "value": -5.51, + "curve": [ 0.522, -5.51, 0.611, -23.93 ] + }, + { + "time": 0.7, + "value": -23.93, + "curve": [ 0.767, -23.93, 0.833, 6.31 ] + }, + { + "time": 0.9, + "value": 6.31, + "curve": [ 0.978, 6.31, 1.114, -2.63 ] + }, + { "time": 1.1333, "value": -5.63, "curve": "stepped" }, + { "time": 2.2333, "value": -5.63 }, + { "time": 2.4333, "value": -17.37 }, + { "time": 2.7, "value": 5.73, "curve": "stepped" }, + { + "time": 3.3667, + "value": 5.73, + "curve": [ 3.5, 5.73, 3.633, 1.93 ] + }, + { + "time": 3.7667, + "value": 1.93, + "curve": [ 3.867, 1.93, 3.967, 7.13 ] + }, + { + "time": 4.0667, + "value": 7.13, + "curve": [ 4.267, 7.13, 4.467, 5.73 ] + }, + { + "time": 4.6667, + "value": 5.73, + "curve": [ 4.678, 5.73, 4.732, 13.73 ] + }, + { + "time": 4.7667, + "value": 13.89, + "curve": [ 4.833, 14.19, 4.933, 4.95 ] + }, + { "time": 4.9333, "value": 3.65 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": 10.36 }, + { "time": 0.1333, "value": -23.12 }, + { "time": 0.2667, "value": -23.12 }, + { "time": 0.4, "value": -23.16, "curve": "stepped" }, + { "time": 0.4333, "value": -23.16 }, + { "time": 0.5667, "value": -23.2 } + ] + }, + "gun": { + "rotate": [ + { "value": -2.79 }, + { "time": 0.1333, "value": -24.58 } + ] + }, + "front-thigh": { + "rotate": [ + { + "curve": [ 0.052, 4.38, 0.089, 28.31 ] + }, + { + "time": 0.1333, + "value": 48.45, + "curve": [ 0.178, 68.6, 0.222, 99.39 ] + }, + { + "time": 0.2667, + "value": 120.87, + "curve": [ 0.311, 142.34, 0.356, 169.02 ] + }, + { + "time": 0.4, + "value": 177.3, + "curve": [ 0.433, 183.51, 0.467, 183.51 ] + }, + { + "time": 0.5, + "value": 183.51, + "curve": [ 0.544, 183.51, 0.589, 176.55 ] + }, + { + "time": 0.6333, + "value": 162.29, + "curve": [ 0.678, 148.03, 0.752, 108.37 ] + }, + { + "time": 0.7667, + "value": 97.94, + "curve": [ 0.819, 105.34, 0.856, 110.74 ] + }, + { + "time": 0.9, + "value": 110.74, + "curve": [ 0.944, 110.74, 1.016, 102.2 ] + }, + { "time": 1.0333, "value": 97.93 } + ] + }, + "front-shin": { + "rotate": [ + { + "curve": [ 0.044, 0.09, 0.1, -7.14 ] + }, + { + "time": 0.1333, + "value": -14.67, + "curve": [ 0.169, -22.83, 0.222, -43.77 ] + }, + { + "time": 0.2667, + "value": -43.77, + "curve": [ 0.311, -43.77, 0.344, -43.27 ] + }, + { + "time": 0.4, + "value": -33.94, + "curve": [ 0.433, -28.34, 0.467, 4.15 ] + }, + { + "time": 0.5, + "value": 9.2, + "curve": [ 0.533, 14.25, 0.567, 14.25 ] + }, + { + "time": 0.6, + "value": 14.25, + "curve": [ 0.733, 14.25, 0.867, 4.73 ] + }, + { "time": 1, "value": -0.03 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "curve": [ 0.044, 21.88, 0.089, 41.01 ] + }, + { + "time": 0.1333, + "value": 65.64, + "curve": [ 0.178, 90.28, 0.222, 127.15 ] + }, + { + "time": 0.2667, + "value": 147.79, + "curve": [ 0.311, 168.43, 0.356, 189.48 ] + }, + { + "time": 0.4, + "value": 189.48, + "curve": [ 0.433, 189.48, 0.473, 161.8 ] + }, + { + "time": 0.5, + "value": 142.56, + "curve": [ 0.542, 113.14, 0.589, 83.04 ] + }, + { + "time": 0.6, + "value": 78.15, + "curve": [ 0.613, 83.04, 0.733, 108.16 ] + }, + { + "time": 0.8, + "value": 108.16, + "curve": [ 0.878, 108.16, 1.009, 88.71 ] + }, + { "time": 1.0333, "value": 82.7 } + ] + }, + "rear-shin": { + "rotate": [ + { + "curve": [ 0.044, -19.59, 0.089, -58.76 ] + }, + { + "time": 0.1333, + "value": -58.76, + "curve": [ 0.178, -58.76, 0.222, -54.53 ] + }, + { + "time": 0.2667, + "value": -47.85, + "curve": [ 0.311, -41.16, 0.356, -33.24 ] + }, + { + "time": 0.4, + "value": -18.63, + "curve": [ 0.433, -7.68, 0.467, 28.83 ] + }, + { + "time": 0.5, + "value": 28.83, + "curve": [ 0.533, 28.83, 0.567, 15.17 ] + }, + { + "time": 0.6, + "value": 15.17, + "curve": [ 0.633, 15.17, 0.667, 16.17 ] + }, + { + "time": 0.7, + "value": 18.37, + "curve": [ 0.744, 21.32, 0.789, 27.27 ] + }, + { + "time": 0.8333, + "value": 30.61, + "curve": [ 0.878, 33.95, 0.922, 38.42 ] + }, + { + "time": 0.9667, + "value": 38.42, + "curve": [ 1.011, 38.42, 1.079, 17.39 ] + }, + { "time": 1.1, "value": 9.11 } + ] + }, + "rear-foot": { + "rotate": [ + { + "curve": [ 0.044, 0, 0.114, -5.44 ] + }, + { + "time": 0.1333, + "value": -11.63, + "curve": [ 0.158, -19.61, 0.222, -57.59 ] + }, + { + "time": 0.2667, + "value": -57.59, + "curve": [ 0.311, -57.59, 0.356, -45.6 ] + }, + { + "time": 0.4, + "value": -45.6, + "curve": [ 0.433, -45.6, 0.467, -65.99 ] + }, + { + "time": 0.5, + "value": -65.99, + "curve": [ 0.522, -65.99, 0.544, -21.7 ] + }, + { + "time": 0.5667, + "value": -21.7, + "curve": [ 0.6, -21.7, 0.633, -47.61 ] + }, + { + "time": 0.6667, + "value": -47.61, + "curve": [ 0.722, -47.61, 0.778, -25.68 ] + }, + { + "time": 0.8333, + "value": -15.6, + "curve": [ 0.878, -7.54, 0.922, 6.79 ] + }, + { + "time": 0.9667, + "value": 6.79, + "curve": [ 1.022, 6.79, 1.093, 2.23 ] + }, + { + "time": 1.1333, + "value": -6.82, + "curve": [ 1.165, -13.89, 1.178, -28.53 ] + }, + { + "time": 1.2, + "value": -28.53, + "curve": [ 1.267, -28.53, 1.333, -23.77 ] + }, + { "time": 1.4, "value": -23.77 } + ] + }, + "front-foot": { + "rotate": [ + { + "curve": [ 0.022, -21.9, 0.044, -65.7 ] + }, + { + "time": 0.0667, + "value": -65.7, + "curve": [ 0.089, -65.7, 0.111, -65.7 ] + }, + { + "time": 0.1333, + "value": -64.65, + "curve": [ 0.222, -60.43, 0.311, -52.48 ] + }, + { + "time": 0.4, + "value": -42.68, + "curve": [ 0.433, -39, 0.467, -33.17 ] + }, + { + "time": 0.5, + "value": -24.22, + "curve": [ 0.544, -12.29, 0.589, 19.98 ] + }, + { + "time": 0.6333, + "value": 19.98, + "curve": [ 0.656, 19.98, 0.678, 13.2 ] + }, + { + "time": 0.7, + "value": 2.45, + "curve": [ 0.733, -13.69, 0.767, -60.68 ] + }, + { + "time": 0.8, + "value": -60.68, + "curve": [ 0.878, -60.68, 0.956, 0.38 ] + }, + { + "time": 1.0333, + "value": 0.38, + "curve": [ 1.078, 0.38, 1.122, -31.77 ] + }, + { + "time": 1.1667, + "value": -31.77, + "curve": [ 1.211, -31.77, 1.256, -26.74 ] + }, + { "time": 1.3, "value": -24.22 } + ] + }, + "hip": { + "translate": [ + { + "curve": [ 0.081, -41.14, 0.178, -93.27, 0.038, 78.73, 0.156, 168.49 ] + }, + { + "time": 0.2667, + "x": -137.74, + "y": 169.66, + "curve": [ 0.333, -171.09, 0.4, -202.84, 0.377, 170.82, 0.467, 29.16 ] + }, + { + "time": 0.4667, + "x": -233.47, + "y": -76.63, + "curve": [ 0.5, -248.79, 0.533, -265.16, 0.521, -158.34, 0.516, -167.9 ] + }, + { + "time": 0.5667, + "x": -275.61, + "y": -209.28, + "curve": [ 0.589, -282.57, 0.608, -285.14, 0.572, -213.87, 0.611, -216.23 ] + }, + { + "time": 0.6333, + "x": -285.69, + "y": -216.23, + "curve": [ 0.713, -287.45, 0.789, -288.08, 0.711, -216.23, 0.812, -213.49 ] + }, + { + "time": 0.8667, + "x": -288.44, + "y": -209.28, + "curve": [ 0.911, -288.65, 0.965, -288.65, 0.919, -209.28, 0.967, -209.28 ] + }, + { "time": 1, "x": -288.65, "y": -209.28 } + ] + } + } + }, + "hit": { + "slots": { + "front-fist": { + "attachment": [ + { "time": 0.1667, "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "name": "mouth-grind" }, + { "time": 0.3333, "name": "mouth-smile" } + ] + } + }, + "bones": { + "torso": { + "rotate": [ + { "value": 56.42 }, + { "time": 0.3333, "value": 8.89 } + ] + }, + "neck": { + "rotate": [ + { "value": 35.39 }, + { "time": 0.2333, "value": 24.95 } + ] + }, + "head": { + "rotate": [ + { "value": 10.22 }, + { "time": 0.3333, "value": -41.3 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -310.93, + "curve": [ 0.127, -397.15, 0.248, -472.6 ] + }, + { "time": 0.3333, "value": -472.6 } + ], + "translate": [ + { "x": 7.23, "y": -13.13 } + ] + }, + "front-bracer": { + "rotate": [ + { "value": 36.99 }, + { "time": 0.3333, "value": -28.65 } + ] + }, + "front-fist": { + "rotate": [ + { "value": 13.59 }, + { "time": 0.3333, "value": 7.56 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 271.02, + "curve": [ 0.114, 297.63, 0.227, 322.97 ] + }, + { "time": 0.3333, "value": 344.16 } + ], + "translate": [ + { "time": 0.3333, "x": -0.1, "y": -0.46 } + ] + }, + "rear-bracer": { + "rotate": [ + {}, + { "time": 0.3333, "value": 40.03 } + ] + }, + "gun": { + "rotate": [ + { "value": 14.98 }, + { "time": 0.3333, "value": 39.76 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 90.94, + "curve": [ 0.076, 75.29, 0.144, 32.03 ] + }, + { "time": 0.3333, "value": 32.03 } + ], + "translate": [ + { "x": 7.21, "y": -4 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 40.52, + "curve": [ 0.099, 55.81, 0.197, 90.52 ] + }, + { "time": 0.3333, "value": 90.77 } + ], + "translate": [ + { "x": -1.96, "y": -0.32 } + ] + }, + "front-shin": { + "rotate": [ + { "value": -96.63 }, + { "time": 0.3333, "value": -15.13 } + ] + }, + "rear-shin": { + "rotate": [ + { "value": 8 }, + { "time": 0.3333, "value": -67.54 } + ] + }, + "front-foot": { + "rotate": [ + { "value": 5.4 }, + { "time": 0.3333, "value": -16.27 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": 2.67 }, + { "time": 0.3333, "value": -10.31 } + ] + }, + "hip": { + "translate": [ + { "x": -75.55, "y": -78.04 }, + { "time": 0.2333, "x": -36.48, "y": 12.42 }, + { "time": 0.3333, "x": -36.48, "y": -3 } + ] + } + } + }, + "idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "torso": { + "rotate": [ + { + "value": -16.11, + "curve": [ 0.057, -15.7, 0.268, -14.61 ] + }, + { + "time": 0.4333, + "value": -14.6, + "curve": [ 0.591, -14.59, 0.73, -15.81 ] + }, + { + "time": 0.8333, + "value": -16.63, + "curve": [ 0.915, -17.27, 1.074, -18.04 ] + }, + { + "time": 1.2333, + "value": -18.02, + "curve": [ 1.385, -18, 1.619, -16.57 ] + }, + { "time": 1.6667, "value": -16.11 } + ], + "translate": [ + { "x": -6.5 } + ], + "scale": [ + { + "curve": [ 0.156, 0.996, 0.525, 0.994, 0.106, 1.002, 0.525, 1.01 ] + }, + { + "time": 0.8333, + "x": 0.994, + "y": 1.01, + "curve": [ 1.15, 0.994, 1.52, 0.997, 1.15, 1.01, 1.519, 1.004 ] + }, + { "time": 1.6667 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -59.85, + "curve": [ 0.329, -59.85, 0.447, -64.99 ] + }, + { + "time": 0.6667, + "value": -64.99, + "curve": [ 0.997, -64.99, 1.417, -59.85 ] + }, + { "time": 1.6667, "value": -59.85 } + ], + "translate": [ + { + "x": -7.12, + "y": -8.24, + "curve": [ 0.167, -7.12, 0.5, -3.66, 0.167, -8.24, 0.5, -5.93 ] + }, + { + "time": 0.6667, + "x": -3.66, + "y": -5.93, + "curve": [ 0.917, -3.66, 1.417, -7.12, 0.917, -5.93, 1.417, -8.24 ] + }, + { "time": 1.6667, "x": -7.12, "y": -8.24 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 39.08, + "curve": [ 0.37, 38.67, 0.55, 32.29 ] + }, + { + "time": 0.7333, + "value": 32.29, + "curve": [ 0.967, 32.29, 1.433, 39.08 ] + }, + { "time": 1.6667, "value": 39.08 } + ], + "translate": [ + { + "x": -1.83, + "y": -6.48, + "curve": [ 0.167, -1.83, 0.5, 0.35, 0.167, -6.48, 0.447, -4.92 ] + }, + { + "time": 0.6667, + "x": 0.35, + "y": -4.92, + "curve": [ 0.917, 0.35, 1.417, -1.83, 0.917, -4.92, 1.417, -6.48 ] + }, + { "time": 1.6667, "x": -1.83, "y": -6.48 } + ] + }, + "neck": { + "rotate": [ + { + "curve": [ 0.167, 0, 0.5, 2.39 ] + }, + { + "time": 0.6667, + "value": 2.39, + "curve": [ 0.917, 2.39, 1.417, 0 ] + }, + { "time": 1.6667 } + ], + "translate": [ + { "x": -1.89, "y": -4.76 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 0.65, + "curve": [ 0.157, 0.6, 0.372, -4.31 ] + }, + { + "time": 0.6667, + "value": -4.34, + "curve": [ 1.262, -4.34, 1.32, 0.65 ] + }, + { "time": 1.6667, "value": 0.65 } + ], + "translate": [ + { "x": -13.4, "y": 6.7 } + ], + "scale": [ + { + "x": 0.945, + "curve": [ 0.157, 0.945, 0.372, 0.917, 0.157, 1, 0.372, 1 ] + }, + { + "time": 0.6667, + "x": 0.917, + "curve": [ 1.262, 0.917, 1.32, 0.945, 1.262, 1, 1.32, 1 ] + }, + { "time": 1.6667, "x": 0.945 } + ] + }, + "front-shin": { + "rotate": [ + { "value": -19.59 } + ], + "scale": [ + { + "curve": [ 0.157, 1, 0.372, 0.994, 0.157, 1, 0.372, 1 ] + }, + { + "time": 0.6667, + "x": 0.994, + "curve": [ 1.262, 0.994, 1.32, 1, 1.262, 1, 1.32, 1 ] + }, + { "time": 1.6667 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 30.51, + "curve": [ 0.157, 30.6, 0.372, 40.09 ] + }, + { + "time": 0.6667, + "value": 40.15, + "curve": [ 1.262, 40.14, 1.32, 30.51 ] + }, + { "time": 1.6667, "value": 30.51 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -24.14, + "curve": [ 0.157, -24.33, 0.372, -43.64 ] + }, + { + "time": 0.6667, + "value": -43.77, + "curve": [ 1.262, -43.76, 1.32, -23.83 ] + }, + { "time": 1.6667, "value": -23.83 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 4.83, + "curve": [ 0.157, 4.88, 0.372, 10.02 ] + }, + { + "time": 0.6667, + "value": 10.05, + "curve": [ 1.262, 10.05, 1.32, 5.14 ] + }, + { "time": 1.6667, "value": 5.14 } + ], + "scale": [ + { "x": 0.755, "y": 1.31 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -7.65, + "curve": [ 0.157, -7.54, 0.372, 3.78 ] + }, + { + "time": 0.6667, + "value": 3.85, + "curve": [ 1.262, 3.84, 1.32, -7.34 ] + }, + { "time": 1.6667, "value": -7.34 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": -17.16, + "curve": [ 0.167, -17.16, 0.447, -4.1 ] + }, + { + "time": 0.6667, + "value": -4.1, + "curve": [ 0.997, -4.1, 1.417, -17.16 ] + }, + { "time": 1.6667, "value": -17.16 } + ] + }, + "head": { + "rotate": [ + { + "value": -5.51, + "curve": [ 0.167, -5.51, 0.7, -3.12 ] + }, + { + "time": 0.8667, + "value": -3.12, + "curve": [ 1.117, -3.12, 1.417, -5.51 ] + }, + { "time": 1.6667, "value": -5.51 } + ], + "scale": [ + { + "curve": [ 0.217, 1, 0.546, 0.996, 0.217, 1, 0.546, 1.007 ] + }, + { + "time": 0.8667, + "x": 0.996, + "y": 1.007, + "curve": [ 1.171, 0.996, 1.467, 1, 1.171, 1.007, 1.467, 1 ] + }, + { "time": 1.6667 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 35.2, + "curve": [ 0.086, 36.03, 0.514, 40.31 ] + }, + { + "time": 0.6667, + "value": 40.3, + "curve": [ 0.859, 40.29, 0.969, 32.24 ] + }, + { + "time": 1.2, + "value": 32.31, + "curve": [ 1.401, 32.37, 1.561, 34.14 ] + }, + { "time": 1.6667, "value": 35.2 } + ] + }, + "gun": { + "rotate": [ + { + "curve": [ 0.167, 0, 0.581, -12.7 ] + }, + { + "time": 0.8667, + "value": -12.7, + "curve": [ 1.131, -12.7, 1.437, -0.11 ] + }, + { "time": 1.6667 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -6.85, + "curve": [ 0.181, -5.23, 0.5, -3.97 ] + }, + { + "time": 0.6667, + "value": -3.89, + "curve": [ 0.84, -3.81, 1.042, -9.89 ] + }, + { + "time": 1.2667, + "value": -9.76, + "curve": [ 1.428, -9.66, 1.537, -8.3 ] + }, + { "time": 1.6667, "value": -6.85 } + ], + "scale": [ + { + "curve": [ 0.167, 1, 0.5, 0.886, 0.167, 1, 0.5, 1.101 ] + }, + { + "time": 0.6667, + "x": 0.886, + "y": 1.101, + "curve": [ 0.917, 0.886, 1.417, 1, 0.917, 1.101, 1.417, 1 ] + }, + { "time": 1.6667 } + ] + }, + "hip": { + "translate": [ + { + "x": -6.64, + "y": -23.02, + "curve": [ 0.157, -6.51, 0.372, 6.19, 0.157, -23.13, 0.372, -34.93 ] + }, + { + "time": 0.6667, + "x": 6.28, + "y": -35.01, + "curve": [ 1.262, 6.27, 1.32, -6.64, 1.262, -35, 1.32, -23.02 ] + }, + { "time": 1.6667, "x": -6.64, "y": -23.02 } + ] + } + } + }, + "jump": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" }, + { "time": 0.1, "name": "front-fist-closed" }, + { "time": 0.8333, "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { + "value": 55.08, + "curve": [ 0.007, 46.66, 0.043, 26.3 ] + }, + { + "time": 0.0667, + "value": 22.84, + "curve": [ 0.1, 17.99, 0.165, 15.78 ] + }, + { + "time": 0.2333, + "value": 15.71, + "curve": [ 0.309, 15.63, 0.411, 36.56 ] + }, + { + "time": 0.5, + "value": 36.56, + "curve": [ 0.656, 36.56, 0.811, 33.41 ] + }, + { + "time": 0.9667, + "value": 26.43, + "curve": [ 1.011, 24.43, 1.056, 9.63 ] + }, + { + "time": 1.1, + "value": 9.63, + "curve": [ 1.122, 9.63, 1.144, 9.63 ] + }, + { + "time": 1.1667, + "value": 12.33, + "curve": [ 1.178, 13.68, 1.189, 47.62 ] + }, + { + "time": 1.2, + "value": 56.85, + "curve": [ 1.211, 66.08, 1.222, 67.7 ] + }, + { + "time": 1.2333, + "value": 67.72, + "curve": [ 1.261, 67.77, 1.322, 58.12 ] + }, + { "time": 1.3333, "value": 55.08 } + ], + "translate": [ + { + "x": -5.13, + "y": 11.55, + "curve": [ 0.422, -5.13, 0.733, -5.25, 0.422, 11.55, 0.733, 11.55 ] + }, + { + "time": 1.1, + "x": -5.25, + "y": 11.55, + "curve": [ 1.133, -5.25, 1.167, -4.54, 1.133, 11.55, 1.167, -1.07 ] + }, + { + "time": 1.2, + "x": -3.98, + "y": -1.07, + "curve": [ 1.211, -3.79, 1.222, -3.62, 1.211, -1.07, 1.222, 5.22 ] + }, + { + "time": 1.2333, + "x": -3.5, + "y": 5.73, + "curve": [ 1.245, -3.37, 1.289, -3.68, 1.245, 6.24, 1.283, 5.14 ] + }, + { + "time": 1.3, + "x": -4.1, + "y": 5.23, + "curve": [ 1.311, -4.52, 1.322, -4.99, 1.32, 5.32, 1.322, 9.78 ] + }, + { "time": 1.3333, "x": -5.13, "y": 11.55 } + ] + }, + "torso": { + "rotate": [ + { + "value": -45.57, + "curve": [ 0.022, -44.61, 0.03, -39.06 ] + }, + { + "time": 0.0667, + "value": -35.29, + "curve": [ 0.12, -29.77, 0.28, -19.95 ] + }, + { + "time": 0.4333, + "value": -19.95, + "curve": [ 0.673, -19.95, 0.871, -22.38 ] + }, + { + "time": 0.9667, + "value": -27.08, + "curve": [ 1.094, -33.33, 1.176, -44.93 ] + }, + { "time": 1.3333, "value": -45.57 } + ], + "translate": [ + { "x": -3.79, "y": -0.77 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 12.81, + "curve": [ 0.067, 12.81, 0.242, 67.88 ] + }, + { + "time": 0.2667, + "value": 74.11, + "curve": [ 0.314, 86.02, 0.454, 92.23 ] + }, + { + "time": 0.5667, + "value": 92.24, + "curve": [ 0.753, 92.26, 0.966, 67.94 ] + }, + { + "time": 1, + "value": 61.32, + "curve": [ 1.039, 53.75, 1.218, 12.68 ] + }, + { "time": 1.3333, "value": 12.81 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -115.64, + "curve": [ 0.067, -117.17, 0.125, -117.15 ] + }, + { + "time": 0.1667, + "value": -117.15, + "curve": [ 0.225, -117.15, 0.332, -108.76 ] + }, + { + "time": 0.4, + "value": -107.15, + "curve": [ 0.48, -105.26, 0.685, -103.49 ] + }, + { + "time": 0.7667, + "value": -101.97, + "curve": [ 0.826, -100.87, 0.919, -92.3 ] + }, + { + "time": 1, + "value": -92.28, + "curve": [ 1.113, -92.26, 1.297, -114.22 ] + }, + { "time": 1.3333, "value": -115.64 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -40.21, + "curve": [ 0.054, -35.46, 0.15, -31.12 ] + }, + { + "time": 0.2, + "value": -31.12, + "curve": [ 0.308, -31.12, 0.547, -80.12 ] + }, + { + "time": 0.6333, + "value": -96.56, + "curve": [ 0.697, -108.56, 0.797, -112.54 ] + }, + { + "time": 0.8667, + "value": -112.6, + "curve": [ 1.137, -112.84, 1.274, -49.19 ] + }, + { "time": 1.3333, "value": -40.21 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 20.54, + "curve": [ 0.054, 32.23, 0.192, 55.84 ] + }, + { + "time": 0.2333, + "value": 62.58, + "curve": [ 0.29, 71.87, 0.375, 79.28 ] + }, + { + "time": 0.4333, + "value": 79.18, + "curve": [ 0.555, 78.98, 0.684, 27.54 ] + }, + { + "time": 0.7333, + "value": 13.28, + "curve": [ 0.786, -1.85, 0.874, -24.76 ] + }, + { + "time": 1, + "value": -25.45, + "curve": [ 1.165, -26.36, 1.303, 9.1 ] + }, + { "time": 1.3333, "value": 20.54 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16, + "curve": [ 0.114, -39.59, 0.3, -45.61 ] + }, + { + "time": 0.4, + "value": -45.61, + "curve": [ 0.442, -45.61, 0.537, -21.54 ] + }, + { + "time": 0.5667, + "value": -15.4, + "curve": [ 0.592, -10.23, 0.692, 11.89 ] + }, + { + "time": 0.7333, + "value": 11.73, + "curve": [ 0.783, 11.54, 0.831, 1.8 ] + }, + { + "time": 0.8667, + "value": -5.78, + "curve": [ 0.897, -12.22, 0.901, -14.22 ] + }, + { + "time": 0.9333, + "value": -14.51, + "curve": [ 0.974, -14.89, 0.976, 10.38 ] + }, + { + "time": 1, + "value": 10.55, + "curve": [ 1.027, 10.74, 1.023, -8.44 ] + }, + { + "time": 1.0333, + "value": -8.42, + "curve": [ 1.059, -8.36, 1.074, 10.12 ] + }, + { + "time": 1.1, + "value": 10.22, + "curve": [ 1.168, 10.48, 1.27, -36.07 ] + }, + { "time": 1.3333, "value": -36.16 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.5, + "curve": [ 0.048, 36.1, 0.168, 20.45 ] + }, + { + "time": 0.3, + "value": 20.45, + "curve": [ 0.476, 20.45, 0.571, 33.76 ] + }, + { + "time": 0.6, + "value": 38.67, + "curve": [ 0.642, 45.8, 0.681, 57.44 ] + }, + { + "time": 0.7333, + "value": 62.91, + "curve": [ 0.829, 72.8, 0.996, 77.61 ] + }, + { + "time": 1.0333, + "value": 80.37, + "curve": [ 1.082, 83.94, 1.148, 90.6 ] + }, + { + "time": 1.2, + "value": 90.6, + "curve": [ 1.248, 90.46, 1.289, 44.58 ] + }, + { "time": 1.3333, "value": 40.5 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.022, 25.12, 0.187, -0.89 ] + }, + { + "time": 0.2, + "value": -2.52, + "curve": [ 0.257, -9.92, 0.372, -17.38 ] + }, + { + "time": 0.4333, + "value": -17.41, + "curve": [ 0.54, -17.47, 0.659, -16.91 ] + }, + { + "time": 0.7667, + "value": -12.1, + "curve": [ 0.907, -5.79, 1.025, 14.58 ] + }, + { + "time": 1.1, + "value": 20.58, + "curve": [ 1.191, 27.85, 1.283, 29.67 ] + }, + { "time": 1.3333, "value": 29.67 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.88, + "curve": [ 0.104, 11.82, 0.179, 11.15 ] + }, + { + "time": 0.2, + "value": 10.08, + "curve": [ 0.255, 7.29, 0.405, -8.15 ] + }, + { + "time": 0.4333, + "value": -9.35, + "curve": [ 0.508, -12.48, 0.595, -13.14 ] + }, + { + "time": 0.6667, + "value": -12.61, + "curve": [ 0.714, -12.26, 0.815, -5.57 ] + }, + { + "time": 0.8333, + "value": -4.08, + "curve": [ 0.883, -0.07, 1.011, 10.6 ] + }, + { + "time": 1.1, + "value": 15.01, + "curve": [ 1.178, 18.87, 1.279, 20.64 ] + }, + { "time": 1.3333, "value": 20.73 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.14, + "curve": [ 0.063, 13.1, 0.222, -20.78 ] + }, + { + "time": 0.3333, + "value": -20.78, + "curve": [ 0.467, -20.78, 0.6, 7.26 ] + }, + { + "time": 0.7333, + "value": 11.44, + "curve": [ 0.811, 13.88, 0.889, 13.88 ] + }, + { + "time": 0.9667, + "value": 13.88, + "curve": [ 1.044, 13.88, 1.122, 7.56 ] + }, + { + "time": 1.2, + "value": 7.56, + "curve": [ 1.244, 7.56, 1.289, 11.28 ] + }, + { "time": 1.3333, "value": 13.14 } + ], + "scale": [ + { + "curve": [ 0.041, 1, 0.052, 0.962, 0.041, 1, 0.052, 1.137 ] + }, + { + "time": 0.1, + "x": 0.954, + "y": 1.137, + "curve": [ 0.202, 0.962, 0.318, 1, 0.202, 1.137, 0.252, 1.002 ] + }, + { "time": 0.4667 }, + { + "time": 1.0667, + "x": 1.002, + "curve": [ 1.092, 1.002, 1.126, 1.173, 1.092, 1, 1.128, 0.975 ] + }, + { + "time": 1.1667, + "x": 1.174, + "y": 0.973, + "curve": [ 1.204, 1.175, 1.233, 0.959, 1.206, 0.972, 1.227, 1.062 ] + }, + { + "time": 1.2667, + "x": 0.958, + "y": 1.063, + "curve": [ 1.284, 0.958, 1.311, 1, 1.288, 1.063, 1.311, 1 ] + }, + { "time": 1.3333 } + ] + }, + "hip": { + "translate": [ + { + "y": -45.46, + "curve": [ 0.042, -0.09, 0.15, 15.22, 0.031, 44.98, 0.123, 289.73 ] + }, + { + "time": 0.2, + "x": 15.22, + "y": 415.85, + "curve": [ 0.332, 15.22, 0.539, -34.52, 0.271, 532.93, 0.483, 753.87 ] + }, + { + "time": 0.7667, + "x": -34.52, + "y": 754.96, + "curve": [ 0.888, -34.52, 1.057, -21.95, 1.049, 754.54, 1.098, 379.84 ] + }, + { + "time": 1.1333, + "x": -15.67, + "y": 266.77, + "curve": [ 1.144, -14.77, 1.188, -10.53, 1.15, 213.72, 1.172, -61.32 ] + }, + { + "time": 1.2333, + "x": -6.53, + "y": -61.34, + "curve": [ 1.272, -3.22, 1.311, 0.05, 1.291, -61.36, 1.296, -44.8 ] + }, + { "time": 1.3333, "y": -45.46 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -74.19, + "curve": [ 0, -51.14, 0.042, -12.54 ] + }, + { + "time": 0.1667, + "value": -12.28, + "curve": [ 0.285, -12.32, 0.389, -51.96 ] + }, + { + "time": 0.5, + "value": -51.96, + "curve": [ 0.633, -51.96, 0.767, -40.17 ] + }, + { + "time": 0.9, + "value": -30.59, + "curve": [ 0.967, -25.8, 1.033, -16.01 ] + }, + { + "time": 1.1, + "value": -8.85, + "curve": [ 1.122, -6.46, 1.144, -1.91 ] + }, + { + "time": 1.1667, + "value": -1.91, + "curve": [ 1.178, -1.91, 1.189, -58.19 ] + }, + { + "time": 1.2, + "value": -72.71, + "curve": [ 1.211, -87.23, 1.222, -89.05 ] + }, + { + "time": 1.2333, + "value": -89.05, + "curve": [ 1.273, -89.05, 1.308, -79.55 ] + }, + { "time": 1.3333, "value": -74.19 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 15.88, + "curve": [ 0, 13.33, 0.05, -26.64 ] + }, + { + "time": 0.0667, + "value": -26.64, + "curve": [ 0.192, -26.64, 0.442, -11.77 ] + }, + { + "time": 0.5667, + "value": -11.77, + "curve": [ 0.692, -11.77, 0.942, -19.36 ] + }, + { + "time": 1.0667, + "value": -19.36, + "curve": [ 1.089, -19.36, 1.127, -67.74 ] + }, + { + "time": 1.1667, + "value": -63.62, + "curve": [ 1.178, -62.51, 1.189, 5.83 ] + }, + { + "time": 1.2, + "value": 11.39, + "curve": [ 1.222, 22.51, 1.244, 22.51 ] + }, + { + "time": 1.2667, + "value": 22.51, + "curve": [ 1.289, 22.51, 1.333, 16.45 ] + }, + { "time": 1.3333, "value": 15.88 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -7.14, + "curve": [ 0.044, -17.32, 0.089, -37.67 ] + }, + { + "time": 0.1333, + "value": -37.67, + "curve": [ 0.311, -37.67, 0.521, -26.72 ] + }, + { + "time": 0.6667, + "value": -15.71, + "curve": [ 0.776, -7.49, 0.911, 14.92 ] + }, + { + "time": 1.0333, + "value": 14.92, + "curve": [ 1.133, 14.92, 1.233, 0.21 ] + }, + { "time": 1.3333, "value": -7.14 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.36, + "curve": [ 0.022, 16.28, 0.15, 30.81 ] + }, + { + "time": 0.2, + "value": 30.81, + "curve": [ 0.258, 30.81, 0.375, 13.26 ] + }, + { + "time": 0.4333, + "value": 13.26, + "curve": [ 0.508, 13.26, 0.658, 15.05 ] + }, + { + "time": 0.7333, + "value": 14.98, + "curve": [ 0.789, 14.94, 0.828, 13.62 ] + }, + { + "time": 0.8667, + "value": 12.72, + "curve": [ 0.887, 12.25, 0.984, 9.83 ] + }, + { + "time": 1.0333, + "value": 8.6, + "curve": [ 1.045, 8.31, 1.083, 7.55 ] + }, + { + "time": 1.1333, + "value": 7.13, + "curve": [ 1.175, 6.78, 1.283, 6.18 ] + }, + { "time": 1.3333, "value": 6.18 } + ] + } + }, + "events": [ + { "time": 1.2, "name": "footstep" } + ] + }, + "run": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { + "value": 49.77, + "curve": [ 0.007, 49.71, 0.022, 41.99 ] + }, + { + "time": 0.0333, + "value": 32.26, + "curve": [ 0.044, 22.54, 0.056, 0.1 ] + }, + { + "time": 0.0667, + "value": -8.56, + "curve": [ 0.078, -17.22, 0.089, -19.05 ] + }, + { + "time": 0.1, + "value": -19.71, + "curve": [ 0.144, -22.38, 0.189, -22.38 ] + }, + { + "time": 0.2333, + "value": -22.38, + "curve": [ 0.267, -22.38, 0.3, 36.57 ] + }, + { + "time": 0.3333, + "value": 54.69, + "curve": [ 0.367, 72.82, 0.4, 86.37 ] + }, + { + "time": 0.4333, + "value": 86.37, + "curve": [ 0.478, 86.37, 0.522, 46.94 ] + }, + { + "time": 0.5667, + "value": 46.94, + "curve": [ 0.589, 46.94, 0.652, 49.34 ] + }, + { "time": 0.6667, "value": 49.77 } + ], + "translate": [ + { + "x": -7.86, + "y": 10.34, + "curve": [ 0.036, -7.85, 0.123, -6.71, 0.056, 10.34, 0.108, 9.74 ] + }, + { + "time": 0.1667, + "x": -5.7, + "y": 7.99, + "curve": [ 0.22, -4.49, 0.295, -0.78, 0.236, 5.93, 0.28, 3.22 ] + }, + { + "time": 0.3333, + "x": 1.68, + "y": 3.19, + "curve": [ 0.358, 3.28, 0.449, 9.99, 0.384, 3.16, 0.449, 4.98 ] + }, + { + "time": 0.5, + "x": 9.99, + "y": 6.76, + "curve": [ 0.556, 10, 0.611, -7.86, 0.556, 8.69, 0.611, 10.34 ] + }, + { "time": 0.6667, "x": -7.86, "y": 10.34 } + ] + }, + "torso": { + "rotate": [ + { + "value": -38.65, + "curve": [ 0.022, -39.16, 0.067, -41.4 ] + }, + { + "time": 0.1, + "value": -41.4, + "curve": [ 0.156, -41.4, 0.211, -37.6 ] + }, + { + "time": 0.2667, + "value": -37.6, + "curve": [ 0.289, -37.6, 0.315, -38.2 ] + }, + { + "time": 0.3333, + "value": -38.63, + "curve": [ 0.369, -39.48, 0.434, -41.38 ] + }, + { + "time": 0.4667, + "value": -41.39, + "curve": [ 0.512, -41.39, 0.556, -37.69 ] + }, + { + "time": 0.6, + "value": -37.69, + "curve": [ 0.622, -37.69, 0.652, -38.3 ] + }, + { "time": 0.6667, "value": -38.65 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 17.72, + "curve": [ 0.025, 28.51, 0.067, 54.38 ] + }, + { + "time": 0.1, + "value": 54.38, + "curve": [ 0.144, 54.38, 0.189, 19.31 ] + }, + { + "time": 0.2333, + "value": 19.31, + "curve": [ 0.254, 19.31, 0.278, 32.87 ] + }, + { + "time": 0.3, + "value": 32.87, + "curve": [ 0.311, 32.87, 0.322, 32.87 ] + }, + { + "time": 0.3333, + "value": 28.23, + "curve": [ 0.344, 23.6, 0.356, 4.08 ] + }, + { + "time": 0.3667, + "value": -3.6, + "curve": [ 0.389, -18.95, 0.411, -38.43 ] + }, + { + "time": 0.4333, + "value": -40.85, + "curve": [ 0.478, -45.69, 0.522, -45.69 ] + }, + { + "time": 0.5667, + "value": -45.69, + "curve": [ 0.6, -45.69, 0.633, -7.24 ] + }, + { "time": 0.6667, "value": 17.72 } + ], + "translate": [ + { + "x": -13.59, + "y": 3.21, + "curve": [ 0.013, -12.85, 0.183, -8.55, 0.03, 4.05, 0.183, 6.17 ] + }, + { + "time": 0.2333, + "x": -8.55, + "y": 6.17, + "curve": [ 0.308, -8.55, 0.492, -19.75, 0.308, 6.17, 0.492, 0.61 ] + }, + { + "time": 0.5667, + "x": -19.75, + "y": 0.61, + "curve": [ 0.592, -19.75, 0.633, -15.46, 0.592, 0.61, 0.633, 2.28 ] + }, + { "time": 0.6667, "x": -13.59, "y": 3.21 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": 324.21, + "curve": [ 0.051, 363.15, 0.145, 449.66 ] + }, + { + "time": 0.2333, + "value": 449.66, + "curve": [ 0.28, 450.07, 0.324, 419.51 ] + }, + { + "time": 0.3333, + "value": 411.11, + "curve": [ 0.358, 390.19, 0.445, 293.13 ] + }, + { + "time": 0.5667, + "value": 292.23, + "curve": [ 0.599, 291.99, 0.633, 298.54 ] + }, + { "time": 0.6667, "value": 324.21 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 7.49, + "curve": [ 0.032, 2.15, 0.089, -2.82 ] + }, + { + "time": 0.1333, + "value": -2.8, + "curve": [ 0.186, -2.78, 0.221, 26.29 ] + }, + { + "time": 0.2333, + "value": 32.37, + "curve": [ 0.247, 39.19, 0.286, 61.45 ] + }, + { + "time": 0.3333, + "value": 61.58, + "curve": [ 0.371, 61.69, 0.42, 55.79 ] + }, + { + "time": 0.4667, + "value": 49.68, + "curve": [ 0.533, 40.96, 0.643, 13.39 ] + }, + { "time": 0.6667, "value": 7.49 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -10.96, + "curve": [ 0.014, -13.6, 0.036, -43.27 ] + }, + { + "time": 0.0667, + "value": -43.37, + "curve": [ 0.102, -43.49, 0.182, -28.46 ] + }, + { + "time": 0.2, + "value": -23.04, + "curve": [ 0.23, -13.87, 0.264, 3.86 ] + }, + { + "time": 0.3333, + "value": 3.7, + "curve": [ 0.38, 3.64, 0.489, -21.29 ] + }, + { + "time": 0.5667, + "value": -21.29, + "curve": [ 0.6, -21.29, 0.633, -10.96 ] + }, + { "time": 0.6667, "value": -10.96 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 35.32, + "curve": [ 0.028, 18.56, 0.128, -79.86 ] + }, + { + "time": 0.2333, + "value": -79.87, + "curve": [ 0.38, -79.88, 0.403, 63.25 ] + }, + { + "time": 0.5667, + "value": 64.13, + "curve": [ 0.607, 64.35, 0.633, 55.07 ] + }, + { "time": 0.6667, "value": 35.32 } + ], + "translate": [ + { + "x": -4.58, + "y": 0.93, + "curve": [ 0.044, -5.37, 0.169, -5.48, 0.044, 2.63, 0.169, 2.85 ] + }, + { + "time": 0.2333, + "x": -5.48, + "y": 2.85, + "curve": [ 0.346, -5.48, 0.475, -2.68, 0.346, 2.85, 0.475, -3.13 ] + }, + { + "time": 0.5667, + "x": -2.68, + "y": -3.13, + "curve": [ 0.611, -2.68, 0.633, -3.98, 0.611, -3.13, 0.633, -0.35 ] + }, + { "time": 0.6667, "x": -4.58, "y": 0.93 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": 17.03 }, + { + "time": 0.2333, + "value": -13.07, + "curve": [ 0.252, -16.08, 0.297, -19.37 ] + }, + { + "time": 0.3333, + "value": -19.38, + "curve": [ 0.435, -19.41, 0.522, 38.96 ] + }, + { + "time": 0.5667, + "value": 38.87, + "curve": [ 0.619, 38.76, 0.625, 24.64 ] + }, + { "time": 0.6667, "value": 17.03 } + ] + }, + "neck": { + "rotate": [ + { + "value": 10.23, + "curve": [ 0.024, 9.75, 0.075, 9.74 ] + }, + { + "time": 0.1, + "value": 9.74, + "curve": [ 0.125, 9.74, 0.208, 13.36 ] + }, + { + "time": 0.2333, + "value": 13.36, + "curve": [ 0.258, 13.36, 0.3, 10.88 ] + }, + { + "time": 0.3333, + "value": 10.3, + "curve": [ 0.367, 9.72, 0.408, 9.72 ] + }, + { + "time": 0.4333, + "value": 9.72, + "curve": [ 0.458, 9.72, 0.542, 13.36 ] + }, + { + "time": 0.5667, + "value": 13.36, + "curve": [ 0.592, 13.36, 0.633, 10.91 ] + }, + { "time": 0.6667, "value": 10.23 } + ] + }, + "head": { + "rotate": [ + { + "value": 8.93, + "curve": [ 0.033, 7.96, 0.065, 6.03 ] + }, + { + "time": 0.1, + "value": 6.03, + "curve": [ 0.146, 6.03, 0.189, 10.78 ] + }, + { + "time": 0.2333, + "value": 10.78, + "curve": [ 0.267, 10.78, 0.309, 9.94 ] + }, + { + "time": 0.3333, + "value": 8.93, + "curve": [ 0.358, 7.93, 0.388, 6.1 ] + }, + { + "time": 0.4333, + "value": 6.1, + "curve": [ 0.486, 6.1, 0.544, 10.76 ] + }, + { + "time": 0.6, + "value": 10.76, + "curve": [ 0.622, 10.76, 0.652, 9.58 ] + }, + { "time": 0.6667, "value": 8.93 } + ], + "scale": [ + { + "x": 0.992, + "y": 1.01, + "curve": [ 0.036, 0.991, 0.068, 0.991, 0.014, 1.013, 0.083, 1.026 ] + }, + { + "time": 0.1, + "x": 0.991, + "y": 1.026, + "curve": [ 0.128, 0.991, 0.205, 1.038, 0.128, 1.026, 0.197, 0.982 ] + }, + { + "time": 0.2333, + "x": 1.038, + "y": 0.982, + "curve": [ 0.272, 1.038, 0.305, 1.008, 0.262, 0.982, 0.311, 0.995 ] + }, + { + "time": 0.3333, + "curve": [ 0.351, 0.995, 0.417, 0.981, 0.359, 1.006, 0.417, 1.026 ] + }, + { + "time": 0.4333, + "x": 0.981, + "y": 1.026, + "curve": [ 0.467, 0.981, 0.533, 1.037, 0.467, 1.026, 0.533, 0.982 ] + }, + { + "time": 0.5667, + "x": 1.037, + "y": 0.982, + "curve": [ 0.592, 1.037, 0.636, 0.993, 0.592, 0.982, 0.64, 1.004 ] + }, + { "time": 0.6667, "x": 0.992, "y": 1.01 } + ] + }, + "gun": { + "rotate": [ + { + "value": 18.25, + "curve": [ 0.033, 19.24, 0.087, 20.25 ] + }, + { + "time": 0.1333, + "value": 20.19, + "curve": [ 0.168, 20.32, 0.254, -8.82 ] + }, + { + "time": 0.2667, + "value": -11.88, + "curve": [ 0.291, -17.91, 0.344, -24.11 ] + }, + { + "time": 0.4, + "value": -23.88, + "curve": [ 0.448, -23.69, 0.533, -15.47 ] + }, + { "time": 0.5667, "value": -8.69 }, + { "time": 0.6667, "value": 18.25 } + ] + }, + "hip": { + "translate": [ + { + "x": 0.63, + "y": -34.19, + "curve": [ 0.042, 0.39, 0.118, 7.62, 0.042, -33.83, 0.084, 20.04 ] + }, + { + "time": 0.1667, + "x": 7.61, + "y": 20.36, + "curve": [ 0.194, 7.6, 0.21, 5.06, 0.204, 20.65, 0.217, -8.69 ] + }, + { + "time": 0.2333, + "x": 1.68, + "y": -18.48, + "curve": [ 0.279, -4.99, 0.297, -5.64, 0.254, -31.08, 0.292, -34.55 ] + }, + { + "time": 0.3333, + "x": -5.76, + "y": -35, + "curve": [ 0.379, -5.9, 0.451, 6.8, 0.384, -35.56, 0.416, 17.6 ] + }, + { + "time": 0.5, + "x": 6.61, + "y": 17.01, + "curve": [ 0.536, 6.47, 0.545, 3.56, 0.533, 16.75, 0.548, -8.71 ] + }, + { + "time": 0.5667, + "x": 0.35, + "y": -18.81, + "curve": [ 0.597, -4.07, 0.633, 0.82, 0.584, -28.58, 0.633, -34.48 ] + }, + { "time": 0.6667, "x": 0.63, "y": -34.19 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -27.81, + "curve": [ 0.078, -27.81, 0.156, 17.7 ] + }, + { + "time": 0.2333, + "value": 17.7, + "curve": [ 0.256, 17.7, 0.278, 12.8 ] + }, + { + "time": 0.3, + "value": 12.8, + "curve": [ 0.311, 12.8, 0.322, 17.93 ] + }, + { + "time": 0.3333, + "value": 20.49, + "curve": [ 0.344, 20.49, 0.356, 36.91 ] + }, + { + "time": 0.3667, + "value": 33.49, + "curve": [ 0.378, 30.04, 0.389, 28.84 ] + }, + { + "time": 0.4, + "value": 19.93, + "curve": [ 0.411, 10.9, 0.422, -5.84 ] + }, + { + "time": 0.4333, + "value": -8.18, + "curve": [ 0.478, -17.39, 0.523, 4.88 ] + }, + { + "time": 0.5667, + "value": 2.21, + "curve": [ 0.6, 0.19, 0.633, -27.81 ] + }, + { "time": 0.6667, "value": -27.81 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 11.76, + "curve": [ 0.008, 11.76, 0.02, 19.97 ] + }, + { + "time": 0.0333, + "value": 20.38, + "curve": [ 0.044, 20.72, 0.056, 17.21 ] + }, + { + "time": 0.0667, + "value": 11.96, + "curve": [ 0.079, 6.01, 0.089, -24.56 ] + }, + { + "time": 0.1, + "value": -25.8, + "curve": [ 0.144, -30.78, 0.189, -30.78 ] + }, + { + "time": 0.2333, + "value": -30.78, + "curve": [ 0.267, -30.78, 0.3, -29.2 ] + }, + { + "time": 0.3333, + "value": -24.64, + "curve": [ 0.389, -17.03, 0.444, -0.27 ] + }, + { + "time": 0.5, + "value": 5.74, + "curve": [ 0.556, 11.76, 0.633, 11.76 ] + }, + { "time": 0.6667, "value": 11.76 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -66.44, + "curve": [ 0.011, -66.44, 0.022, -65.11 ] + }, + { + "time": 0.0333, + "value": -58, + "curve": [ 0.044, -50.9, 0.056, -28.78 ] + }, + { + "time": 0.0667, + "value": -23.84, + "curve": [ 0.078, -18.9, 0.089, -18.9 ] + }, + { + "time": 0.1, + "value": -18.9, + "curve": [ 0.144, -18.9, 0.189, -66.55 ] + }, + { + "time": 0.2333, + "value": -85.8, + "curve": [ 0.267, -100.25, 0.3, -120 ] + }, + { + "time": 0.3333, + "value": -120, + "curve": [ 0.367, -120, 0.4, -116.77 ] + }, + { + "time": 0.4333, + "value": -103.62, + "curve": [ 0.456, -94.85, 0.478, -73.54 ] + }, + { + "time": 0.5, + "value": -54.26, + "curve": [ 0.522, -34.99, 0.544, -5.08 ] + }, + { + "time": 0.5667, + "value": -5.08, + "curve": [ 0.589, -5.08, 0.611, -31.56 ] + }, + { + "time": 0.6333, + "value": -45.19, + "curve": [ 0.644, -52.01, 0.656, -66.44 ] + }, + { "time": 0.6667, "value": -66.44 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -99.91, + "curve": [ 0.048, -99.45, 0.067, -87.25 ] + }, + { + "time": 0.1, + "value": -72.41, + "curve": [ 0.144, -52.61, 0.189, 4.01 ] + }, + { + "time": 0.2333, + "value": 4.01, + "curve": [ 0.256, 4.01, 0.278, -32.4 ] + }, + { + "time": 0.3, + "value": -46.27, + "curve": [ 0.311, -53.2, 0.322, -58.41 ] + }, + { + "time": 0.3333, + "value": -58.41, + "curve": [ 0.367, -58.41, 0.4, -2.86 ] + }, + { + "time": 0.4333, + "value": -2.86, + "curve": [ 0.478, -2.86, 0.522, -61.56 ] + }, + { + "time": 0.5667, + "value": -80.05, + "curve": [ 0.6, -93.91, 0.632, -99.87 ] + }, + { "time": 0.6667, "value": -99.91 } + ] + }, + "gun-tip": { + "rotate": [ + { "time": 0.4333, "value": 12.93 } + ] + } + }, + "drawOrder": [ + { + "offsets": [ + { "slot": "head", "offset": -2 } + ] + } + ], + "events": [ + { "time": 0.2667, "name": "footstep" }, + { "time": 0.6, "name": "footstep" } + ] + }, + "shoot": { + "slots": { + "muzzle": { + "rgba": [ + { "time": 0.3667, "color": "ffffff00" } + ], + "attachment": [ + { "time": 0.1333, "name": "muzzle01" }, + { "time": 0.2, "name": "muzzle02" }, + { "time": 0.2667, "name": "muzzle03" }, + { "time": 0.3333, "name": "muzzle04" }, + { "time": 0.3667 } + ] + } + }, + "bones": { + "gun-tip": { + "translate": [ + { "time": 0.1333 }, + { "time": 0.2333, "x": 32.31, "y": 2.94 } + ] + }, + "gun": { + "rotate": [ + { "value": 1.91, "curve": "stepped" }, + { + "time": 0.1, + "value": 1.91, + "curve": [ 0.113, 4.95, 0.122, 6.56 ] + }, + { + "time": 0.1333, + "value": 6.56, + "curve": [ 0.167, 6.56, 0.2, -0.97 ] + }, + { + "time": 0.2333, + "value": -0.97, + "curve": [ 0.289, -0.97, 0.344, 0.95 ] + }, + { "time": 0.4, "value": 1.91 } + ], + "translate": [ + { "x": 7.95, "y": 5.85, "curve": "stepped" }, + { + "time": 0.1, + "x": 7.95, + "y": 5.85, + "curve": [ 0.167, 7.95, 0.204, -9.3, 0.167, 5.85, 0.204, -1.41 ] + }, + { + "time": 0.3, + "x": -9.3, + "y": -1.41, + "curve": [ 0.333, -9.3, 0.367, 7.95, 0.333, -1.41, 0.367, 5.85 ] + }, + { "time": 0.4, "x": 7.95, "y": 5.85 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": -30.47 } + ], + "translate": [ + { + "time": 0.1, + "curve": [ 0.156, -4.39, 0.204, -6, 0.167, -3.38, 0.204, -3.72 ] + }, + { "time": 0.3, "x": -6, "y": -3.72 }, + { "time": 0.4 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "value": 62.31 } + ], + "translate": [ + { + "time": 0.1, + "curve": [ 0.167, 0, 0.204, 2.81, 0.16, 11.74, 0.23, 11.7 ] + }, + { "time": 0.3, "x": 2.81, "y": 11.53 }, + { "time": 0.4 } + ] + } + } + }, + "walk": { + "bones": { + "hip": { + "rotate": [ + { "value": 0.94 } + ], + "translate": [ + { + "x": -2.86, + "y": -13.86, + "curve": [ 0.025, -2.84, 0.067, -2.82, 0.028, -19.14, 0.054, -31.19 ] + }, + { + "time": 0.1, + "x": -2.61, + "y": -31.36, + "curve": [ 0.143, -2.34, 0.202, -1.79, 0.152, -31.16, 0.213, -14.81 ] + }, + { + "time": 0.2667, + "x": -1.21, + "y": -7.12, + "curve": [ 0.308, -0.86, 0.345, -0.51, 0.306, -1.63, 0.341, 3.15 ] + }, + { + "time": 0.3667, + "x": -0.33, + "y": 3.15, + "curve": [ 0.41, 0.02, 0.458, 0.26, 0.427, 3.3, 0.481, -6.75 ] + }, + { + "time": 0.5, + "x": 0.26, + "y": -10.59, + "curve": [ 0.553, 0.26, 0.559, 0.2, 0.519, -14.41, 0.548, -31.74 ] + }, + { + "time": 0.6, + "x": -0.17, + "y": -31.56, + "curve": [ 0.632, -0.45, 0.683, -0.94, 0.646, -31.41, 0.688, -17.46 ] + }, + { + "time": 0.7333, + "x": -1.4, + "y": -8.62, + "curve": [ 0.783, -1.85, 0.833, -2.28, 0.77, -1.61, 0.831, 3.51 ] + }, + { + "time": 0.8667, + "x": -2.46, + "y": 3.48, + "curve": [ 0.901, -2.63, 0.967, -2.87, 0.913, 3.45, 0.967, -7.64 ] + }, + { "time": 1, "x": -2.86, "y": -13.86 } + ] + }, + "torso": { + "rotate": [ + { + "value": -20.72, + "curve": [ 0.013, -20.49, 0.071, -19.12 ] + }, + { + "time": 0.1333, + "value": -19.12, + "curve": [ 0.187, -19.12, 0.285, -22.22 ] + }, + { + "time": 0.3667, + "value": -22.22, + "curve": [ 0.405, -22.22, 0.491, -20.92 ] + }, + { + "time": 0.5, + "value": -20.71, + "curve": [ 0.51, -20.48, 0.582, -19.06 ] + }, + { + "time": 0.6333, + "value": -19.06, + "curve": [ 0.709, -19.07, 0.815, -22.22 ] + }, + { + "time": 0.8667, + "value": -22.22, + "curve": [ 0.908, -22.22, 0.981, -21.1 ] + }, + { "time": 1, "value": -20.72 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.78, + "curve": [ 0.025, 17.93, 0.071, 18.46 ] + }, + { + "time": 0.1333, + "value": 18.46, + "curve": [ 0.187, 18.46, 0.285, 17.34 ] + }, + { + "time": 0.3667, + "value": 17.34, + "curve": [ 0.405, 17.34, 0.47, 17.6 ] + }, + { + "time": 0.5, + "value": 17.79, + "curve": [ 0.518, 17.9, 0.582, 18.47 ] + }, + { + "time": 0.6333, + "value": 18.46, + "curve": [ 0.709, 18.45, 0.815, 17.32 ] + }, + { + "time": 0.8667, + "value": 17.32, + "curve": [ 0.908, 17.32, 0.971, 17.57 ] + }, + { "time": 1, "value": 17.78 } + ] + }, + "head": { + "rotate": [ + { + "value": -12.23, + "curve": [ 0.061, -12.23, 0.191, -7.45 ] + }, + { + "time": 0.2667, + "value": -7.43, + "curve": [ 0.341, -7.42, 0.421, -12.23 ] + }, + { + "time": 0.5, + "value": -12.23, + "curve": [ 0.567, -12.26, 0.694, -7.46 ] + }, + { + "time": 0.7667, + "value": -7.47, + "curve": [ 0.853, -7.49, 0.943, -12.23 ] + }, + { "time": 1, "value": -12.23 } + ], + "scale": [ + { + "curve": [ 0.039, 1, 0.084, 0.991, 0.039, 1, 0.084, 1.019 ] + }, + { + "time": 0.1333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.205, 0.991, 0.318, 1.019, 0.205, 1.019, 0.337, 0.992 ] + }, + { + "time": 0.4, + "x": 1.019, + "y": 0.992, + "curve": [ 0.456, 1.019, 0.494, 1.001, 0.483, 0.991, 0.493, 0.999 ] + }, + { + "time": 0.5, + "curve": [ 0.508, 0.998, 0.584, 0.991, 0.51, 1.002, 0.584, 1.019 ] + }, + { + "time": 0.6333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.705, 0.991, 0.818, 1.019, 0.705, 1.019, 0.837, 0.992 ] + }, + { + "time": 0.9, + "x": 1.019, + "y": 0.992, + "curve": [ 0.956, 1.019, 0.955, 1, 0.983, 0.991, 0.955, 1 ] + }, + { "time": 1 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 41.41, + "curve": [ 0.033, 41.52, 0.075, 57.36 ] + }, + { + "time": 0.1, + "value": 57.36, + "curve": [ 0.142, 57.36, 0.249, 30.8 ] + }, + { + "time": 0.2667, + "value": 26.81, + "curve": [ 0.314, 16.08, 0.378, 5.4 ] + }, + { + "time": 0.4, + "value": 2.75, + "curve": [ 0.455, -3.75, 0.54, -12.39 ] + }, + { + "time": 0.6, + "value": -12.39, + "curve": [ 0.633, -12.39, 0.722, 21.07 ] + }, + { + "time": 0.7333, + "value": 25.71, + "curve": [ 0.751, 32.81, 0.824, 63.52 ] + }, + { + "time": 0.8667, + "value": 63.79, + "curve": [ 0.913, 64.09, 0.948, 41.49 ] + }, + { "time": 1, "value": 41.41 } + ], + "translate": [ + { + "x": 17.15, + "y": -0.09, + "curve": [ 0.178, 17.14, 0.295, -4.26, 0.009, -0.09, 0.475, 0.02 ] + }, + { + "time": 0.5, + "x": -4.26, + "y": 0.02, + "curve": [ 0.705, -4.27, 0.875, 17.16, 0.525, 0.02, 0.875, -0.09 ] + }, + { "time": 1, "x": 17.15, "y": -0.09 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": -40.72, + "curve": [ 0.026, -42.96, 0.075, -43 ] + }, + { + "time": 0.1, + "value": -43, + "curve": [ 0.142, -43, 0.239, 8.23 ] + }, + { + "time": 0.2667, + "value": 18.99, + "curve": [ 0.284, 25.64, 0.367, 38.72 ] + }, + { + "time": 0.4, + "value": 38.72, + "curve": [ 0.425, 38.72, 0.475, 18.7 ] + }, + { + "time": 0.5, + "value": 18.7, + "curve": [ 0.525, 18.7, 0.575, 31.73 ] + }, + { + "time": 0.6, + "value": 31.73, + "curve": [ 0.633, 31.73, 0.719, 15.2 ] + }, + { + "time": 0.7333, + "value": 11.21, + "curve": [ 0.767, 2.12, 0.851, -15.29 ] + }, + { + "time": 0.8667, + "value": -18.46, + "curve": [ 0.905, -26.32, 0.951, -35.33 ] + }, + { "time": 1, "value": -40.72 } + ], + "translate": [ + { + "x": -17.71, + "y": -4.63, + "curve": [ 0.028, -19.31, 0.04, -20.22, 0.027, -4.63, 0.036, 1.71 ] + }, + { + "time": 0.0667, + "x": -20.72, + "y": 1.6, + "curve": [ 0.082, -21, 0.087, -20.93, 0.082, 1.54, 0.091, 0.29 ] + }, + { + "time": 0.1, + "x": -20.95, + "y": 0.06, + "curve": [ 0.162, -21.05, 0.4, 7.79, 0.194, -2.43, 0.4, -1.9 ] + }, + { + "time": 0.5, + "x": 7.79, + "y": -1.94, + "curve": [ 0.519, 7.78, 0.542, 7.33, 0.517, -1.94, 0.54, 5.55 ] + }, + { + "time": 0.5667, + "x": 6.45, + "y": 5.4, + "curve": [ 0.587, 5.74, 0.721, -0.95, 0.587, 5.28, 0.732, -3.74 ] + }, + { + "time": 0.7667, + "x": -3.61, + "y": -4.14, + "curve": [ 0.855, -8.76, 0.942, -14.37, 0.814, -4.69, 0.944, -4.63 ] + }, + { "time": 1, "x": -17.71, "y": -4.63 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -14.27, + "curve": [ 0.021, -18.08, 0.058, -19.4 ] + }, + { + "time": 0.1, + "value": -19.4, + "curve": [ 0.238, -19.69, 0.337, 7.78 ] + }, + { + "time": 0.3667, + "value": 16.2, + "curve": [ 0.399, 25.42, 0.497, 60.19 ] + }, + { + "time": 0.6, + "value": 60.26, + "curve": [ 0.719, 60.13, 0.845, 27.61 ] + }, + { + "time": 0.8667, + "value": 22.45, + "curve": [ 0.892, 16.38, 0.967, -8.36 ] + }, + { "time": 1, "value": -14.27 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 13.57, + "curve": [ 0.022, 9.71, 0.147, -15.4 ] + }, + { + "time": 0.3667, + "value": -15.3, + "curve": [ 0.457, -15.28, 0.635, 30.8 ] + }, + { + "time": 0.8, + "value": 30.92, + "curve": [ 0.894, 30.82, 0.98, 18.35 ] + }, + { "time": 1, "value": 13.57 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -28.72, + "curve": [ 0.024, -31.74, 0.176, -43.4 ] + }, + { + "time": 0.3667, + "value": -43.6, + "curve": [ 0.403, -43.65, 0.47, -40.15 ] + }, + { + "time": 0.5, + "value": -35.63, + "curve": [ 0.547, -28.59, 0.624, -4.57 ] + }, + { + "time": 0.7333, + "value": -4.59, + "curve": [ 0.891, -4.62, 0.954, -24.28 ] + }, + { "time": 1, "value": -28.48 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.034, 30.94, 0.068, 32.05 ] + }, + { + "time": 0.1, + "value": 31.88, + "curve": [ 0.194, 31.01, 0.336, -0.11 ] + }, + { + "time": 0.3667, + "value": -7.11, + "curve": [ 0.421, -19.73, 0.53, -46.21 ] + }, + { + "time": 0.6, + "value": -45.75, + "curve": [ 0.708, -45.03, 0.844, -13.56 ] + }, + { + "time": 0.8667, + "value": -6.48, + "curve": [ 0.909, 6.59, 0.958, 24.21 ] + }, + { "time": 1, "value": 28.28 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.06, + "curve": [ 0.044, 11.16, 0.063, 11.49 ] + }, + { + "time": 0.1, + "value": 11.49, + "curve": [ 0.215, 11.49, 0.336, 2.92 ] + }, + { + "time": 0.3667, + "value": 0.84, + "curve": [ 0.416, -2.52, 0.498, -10.84 ] + }, + { + "time": 0.6, + "value": -10.83, + "curve": [ 0.762, -10.71, 0.845, -3.05 ] + }, + { + "time": 0.8667, + "value": -1.34, + "curve": [ 0.917, 2.54, 0.977, 8.81 ] + }, + { "time": 1, "value": 10.06 } + ] + }, + "gun": { + "rotate": [ + { + "value": -14.67, + "curve": [ 0.086, -14.67, 0.202, 8.31 ] + }, + { + "time": 0.2333, + "value": 12.14, + "curve": [ 0.279, 17.71, 0.391, 25.79 ] + }, + { + "time": 0.5, + "value": 25.77, + "curve": [ 0.631, 25.74, 0.694, 4.53 ] + }, + { + "time": 0.7333, + "value": -0.65, + "curve": [ 0.768, -5.21, 0.902, -14.4 ] + }, + { "time": 1, "value": -14.67 } + ] + }, + "gun-tip": { + "rotate": [ + { "time": 0.2333, "value": 0.11 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": 26.22 }, + { + "time": 0.0333, + "value": 28.94, + "curve": [ 0.05, 28.94, 0.081, 17.62 ] + }, + { + "time": 0.1, + "value": 12.68, + "curve": [ 0.121, 7.25, 0.239, -22.96 ] + }, + { + "time": 0.2667, + "value": -26.31, + "curve": [ 0.299, -30.12, 0.364, -35.52 ] + }, + { + "time": 0.4, + "value": -35.38, + "curve": [ 0.418, -35.31, 0.485, 1.14 ] + }, + { + "time": 0.5, + "value": 6.17, + "curve": [ 0.503, 7.08, 0.519, 11.27 ] + }, + { + "time": 0.5333, + "value": 11.15, + "curve": [ 0.545, 11.06, 0.552, 11.27 ] + }, + { "time": 0.5667, "value": 3.69 }, + { "time": 0.6, "value": 3.55 }, + { "time": 0.7, "value": 10.77 }, + { "time": 1, "value": 26.22 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -6.79, + "curve": [ 0.028, -6.79, 0.087, -49.32 ] + }, + { + "time": 0.1, + "value": -51.42, + "curve": [ 0.109, -52.92, 0.137, -55.37 ] + }, + { + "time": 0.1667, + "value": -55.35, + "curve": [ 0.188, -55.34, 0.238, -44.96 ] + }, + { + "time": 0.2667, + "value": -40.55, + "curve": [ 0.284, -37.93, 0.365, -23.14 ] + }, + { + "time": 0.4333, + "value": -22.85, + "curve": [ 0.524, -22.46, 0.585, -48.24 ] + }, + { + "time": 0.6, + "value": -54.5, + "curve": [ 0.618, -61.64, 0.714, -97.51 ] + }, + { + "time": 0.7333, + "value": -102.65, + "curve": [ 0.749, -106.84, 0.768, -109.78 ] + }, + { + "time": 0.8, + "value": -109.78, + "curve": [ 0.818, -109.78, 0.859, -94.44 ] + }, + { + "time": 0.8667, + "value": -87.74, + "curve": [ 0.874, -81.52, 0.969, -6.79 ] + }, + { "time": 1, "value": -6.79 } + ], + "scale": [ + {}, + { "time": 0.0333, "x": 0.983 }, + { "time": 0.1, "x": 0.967, "y": 0.981 }, + { "time": 0.4333 }, + { "time": 0.5333, "x": 0.958, "y": 0.951 }, + { "time": 0.6333 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": 6.84, + "curve": [ 0.025, 6.84, 0.093, -24.57 ] + }, + { + "time": 0.1, + "value": -28.08, + "curve": [ 0.121, -38.52, 0.204, -92.35 ] + }, + { + "time": 0.2667, + "value": -91.68, + "curve": [ 0.309, -91.22, 0.379, -77.62 ] + }, + { + "time": 0.4, + "value": -68.91, + "curve": [ 0.43, -56.58, 0.474, 2.28 ] + }, + { + "time": 0.5, + "value": 2.63, + "curve": [ 0.538, 3.15, 0.567, -35.43 ] + }, + { + "time": 0.6, + "value": -35.18, + "curve": [ 0.634, -34.93, 0.665, -34.17 ] + }, + { + "time": 0.7, + "value": -30.64, + "curve": [ 0.718, -28.79, 0.857, -8.34 ] + }, + { + "time": 0.8667, + "value": -6.83, + "curve": [ 0.915, 0.75, 0.967, 6.84 ] + }, + { "time": 1, "value": 6.84 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 2.73, + "curve": [ 0.013, 4.28, 0.019, 5.27 ] + }, + { + "time": 0.0333, + "value": 5.15, + "curve": [ 0.045, 5.05, 0.063, -4.11 ] + }, + { + "time": 0.0667, + "value": -6.67, + "curve": [ 0.111, -6.72, 0.148, 3.78 ] + }, + { "time": 0.1667, "value": 4.67 }, + { "time": 0.2667, "value": 7.06 }, + { "time": 0.3333, "value": 8.97 }, + { "time": 0.4, "value": 11.15 }, + { + "time": 0.5333, + "value": 21.62, + "curve": [ 0.572, 21.62, 0.587, 17.19 ] + }, + { + "time": 0.6, + "value": 13.77, + "curve": [ 0.639, 3.33, 0.713, -20.85 ] + }, + { + "time": 0.7333, + "value": -27.3, + "curve": [ 0.757, -34.54, 0.766, -37.13 ] + }, + { + "time": 0.8, + "value": -38.01, + "curve": [ 0.828, -38.72, 0.976, -2.16 ] + }, + { "time": 1, "value": 2.73 } + ] + } + }, + "events": [ + { "name": "footstep" }, + { "time": 0.5333, "name": "footstep" } + ] + } +} +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-ess.skel b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-ess.skel new file mode 100644 index 0000000..198f0f3 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-ess.skel differ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-pma.atlas b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-pma.atlas new file mode 100644 index 0000000..9c8bd8e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-pma.atlas @@ -0,0 +1,102 @@ +spineboy-pma.png + size: 1024, 256 + filter: Linear, Linear + pma: true + scale: 0.5 +crosshair + bounds: 813, 160, 45, 45 +eye-indifferent + bounds: 569, 2, 47, 45 +eye-surprised + bounds: 643, 7, 47, 45 + rotate: 90 +front-bracer + bounds: 811, 51, 29, 40 +front-fist-closed + bounds: 807, 93, 38, 41 +front-fist-open + bounds: 815, 210, 43, 44 +front-foot + bounds: 706, 64, 63, 35 + rotate: 90 +front-shin + bounds: 80, 11, 41, 92 +front-thigh + bounds: 754, 12, 23, 56 +front-upper-arm + bounds: 618, 5, 23, 49 +goggles + bounds: 214, 20, 131, 83 +gun + bounds: 347, 14, 105, 102 + rotate: 90 +head + bounds: 80, 105, 136, 149 +hoverboard-board + bounds: 2, 8, 246, 76 + rotate: 90 +hoverboard-thruster + bounds: 478, 2, 30, 32 +hoverglow-small + bounds: 218, 117, 137, 38 + rotate: 90 +mouth-grind + bounds: 775, 80, 47, 30 + rotate: 90 +mouth-oooo + bounds: 779, 31, 47, 30 + rotate: 90 +mouth-smile + bounds: 783, 207, 47, 30 + rotate: 90 +muzzle-glow + bounds: 779, 4, 25, 25 +muzzle-ring + bounds: 451, 14, 25, 105 +muzzle01 + bounds: 664, 60, 67, 40 + rotate: 90 +muzzle02 + bounds: 580, 56, 68, 42 + rotate: 90 +muzzle03 + bounds: 478, 36, 83, 53 + rotate: 90 +muzzle04 + bounds: 533, 49, 75, 45 + rotate: 90 +muzzle05 + bounds: 624, 56, 68, 38 + rotate: 90 +neck + bounds: 806, 8, 18, 21 +portal-bg + bounds: 258, 121, 133, 133 +portal-flare1 + bounds: 690, 2, 56, 30 + rotate: 90 +portal-flare2 + bounds: 510, 3, 57, 31 +portal-flare3 + bounds: 722, 4, 58, 30 + rotate: 90 +portal-shade + bounds: 393, 121, 133, 133 +portal-streaks1 + bounds: 528, 126, 126, 128 +portal-streaks2 + bounds: 656, 129, 125, 125 +rear-bracer + bounds: 826, 13, 28, 36 +rear-foot + bounds: 743, 70, 57, 30 + rotate: 90 +rear-shin + bounds: 174, 14, 38, 89 +rear-thigh + bounds: 783, 158, 28, 47 +rear-upper-arm + bounds: 783, 136, 20, 44 + rotate: 90 +torso + bounds: 123, 13, 49, 90 diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-pma.png b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-pma.png new file mode 100644 index 0000000..1f322d0 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-pma.png differ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-pro.json b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-pro.json new file mode 100644 index 0000000..78ba1dc --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-pro.json @@ -0,0 +1,8707 @@ +{ +"skeleton": { + "hash": "itfFESDjM1c", + "spine": "4.1.17", + "x": -188.63, + "y": -7.94, + "width": 418.45, + "height": 686.2, + "images": "./images/", + "audio": "" +}, +"bones": [ + { "name": "root", "rotation": 0.05 }, + { "name": "hip", "parent": "root", "y": 247.27 }, + { "name": "crosshair", "parent": "root", "x": 302.83, "y": 569.45, "color": "ff3f00ff" }, + { + "name": "aim-constraint-target", + "parent": "hip", + "length": 26.24, + "rotation": 19.61, + "x": 1.02, + "y": 5.62, + "color": "abe323ff" + }, + { "name": "rear-foot-target", "parent": "root", "x": 61.91, "y": 0.42, "color": "ff3f00ff" }, + { "name": "rear-leg-target", "parent": "rear-foot-target", "x": -33.91, "y": 37.34, "color": "ff3f00ff" }, + { + "name": "rear-thigh", + "parent": "hip", + "length": 85.72, + "rotation": -72.54, + "x": 8.91, + "y": -5.63, + "color": "ff000dff" + }, + { + "name": "rear-shin", + "parent": "rear-thigh", + "length": 121.88, + "rotation": -19.83, + "x": 86.1, + "y": -1.33, + "color": "ff000dff" + }, + { + "name": "rear-foot", + "parent": "rear-shin", + "length": 51.58, + "rotation": 45.78, + "x": 121.46, + "y": -0.76, + "color": "ff000dff" + }, + { + "name": "back-foot-tip", + "parent": "rear-foot", + "length": 50.3, + "rotation": -0.85, + "x": 51.17, + "y": 0.24, + "transform": "noRotationOrReflection", + "color": "ff000dff" + }, + { "name": "board-ik", "parent": "root", "x": -131.78, "y": 69.09, "color": "4c56ffff" }, + { "name": "clipping", "parent": "root" }, + { "name": "hoverboard-controller", "parent": "root", "rotation": -0.28, "x": -329.69, "y": 69.82, "color": "ff0004ff" }, + { "name": "exhaust1", "parent": "hoverboard-controller", "rotation": 3.02, "x": -249.68, "y": 53.39 }, + { "name": "exhaust2", "parent": "hoverboard-controller", "rotation": 26.34, "x": -191.6, "y": -22.92 }, + { + "name": "exhaust3", + "parent": "hoverboard-controller", + "rotation": -12.34, + "x": -236.03, + "y": 80.54, + "scaleX": 0.7847, + "scaleY": 0.7847 + }, + { "name": "portal-root", "parent": "root", "x": 12.9, "y": 328.54, "scaleX": 2.0334, "scaleY": 2.0334 }, + { "name": "flare1", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare10", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare2", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare3", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare4", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare5", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare6", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare7", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare8", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare9", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { + "name": "torso", + "parent": "hip", + "length": 42.52, + "rotation": 103.82, + "x": -1.62, + "y": 4.9, + "color": "e0da19ff" + }, + { "name": "torso2", "parent": "torso", "length": 42.52, "x": 42.52, "color": "e0da19ff" }, + { "name": "torso3", "parent": "torso2", "length": 42.52, "x": 42.52, "color": "e0da19ff" }, + { "name": "front-shoulder", "parent": "torso3", "rotation": 255.89, "x": 18.72, "y": 19.33, "color": "00ff04ff" }, + { "name": "front-upper-arm", "parent": "front-shoulder", "length": 69.45, "rotation": -87.51, "color": "00ff04ff" }, + { + "name": "front-bracer", + "parent": "front-upper-arm", + "length": 40.57, + "rotation": 18.3, + "x": 68.8, + "y": -0.68, + "color": "00ff04ff" + }, + { + "name": "front-fist", + "parent": "front-bracer", + "length": 65.39, + "rotation": 12.43, + "x": 40.57, + "y": 0.2, + "color": "00ff04ff" + }, + { "name": "front-foot-target", "parent": "root", "x": -13.53, "y": 0.04, "color": "ff3f00ff" }, + { "name": "front-leg-target", "parent": "front-foot-target", "x": -28.4, "y": 29.06, "color": "ff3f00ff" }, + { + "name": "front-thigh", + "parent": "hip", + "length": 74.81, + "rotation": -95.51, + "x": -17.46, + "y": -11.64, + "color": "00ff04ff" + }, + { + "name": "front-shin", + "parent": "front-thigh", + "length": 128.77, + "rotation": -2.21, + "x": 78.69, + "y": 1.6, + "color": "00ff04ff" + }, + { + "name": "front-foot", + "parent": "front-shin", + "length": 41.01, + "rotation": 51.27, + "x": 128.76, + "y": -0.34, + "color": "00ff04ff" + }, + { + "name": "front-foot-tip", + "parent": "front-foot", + "length": 56.03, + "rotation": -1.68, + "x": 41.42, + "y": -0.09, + "transform": "noRotationOrReflection", + "color": "00ff04ff" + }, + { "name": "back-shoulder", "parent": "torso3", "rotation": -104.11, "x": 7.32, "y": -19.22, "color": "ff000dff" }, + { "name": "rear-upper-arm", "parent": "back-shoulder", "length": 51.94, "rotation": -65.45, "color": "ff000dff" }, + { "name": "rear-bracer", "parent": "rear-upper-arm", "length": 34.56, "rotation": 23.15, "x": 51.36, "color": "ff000dff" }, + { + "name": "gun", + "parent": "rear-bracer", + "length": 43.11, + "rotation": -5.43, + "x": 34.42, + "y": -0.45, + "color": "ff000dff" + }, + { "name": "gun-tip", "parent": "gun", "rotation": 7.1, "x": 200.78, "y": 52.5, "color": "ff0000ff" }, + { + "name": "neck", + "parent": "torso3", + "length": 25.45, + "rotation": -31.54, + "x": 42.46, + "y": -0.31, + "color": "e0da19ff" + }, + { + "name": "head", + "parent": "neck", + "length": 131.79, + "rotation": 26.1, + "x": 27.66, + "y": -0.26, + "color": "e0da19ff" + }, + { + "name": "hair1", + "parent": "head", + "length": 47.23, + "rotation": -49.1, + "x": 149.83, + "y": -59.77, + "color": "e0da19ff" + }, + { + "name": "hair2", + "parent": "hair1", + "length": 55.57, + "rotation": 50.42, + "x": 47.23, + "y": 0.19, + "color": "e0da19ff" + }, + { + "name": "hair3", + "parent": "head", + "length": 62.22, + "rotation": -32.17, + "x": 164.14, + "y": 3.68, + "color": "e0da19ff" + }, + { + "name": "hair4", + "parent": "hair3", + "length": 80.28, + "rotation": 83.71, + "x": 62.22, + "y": -0.04, + "color": "e0da19ff" + }, + { "name": "hoverboard-thruster-front", "parent": "hoverboard-controller", "rotation": -29.2, "x": 95.77, "y": -2.99, "transform": "noRotationOrReflection" }, + { "name": "hoverboard-thruster-rear", "parent": "hoverboard-controller", "rotation": -29.2, "x": -76.47, "y": -4.88, "transform": "noRotationOrReflection" }, + { "name": "hoverglow-front", "parent": "hoverboard-thruster-front", "rotation": 0.17, "x": -1.78, "y": -37.79 }, + { "name": "hoverglow-rear", "parent": "hoverboard-thruster-rear", "rotation": 0.17, "x": 1.06, "y": -35.66 }, + { "name": "muzzle", "parent": "rear-bracer", "rotation": 3.06, "x": 242.34, "y": 34.26, "color": "ffb900ff" }, + { "name": "muzzle-ring", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring2", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring3", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring4", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "portal", "parent": "portal-root" }, + { "name": "portal-shade", "parent": "portal-root" }, + { "name": "portal-streaks1", "parent": "portal-root" }, + { "name": "portal-streaks2", "parent": "portal-root" }, + { "name": "side-glow1", "parent": "hoverboard-controller", "x": -110.56, "y": 2.62, "color": "000effff" }, + { + "name": "side-glow2", + "parent": "hoverboard-controller", + "x": -110.56, + "y": 2.62, + "scaleX": 0.738, + "scaleY": 0.738, + "color": "000effff" + }, + { "name": "head-control", "parent": "head", "x": 110.21, "color": "00a220ff" } +], +"slots": [ + { "name": "portal-bg", "bone": "portal" }, + { "name": "portal-shade", "bone": "portal-shade" }, + { "name": "portal-streaks2", "bone": "portal-streaks2", "blend": "additive" }, + { "name": "portal-streaks1", "bone": "portal-streaks1", "blend": "additive" }, + { "name": "portal-flare8", "bone": "flare8", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare9", "bone": "flare9", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare10", "bone": "flare10", "color": "c3cbffff", "blend": "additive" }, + { "name": "clipping", "bone": "clipping" }, + { "name": "exhaust3", "bone": "exhaust3", "color": "5eb4ffff", "blend": "additive" }, + { "name": "hoverboard-thruster-rear", "bone": "hoverboard-thruster-rear" }, + { "name": "hoverboard-thruster-front", "bone": "hoverboard-thruster-front" }, + { "name": "hoverboard-board", "bone": "hoverboard-controller" }, + { "name": "side-glow1", "bone": "side-glow1", "color": "ff8686ff", "blend": "additive" }, + { "name": "side-glow3", "bone": "side-glow1", "color": "ff8686ff", "blend": "additive" }, + { "name": "side-glow2", "bone": "side-glow2", "color": "ff8686ff", "blend": "additive" }, + { "name": "hoverglow-front", "bone": "hoverglow-front", "color": "5eb4ffff", "blend": "additive" }, + { "name": "hoverglow-rear", "bone": "hoverglow-rear", "color": "5eb4ffff", "blend": "additive" }, + { "name": "exhaust1", "bone": "exhaust2", "color": "5eb4ffff", "blend": "additive" }, + { "name": "exhaust2", "bone": "exhaust1", "color": "5eb4ffff", "blend": "additive" }, + { "name": "rear-upper-arm", "bone": "rear-upper-arm", "attachment": "rear-upper-arm" }, + { "name": "rear-bracer", "bone": "rear-bracer", "attachment": "rear-bracer" }, + { "name": "gun", "bone": "gun", "attachment": "gun" }, + { "name": "rear-foot", "bone": "rear-foot", "attachment": "rear-foot" }, + { "name": "rear-thigh", "bone": "rear-thigh", "attachment": "rear-thigh" }, + { "name": "rear-shin", "bone": "rear-shin", "attachment": "rear-shin" }, + { "name": "neck", "bone": "neck", "attachment": "neck" }, + { "name": "torso", "bone": "torso", "attachment": "torso" }, + { "name": "front-upper-arm", "bone": "front-upper-arm", "attachment": "front-upper-arm" }, + { "name": "head", "bone": "head", "attachment": "head" }, + { "name": "eye", "bone": "head", "attachment": "eye-indifferent" }, + { "name": "front-thigh", "bone": "front-thigh", "attachment": "front-thigh" }, + { "name": "front-foot", "bone": "front-foot", "attachment": "front-foot" }, + { "name": "front-shin", "bone": "front-shin", "attachment": "front-shin" }, + { "name": "mouth", "bone": "head", "attachment": "mouth-smile" }, + { "name": "goggles", "bone": "head", "attachment": "goggles" }, + { "name": "front-bracer", "bone": "front-bracer", "attachment": "front-bracer" }, + { "name": "front-fist", "bone": "front-fist", "attachment": "front-fist-closed" }, + { "name": "muzzle", "bone": "muzzle" }, + { "name": "head-bb", "bone": "head" }, + { "name": "portal-flare1", "bone": "flare1", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare2", "bone": "flare2", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare3", "bone": "flare3", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare4", "bone": "flare4", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare5", "bone": "flare5", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare6", "bone": "flare6", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare7", "bone": "flare7", "color": "c3cbffff", "blend": "additive" }, + { "name": "crosshair", "bone": "crosshair" }, + { "name": "muzzle-glow", "bone": "gun-tip", "color": "ffffff00", "blend": "additive" }, + { "name": "muzzle-ring", "bone": "muzzle-ring", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring2", "bone": "muzzle-ring2", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring3", "bone": "muzzle-ring3", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring4", "bone": "muzzle-ring4", "color": "d8baffff", "blend": "additive" } +], +"ik": [ + { + "name": "aim-ik", + "order": 13, + "bones": [ "rear-upper-arm" ], + "target": "crosshair", + "mix": 0 + }, + { + "name": "aim-torso-ik", + "order": 8, + "bones": [ "aim-constraint-target" ], + "target": "crosshair" + }, + { + "name": "board-ik", + "order": 1, + "bones": [ "hoverboard-controller" ], + "target": "board-ik" + }, + { + "name": "front-foot-ik", + "order": 6, + "bones": [ "front-foot" ], + "target": "front-foot-target" + }, + { + "name": "front-leg-ik", + "order": 4, + "bones": [ "front-thigh", "front-shin" ], + "target": "front-leg-target", + "bendPositive": false + }, + { + "name": "rear-foot-ik", + "order": 7, + "bones": [ "rear-foot" ], + "target": "rear-foot-target" + }, + { + "name": "rear-leg-ik", + "order": 5, + "bones": [ "rear-thigh", "rear-shin" ], + "target": "rear-leg-target", + "bendPositive": false + } +], +"transform": [ + { + "name": "aim-front-arm-transform", + "order": 11, + "bones": [ "front-upper-arm" ], + "target": "aim-constraint-target", + "rotation": -180, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "aim-head-transform", + "order": 10, + "bones": [ "head" ], + "target": "aim-constraint-target", + "rotation": 84.3, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "aim-rear-arm-transform", + "order": 12, + "bones": [ "rear-upper-arm" ], + "target": "aim-constraint-target", + "x": 57.7, + "y": 56.4, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "aim-torso-transform", + "order": 9, + "bones": [ "torso" ], + "target": "aim-constraint-target", + "rotation": 69.5, + "shearY": -36, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "front-foot-board-transform", + "order": 2, + "bones": [ "front-foot-target" ], + "target": "hoverboard-controller", + "x": -69.8, + "y": 20.7, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "rear-foot-board-transform", + "order": 3, + "bones": [ "rear-foot-target" ], + "target": "hoverboard-controller", + "x": 86.6, + "y": 21.3, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "shoulder", + "bones": [ "back-shoulder" ], + "target": "front-shoulder", + "x": 40.17, + "y": -1.66, + "mixRotate": 0, + "mixX": -1, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "toes-board", + "order": 14, + "bones": [ "front-foot-tip", "back-foot-tip" ], + "target": "hoverboard-controller", + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + } +], +"skins": [ + { + "name": "default", + "attachments": { + "clipping": { + "clipping": { + "type": "clipping", + "end": "head-bb", + "vertexCount": 9, + "vertices": [ 66.76, 509.48, 19.98, 434.54, 5.34, 336.28, 22.19, 247.93, 77.98, 159.54, 182.21, -97.56, 1452.26, -99.8, 1454.33, 843.61, 166.57, 841.02 ], + "color": "ce3a3aff" + } + }, + "crosshair": { + "crosshair": { "width": 89, "height": 89 } + }, + "exhaust1": { + "hoverglow-small": { "scaleX": 0.4629, "scaleY": 0.8129, "rotation": -83.07, "width": 274, "height": 75 } + }, + "exhaust2": { + "hoverglow-small": { + "x": 0.01, + "y": -0.76, + "scaleX": 0.4208, + "scaleY": 0.8403, + "rotation": -89.25, + "width": 274, + "height": 75 + } + }, + "exhaust3": { + "hoverglow-small": { "scaleX": 0.4629, "scaleY": 0.8129, "rotation": -83.07, "width": 274, "height": 75 } + }, + "eye": { + "eye-indifferent": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 66, -36.8, -91.35, 0.3, 46, 73.41, -91.35, 0.7, 2, 66, -87.05, -13.11, 0.70968, 46, 23.16, -13.11, 0.29032, 2, 66, -12.18, 34.99, 0.82818, 46, 98.03, 34.99, 0.17182, 2, 66, 38.07, -43.25, 0.59781, 46, 148.28, -43.25, 0.40219 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 89 + }, + "eye-surprised": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 2, 66, -46.74, -89.7, 0.3, 46, 63.47, -89.7, 0.7, 2, 66, -77.58, -1.97, 0.71, 46, 32.63, -1.97, 0.29, 2, 66, 6.38, 27.55, 0.83, 46, 116.59, 27.55, 0.17, 2, 66, 37.22, -60.19, 0.6, 46, 147.44, -60.19, 0.4 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 89 + } + }, + "front-bracer": { + "front-bracer": { "x": 12.03, "y": -1.68, "rotation": 79.6, "width": 58, "height": 80 } + }, + "front-fist": { + "front-fist-closed": { "x": 35.5, "y": 6, "rotation": 67.16, "width": 75, "height": 82 }, + "front-fist-open": { "x": 39.57, "y": 7.76, "rotation": 67.16, "width": 86, "height": 87 } + }, + "front-foot": { + "front-foot": { + "type": "mesh", + "uvs": [ 0.59417, 0.23422, 0.62257, 0.30336, 0.6501, 0.37036, 0.67637, 0.38404, 0.72068, 0.4071, 0.76264, 0.42894, 1, 0.70375, 1, 1, 0.65517, 1, 0.46923, 0.99999, 0, 1, 0, 0.39197, 0.17846, 0, 0.49796, 0 ], + "triangles": [ 8, 9, 3, 4, 8, 3, 5, 8, 4, 6, 8, 5, 8, 6, 7, 11, 1, 10, 0, 12, 13, 0, 11, 12, 0, 1, 11, 9, 2, 3, 1, 2, 10, 9, 10, 2 ], + "vertices": [ 2, 38, 18.17, 41.57, 0.7896, 39, 12.46, 46.05, 0.2104, 2, 38, 24.08, 40.76, 0.71228, 39, 16.12, 41.34, 0.28772, 2, 38, 29.81, 39.98, 0.55344, 39, 19.67, 36.78, 0.44656, 2, 38, 32.81, 41.67, 0.38554, 39, 23, 35.89, 0.61446, 2, 38, 37.86, 44.52, 0.25567, 39, 28.61, 34.4, 0.74433, 2, 38, 42.65, 47.22, 0.17384, 39, 33.92, 32.99, 0.82616, 1, 39, 64.15, 14.56, 1, 1, 39, 64.51, -5.87, 1, 1, 39, 21.08, -6.64, 1, 2, 38, 44.67, -6.77, 0.5684, 39, -2.34, -6.97, 0.4316, 1, 38, 3.1, -48.81, 1, 1, 38, -26.73, -19.31, 1, 1, 38, -30.15, 15.69, 1, 1, 38, -1.84, 44.32, 1 ], + "hull": 14, + "edges": [ 14, 16, 16, 18, 18, 20, 4, 18, 20, 22, 24, 26, 22, 24, 12, 14, 10, 12, 2, 4, 2, 20, 4, 6, 6, 16, 2, 0, 0, 26, 6, 8, 8, 10 ], + "width": 126, + "height": 69 + } + }, + "front-shin": { + "front-shin": { + "type": "mesh", + "uvs": [ 0.90031, 0.05785, 1, 0.12828, 1, 0.21619, 0.9025, 0.31002, 0.78736, 0.35684, 0.78081, 0.39874, 0.77215, 0.45415, 0.77098, 0.51572, 0.84094, 0.63751, 0.93095, 0.7491, 0.95531, 0.7793, 0.78126, 0.87679, 0.5613, 1, 0.2687, 1, 0, 1, 0.00279, 0.96112, 0.01358, 0.81038, 0.02822, 0.60605, 0.08324, 0.45142, 0.18908, 0.31882, 0.29577, 0.2398, 0.30236, 0.14941, 0.37875, 0.05902, 0.53284, 0, 0.70538, 0, 0.41094, 0.71968, 0.40743, 0.54751, 0.41094, 0.4536, 0.4724, 0.35186, 0.33367, 0.27829, 0.50226, 0.31664, 0.65328, 0.67507, 0.60762, 0.52716, 0.6006, 0.45125, 0.62747, 0.37543, 0.6573, 0.3385, 0.27843, 0.32924, 0.18967, 0.45203, 0.16509, 0.58586, 0.18265, 0.7682, 0.50532, 0.24634, 0.59473, 0.17967, 0.60161, 0.10611, 0.51392, 0.04327, 0.72198, 0.28849, 0.82343, 0.20266, 0.86814, 0.11377, 0.79592, 0.04634, 0.44858, 0.15515, 0.25466, 0.96219, 0.53169, 0.9448, 0.7531, 0.8324 ], + "triangles": [ 24, 0, 47, 43, 23, 24, 47, 43, 24, 43, 22, 23, 42, 43, 47, 46, 47, 0, 42, 47, 46, 46, 0, 1, 48, 22, 43, 48, 43, 42, 21, 22, 48, 41, 48, 42, 45, 42, 46, 41, 42, 45, 46, 1, 2, 45, 46, 2, 40, 48, 41, 48, 20, 21, 29, 48, 40, 29, 20, 48, 44, 41, 45, 40, 41, 44, 3, 45, 2, 44, 45, 3, 30, 29, 40, 35, 30, 40, 36, 19, 20, 36, 20, 29, 44, 35, 40, 28, 29, 30, 4, 44, 3, 35, 44, 4, 34, 30, 35, 5, 35, 4, 34, 28, 30, 33, 28, 34, 37, 19, 36, 18, 19, 37, 27, 29, 28, 27, 28, 33, 36, 29, 27, 37, 36, 27, 5, 34, 35, 6, 34, 5, 33, 34, 6, 6, 32, 33, 7, 32, 6, 26, 37, 27, 38, 18, 37, 38, 37, 26, 17, 18, 38, 31, 32, 7, 31, 7, 8, 32, 25, 26, 38, 26, 25, 27, 33, 32, 32, 26, 27, 39, 38, 25, 17, 38, 39, 16, 17, 39, 51, 31, 8, 51, 8, 9, 11, 51, 9, 11, 9, 10, 31, 50, 25, 31, 25, 32, 50, 31, 51, 49, 39, 25, 49, 25, 50, 15, 16, 39, 49, 15, 39, 13, 49, 50, 14, 15, 49, 13, 14, 49, 12, 50, 51, 12, 51, 11, 13, 50, 12 ], + "vertices": [ -23.66, 19.37, -11.73, 28.98, 4.34, 30.83, 22.41, 24.87, 32.05, 16.48, 39.77, 16.83, 49.98, 17.3, 61.25, 18.5, 82.85, 26.78, 102.4, 36.46, 107.69, 39.09, 127.15, 26.97, 151.74, 11.65, 154.49, -12.18, 157.02, -34.07, 149.89, -34.66, 122.23, -36.97, 84.75, -40.09, 55.97, -38.88, 30.73, -33.05, 15.29, -26.03, -1.3, -27.41, -18.54, -23.09, -30.78, -11.79, -32.4, 2.27, 101.92, -6.52, 70.48, -10.44, 53.28, -12.14, 34.11, -9.28, 21.96, -22.13, 27.39, -7.59, 91.48, 12.28, 64.88, 5.44, 51.07, 3.26, 36.95, 3.85, 29.92, 5.5, 31.8, -25.56, 55.08, -30.19, 79.77, -29.37, 112.93, -24.09, 14.51, -8.83, 1.48, -2.95, -12.03, -3.94, -22.69, -12.41, 20.17, 9.71, 3.53, 16.16, -13.14, 17.93, -24.78, 10.62, -1.62, -15.37, 147.71, -14.13, 141.93, 8.07, 119.3, 23.74 ], + "hull": 25, + "edges": [ 8, 6, 6, 4, 4, 2, 2, 0, 0, 48, 46, 48, 46, 44, 44, 42, 42, 40, 40, 38, 38, 36, 36, 34, 32, 34, 50, 52, 52, 54, 54, 56, 40, 58, 58, 60, 8, 10, 20, 22, 22, 24, 62, 64, 64, 66, 66, 68, 8, 70, 70, 60, 68, 70, 58, 72, 72, 74, 74, 76, 76, 78, 24, 26, 26, 28, 58, 80, 80, 82, 82, 84, 84, 86, 86, 44, 70, 88, 88, 90, 90, 92, 92, 94, 94, 48, 80, 88, 88, 6, 82, 90, 90, 4, 84, 92, 92, 2, 86, 94, 94, 0, 56, 60, 10, 12, 12, 14, 14, 16, 28, 30, 30, 32, 26, 98, 98, 78, 30, 98, 24, 100, 100, 50, 98, 100, 22, 102, 102, 62, 100, 102, 16, 18, 18, 20, 102, 18 ], + "width": 82, + "height": 184 + } + }, + "front-thigh": { + "front-thigh": { "x": 42.48, "y": 4.45, "rotation": 84.87, "width": 45, "height": 112 } + }, + "front-upper-arm": { + "front-upper-arm": { "x": 28.31, "y": 7.37, "rotation": 97.9, "width": 46, "height": 97 } + }, + "goggles": { + "goggles": { + "type": "mesh", + "uvs": [ 0.53653, 0.04114, 0.72922, 0.16036, 0.91667, 0.33223, 0.97046, 0.31329, 1, 0.48053, 0.95756, 0.5733, 0.88825, 0.6328, 0.86878, 0.78962, 0.77404, 0.8675, 0.72628, 1, 0.60714, 0.93863, 0.49601, 0.88138, 0.41558, 0.75027, 0.32547, 0.70084, 0.2782, 0.58257, 0.1721, 0.63281, 0.17229, 0.75071, 0.10781, 0.79898, 0, 0.32304, 0, 0.12476, 0.07373, 0.07344, 0.15423, 0.10734, 0.23165, 0.13994, 0.30313, 0.02256, 0.34802, 0, 0.42979, 0.69183, 0.39476, 0.51042, 0.39488, 0.31512, 0.45878, 0.23198, 0.56501, 0.28109, 0.69961, 0.39216, 0.82039, 0.54204, 0.85738, 0.62343, 0.91107, 0.51407, 0.72639, 0.32147, 0.58764, 0.19609, 0.48075, 0.11269, 0.37823, 0.05501, 0.3287, 0.17866, 0.319, 0.305, 0.36036, 0.53799, 0.40327, 0.70072, 0.30059, 0.55838, 0.21957, 0.2815, 0.09963, 0.28943, 0.56863, 0.4368, 0.4911, 0.37156, 0.51185, 0.52093, 0.67018, 0.59304, 0.7619, 0.68575, 0.73296, 0.43355 ], + "triangles": [ 18, 44, 15, 21, 19, 20, 17, 18, 15, 44, 19, 21, 2, 3, 4, 18, 19, 44, 2, 33, 34, 33, 2, 4, 5, 33, 4, 5, 6, 33, 7, 32, 6, 31, 50, 33, 32, 31, 33, 6, 32, 33, 31, 49, 50, 49, 31, 32, 49, 32, 7, 8, 49, 7, 33, 50, 34, 17, 15, 16, 9, 48, 8, 49, 48, 50, 50, 48, 45, 47, 45, 48, 50, 45, 30, 45, 47, 46, 45, 46, 29, 30, 45, 29, 30, 29, 34, 30, 34, 50, 47, 26, 46, 25, 10, 11, 12, 25, 11, 41, 12, 42, 42, 44, 43, 43, 21, 22, 41, 40, 25, 41, 42, 40, 29, 35, 34, 40, 26, 25, 25, 26, 47, 37, 24, 0, 36, 37, 0, 42, 43, 39, 42, 39, 40, 28, 38, 36, 40, 39, 26, 28, 27, 38, 26, 39, 27, 37, 38, 23, 39, 43, 38, 38, 37, 36, 27, 39, 38, 43, 22, 38, 37, 23, 24, 22, 23, 38, 36, 0, 35, 28, 36, 35, 29, 28, 35, 27, 28, 46, 26, 27, 46, 35, 0, 1, 34, 35, 1, 12, 41, 25, 47, 10, 25, 44, 21, 43, 42, 14, 44, 14, 15, 44, 13, 14, 42, 12, 13, 42, 46, 28, 29, 47, 48, 10, 48, 9, 10, 49, 8, 48, 2, 34, 1 ], + "vertices": [ 2, 66, 61.88, 22.81, 0.832, 46, 172.09, 22.81, 0.168, 2, 66, 59.89, -31.19, 0.6855, 46, 170.1, -31.19, 0.3145, 2, 66, 49.2, -86.8, 0.32635, 46, 159.41, -86.8, 0.67365, 2, 66, 56.82, -99.01, 0.01217, 46, 167.03, -99.01, 0.98783, 1, 46, 143.4, -115.48, 1, 2, 66, 15, -110.14, 0.0041, 46, 125.21, -110.14, 0.9959, 2, 66, -0.32, -96.36, 0.07948, 46, 109.89, -96.36, 0.92052, 2, 66, -26.56, -100.19, 0.01905, 46, 83.65, -100.19, 0.98095, 2, 66, -46.96, -81.16, 0.4921, 46, 63.26, -81.16, 0.50791, 2, 66, -71.84, -76.69, 0.56923, 46, 38.37, -76.69, 0.43077, 2, 66, -72.54, -43.98, 0.74145, 46, 37.67, -43.98, 0.25855, 2, 66, -73.2, -13.47, 0.87929, 46, 37.01, -13.47, 0.12071, 2, 66, -59.63, 13.55, 0.864, 46, 50.58, 13.55, 0.136, 2, 66, -59.69, 38.45, 0.85289, 46, 50.52, 38.45, 0.14711, 2, 66, -45.26, 56.6, 0.74392, 46, 64.95, 56.6, 0.25608, 2, 66, -62.31, 79.96, 0.624, 46, 47.9, 79.96, 0.376, 2, 66, -80.76, 73.42, 0.616, 46, 29.45, 73.42, 0.384, 2, 66, -93.9, 86.64, 0.288, 46, 16.31, 86.64, 0.712, 1, 46, 81.51, 139.38, 1, 1, 46, 112.56, 150.3, 1, 2, 66, 16.76, 134.97, 0.02942, 46, 126.97, 134.97, 0.97058, 2, 66, 18.42, 113.28, 0.36147, 46, 128.63, 113.28, 0.63853, 2, 66, 20.02, 92.43, 0.7135, 46, 130.23, 92.43, 0.2865, 2, 66, 44.58, 81.29, 0.69603, 46, 154.79, 81.29, 0.30397, 2, 66, 52, 71.48, 0.848, 46, 162.21, 71.48, 0.152, 2, 66, -49.25, 13.27, 0.8, 46, 60.96, 13.27, 0.2, 2, 66, -23.88, 31.88, 0.896, 46, 86.33, 31.88, 0.104, 2, 66, 6.72, 42.6, 0.928, 46, 116.93, 42.6, 0.072, 2, 66, 25.26, 31.44, 0.8, 46, 135.47, 31.44, 0.2, 2, 66, 26.77, 2.59, 0.75, 46, 136.98, 2.59, 0.25, 2, 66, 21.02, -36.66, 0.54887, 46, 131.23, -36.66, 0.45113, 2, 66, 8.01, -74.65, 0.36029, 46, 118.22, -74.65, 0.63971, 2, 66, -1.52, -88.24, 0.1253, 46, 108.69, -88.24, 0.8747, 2, 66, 20.25, -95.44, 0.08687, 46, 130.46, -95.44, 0.91313, 2, 66, 34.42, -39.36, 0.72613, 46, 144.63, -39.36, 0.27387, 2, 66, 42.03, 1.7, 0.824, 46, 152.25, 1.7, 0.176, 2, 66, 45.85, 32.6, 0.856, 46, 156.06, 32.6, 0.144, 1, 66, 46.01, 61.02, 1, 1, 66, 22.35, 66.41, 1, 1, 66, 1.73, 61.84, 1, 2, 66, -31.17, 38.83, 0.928, 46, 79.04, 38.83, 0.072, 2, 66, -52.94, 19.31, 0.79073, 46, 57.27, 19.31, 0.20927, 2, 66, -39.54, 52.42, 0.912, 46, 70.67, 52.42, 0.088, 2, 66, -3.2, 87.61, 0.744, 46, 107.02, 87.61, 0.256, 2, 66, -14.82, 116.7, 0.6368, 46, 95.4, 116.7, 0.3632, 2, 66, 2.7, -6.87, 0.856, 46, 112.91, -6.87, 0.144, 2, 66, 6.21, 15.8, 0.744, 46, 116.42, 15.8, 0.256, 2, 66, -15.39, 2.47, 0.856, 46, 94.82, 2.47, 0.144, 2, 66, -12.98, -40.48, 0.72102, 46, 97.24, -40.48, 0.27898, 2, 66, -19.55, -68.16, 0.59162, 46, 90.66, -68.16, 0.40838, 2, 66, 17.44, -47.15, 0.53452, 46, 127.65, -47.15, 0.46548 ], + "hull": 25, + "edges": [ 36, 34, 34, 32, 32, 30, 30, 28, 28, 26, 26, 24, 24, 22, 18, 16, 16, 14, 14, 12, 12, 10, 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 48, 48, 46, 46, 44, 36, 38, 40, 38, 24, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 62, 64, 64, 12, 8, 66, 66, 68, 68, 70, 70, 72, 72, 74, 74, 76, 76, 78, 78, 80, 80, 82, 82, 24, 24, 84, 84, 86, 86, 44, 40, 42, 42, 44, 42, 88, 88, 30, 58, 90, 90, 92, 92, 94, 18, 20, 20, 22, 94, 20, 18, 96, 96, 98, 60, 100, 100, 62, 98, 100 ], + "width": 261, + "height": 166 + } + }, + "gun": { + "gun": { "x": 77.3, "y": 16.4, "rotation": 60.83, "width": 210, "height": 203 } + }, + "head": { + "head": { + "type": "mesh", + "uvs": [ 0.75919, 0.06107, 0.88392, 0.17893, 0.90174, 0.30856, 0.94224, 0.1966, 1, 0.26584, 1, 0.422, 0.95864, 0.46993, 0.92118, 0.51333, 0.85957, 0.5347, 0.78388, 0.65605, 0.74384, 0.74838, 0.85116, 0.75151, 0.84828, 0.82564, 0.81781, 0.85367, 0.75599, 0.85906, 0.76237, 0.90468, 0.65875, 1, 0.38337, 1, 0.1858, 0.85404, 0.12742, 0.81091, 0.06025, 0.69209, 0, 0.58552, 0, 0.41021, 0.0853, 0.20692, 0.24243, 0.14504, 0.5, 0.1421, 0.50324, 0.07433, 0.41738, 0, 0.57614, 0, 0.85059, 0.36087, 0.73431, 0.43206, 0.68481, 0.31271, 0.72165, 0.16718, 0.55931, 0.04154, 0.44764, 0.22895, 0.23926, 0.26559, 0.71272, 0.44036, 0.56993, 0.383, 0.41678, 0.33511, 0.293, 0.31497, 0.70802, 0.44502, 0.56676, 0.38976, 0.41521, 0.34416, 0.28754, 0.33017, 0.88988, 0.50177, 0.30389, 0.73463, 0.2646, 0.65675, 0.21414, 0.61584, 0.14613, 0.62194, 0.10316, 0.66636, 0.10358, 0.72557, 0.14505, 0.79164, 0.20263, 0.81355, 0.27873, 0.80159, 0.34947, 0.7376, 0.23073, 0.57073, 0.08878, 0.60707, 0.29461, 0.8129, 0.73006, 0.87883, 0.69805, 0.87348, 0.66166, 0.79681, 0.22468, 0.69824, 0.14552, 0.67405 ], + "triangles": [ 50, 49, 62, 34, 25, 31, 39, 35, 34, 38, 39, 34, 37, 38, 34, 42, 39, 38, 43, 39, 42, 32, 2, 31, 31, 37, 34, 42, 38, 37, 41, 42, 37, 43, 22, 39, 30, 31, 29, 36, 37, 31, 30, 36, 31, 40, 41, 37, 36, 40, 37, 36, 30, 44, 55, 22, 43, 55, 48, 56, 47, 48, 55, 46, 55, 54, 42, 55, 43, 47, 55, 46, 62, 49, 48, 61, 47, 46, 62, 48, 47, 61, 62, 47, 46, 54, 45, 42, 41, 55, 61, 46, 45, 55, 41, 54, 61, 51, 50, 61, 50, 62, 60, 41, 40, 54, 41, 60, 53, 61, 45, 52, 51, 61, 57, 53, 45, 57, 45, 54, 53, 52, 61, 52, 19, 51, 57, 18, 52, 57, 52, 53, 17, 54, 60, 57, 54, 17, 18, 57, 17, 19, 50, 51, 33, 27, 28, 26, 27, 33, 0, 33, 28, 32, 33, 0, 32, 0, 1, 33, 25, 26, 33, 32, 25, 31, 25, 32, 2, 32, 1, 2, 3, 4, 29, 31, 2, 2, 4, 5, 29, 2, 5, 6, 29, 5, 30, 29, 6, 44, 30, 6, 18, 19, 52, 49, 56, 48, 34, 24, 25, 35, 23, 24, 35, 24, 34, 39, 22, 35, 22, 23, 35, 7, 44, 6, 8, 36, 44, 40, 36, 8, 8, 44, 7, 56, 21, 22, 55, 56, 22, 9, 40, 8, 20, 21, 56, 20, 56, 49, 9, 60, 40, 10, 60, 9, 20, 50, 19, 12, 10, 11, 13, 10, 12, 14, 60, 10, 13, 14, 10, 59, 60, 14, 58, 59, 14, 58, 14, 15, 16, 17, 60, 59, 16, 60, 15, 16, 59, 15, 59, 58, 20, 49, 50 ], + "vertices": [ 2, 50, 41.97, -41.8, 0.94074, 66, 165.41, -22.6, 0.05926, 4, 48, 73.47, 27.54, 0.26795, 50, -5.75, -51.71, 0.4738, 49, 112.99, -11.41, 0.12255, 66, 143.5, -66.13, 0.1357, 4, 48, 38.23, 10.99, 0.6831, 50, -41.01, -35.22, 0.07866, 49, 92.73, -44.66, 0.04872, 66, 108.65, -83.49, 0.18952, 2, 48, 73.35, 10.89, 0.8455, 66, 143.77, -82.78, 0.1545, 2, 48, 58.59, -10.38, 0.91607, 66, 129.5, -104.39, 0.08393, 3, 46, 195.82, -119.82, 0.104, 47, 75.49, -4.55, 0.09191, 48, 14.36, -24.8, 0.80409, 4, 46, 178.62, -113.98, 0.19022, 47, 59.82, -13.72, 0.33409, 48, -2.7, -18.57, 0.46643, 66, 68.41, -113.98, 0.00926, 4, 46, 163.06, -108.69, 0.18724, 47, 45.64, -22.03, 0.3133, 48, -18.14, -12.93, 0.47469, 66, 52.84, -108.69, 0.02477, 2, 46, 151.52, -95.05, 0.91122, 66, 41.31, -95.05, 0.08878, 2, 46, 110.61, -87.69, 0.70564, 66, 0.4, -87.69, 0.29436, 2, 46, 81.05, -86.58, 0.63951, 66, -29.16, -86.58, 0.36049, 2, 46, 89.82, -114.32, 0.57, 66, -20.39, -114.32, 0.43, 2, 46, 68.72, -120.91, 0.57, 66, -41.49, -120.91, 0.43, 2, 46, 58.1, -115.9, 0.57, 66, -52.11, -115.9, 0.43, 2, 46, 51.03, -100.63, 0.64242, 66, -59.18, -100.63, 0.35758, 2, 46, 38.79, -106.76, 0.81659, 66, -71.43, -106.76, 0.18341, 2, 46, 2.68, -89.7, 0.77801, 66, -107.53, -89.7, 0.22199, 2, 46, -22.07, -19.3, 0.823, 66, -132.28, -19.3, 0.177, 2, 46, 1.2, 45.63, 0.51204, 66, -109.01, 45.63, 0.48796, 2, 46, 8.07, 64.81, 0.60869, 66, -102.14, 64.81, 0.39131, 2, 46, 35.44, 93.73, 0.80009, 66, -74.77, 93.73, 0.19991, 2, 46, 59.98, 119.66, 0.93554, 66, -50.23, 119.66, 0.06446, 2, 46, 109.26, 136.99, 0.99895, 66, -0.95, 136.99, 0.00105, 1, 46, 174.07, 135.27, 1, 3, 46, 205.59, 101.22, 0.80778, 49, -16.84, 104.63, 0.15658, 66, 95.38, 101.22, 0.03564, 3, 50, 58.94, 30.5, 0.43491, 49, 38.36, 61.89, 0.28116, 66, 119.35, 35.65, 0.28393, 2, 50, 75.56, 19.01, 0.92164, 66, 138.68, 41.52, 0.07836, 1, 50, 106.7, 26.9, 1, 1, 50, 83.79, -9.51, 1, 5, 47, 44.51, 27.24, 0.15139, 48, 19.12, 19.33, 0.44847, 50, -46.82, -15.19, 0.05757, 49, 72.19, -48.24, 0.1149, 66, 89.35, -75.58, 0.22767, 3, 47, 7.42, 19.08, 0.37772, 49, 34.32, -45.24, 0.09918, 66, 58.9, -52.89, 0.52311, 2, 49, 45.94, -9.07, 0.4826, 66, 87.99, -28.45, 0.5174, 2, 50, 20.62, -16.35, 0.7435, 66, 132.21, -23.49, 0.2565, 2, 50, 75.74, 0.94, 0.97172, 66, 152.95, 30.42, 0.02828, 4, 46, 200.45, 40.46, 0.18809, 50, 44.6, 56.29, 0.05831, 49, 11.15, 50.46, 0.14366, 66, 90.24, 40.46, 0.60994, 2, 46, 171.41, 90.12, 0.48644, 66, 61.2, 90.12, 0.51356, 2, 46, 164.84, -48.18, 0.43217, 66, 54.62, -48.18, 0.56783, 4, 46, 168.13, -6.02, 0.01949, 47, -28.65, 49.02, 0.02229, 49, 8.54, -6.09, 0.12791, 66, 57.92, -6.02, 0.83031, 2, 46, 167.84, 37.87, 0.15, 66, 57.63, 37.87, 0.85, 2, 46, 162.36, 71.5, 0.24107, 66, 52.15, 71.5, 0.75893, 2, 46, 163.11, -47.44, 0.41951, 66, 52.9, -47.44, 0.58049, 2, 46, 165.94, -5.87, 0.16355, 66, 55.73, -5.87, 0.83645, 2, 46, 165.14, 37.38, 0.15, 66, 54.93, 37.38, 0.85, 2, 46, 157.6, 71.4, 0.21735, 66, 47.39, 71.4, 0.78265, 3, 46, 163.5, -99.54, 0.61812, 47, 39.01, -15.71, 0.30445, 66, 53.29, -99.54, 0.07744, 2, 46, 45.38, 27.24, 0.16741, 66, -64.83, 27.24, 0.83259, 2, 46, 63.74, 44.98, 0.15, 66, -46.47, 44.98, 0.85, 2, 46, 70.7, 61.92, 0.22175, 66, -39.51, 61.92, 0.77825, 2, 46, 62.88, 78.71, 0.38, 66, -47.34, 78.71, 0.62, 2, 46, 46.53, 85.3, 0.51, 66, -63.68, 85.3, 0.49, 2, 46, 29.92, 79.34, 0.388, 66, -80.29, 79.34, 0.612, 2, 46, 15.08, 62.21, 0.38, 66, -95.13, 62.21, 0.62, 2, 46, 14.09, 45.32, 0.41, 66, -96.12, 45.32, 0.59, 2, 46, 24.3, 27.06, 0.192, 66, -85.91, 27.06, 0.808, 1, 66, -61.57, 15.3, 1, 2, 46, 84.87, 62.14, 0.16757, 66, -25.34, 62.14, 0.83243, 2, 46, 61.9, 94.84, 0.68145, 66, -48.31, 94.84, 0.31855, 2, 46, 22.54, 21.88, 0.16, 66, -87.67, 21.88, 0.84, 2, 46, 43.15, -95.95, 0.73445, 66, -67.06, -95.95, 0.26555, 2, 46, 41.77, -87.24, 0.67858, 66, -68.44, -87.24, 0.32142, 2, 46, 60.05, -70.36, 0.50195, 66, -50.16, -70.36, 0.49805, 2, 46, 48.49, 51.09, 0.25, 66, -61.72, 51.09, 0.75, 2, 46, 48.17, 73.71, 0.15634, 66, -62.04, 73.71, 0.84366 ], + "hull": 29, + "edges": [ 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 56, 54, 56, 54, 52, 52, 50, 50, 48, 48, 46, 46, 44, 42, 44, 32, 34, 4, 58, 58, 60, 62, 64, 64, 66, 66, 54, 50, 68, 68, 70, 70, 44, 60, 72, 62, 74, 72, 74, 74, 76, 76, 78, 78, 44, 16, 80, 80, 82, 82, 84, 84, 86, 86, 44, 14, 88, 88, 72, 14, 16, 10, 12, 12, 14, 12, 60, 90, 92, 92, 94, 94, 96, 96, 98, 98, 100, 100, 102, 102, 104, 104, 106, 106, 90, 108, 110, 110, 112, 38, 40, 40, 42, 112, 40, 34, 36, 36, 38, 36, 114, 114, 108, 30, 32, 30, 28, 24, 26, 28, 26, 22, 24, 22, 20, 20, 18, 18, 16, 28, 116, 116, 118, 118, 120, 120, 20 ], + "width": 271, + "height": 298 + } + }, + "head-bb": { + "head": { + "type": "boundingbox", + "vertexCount": 6, + "vertices": [ -19.14, -70.3, 40.8, -118.08, 257.78, -115.62, 285.17, 57.18, 120.77, 164.95, -5.07, 76.95 ] + } + }, + "hoverboard-board": { + "hoverboard-board": { + "type": "mesh", + "uvs": [ 0.13865, 0.56624, 0.11428, 0.51461, 0.07619, 0.52107, 0.02364, 0.52998, 0.01281, 0.53182, 0, 0.37979, 0, 0.2206, 0.00519, 0.10825, 0.01038, 0.10726, 0.03834, 0.10194, 0.05091, 0, 0.08326, 0, 0.10933, 0.04206, 0.1382, 0.08865, 0.18916, 0.24067, 0.22234, 0.4063, 0.23886, 0.44063, 0.83412, 0.44034, 0.88444, 0.38296, 0.92591, 0.32639, 0.95996, 0.28841, 0.98612, 0.28542, 1, 0.38675, 0.99494, 0.47104, 0.97883, 0.53251, 0.94409, 0.62135, 0.90206, 0.69492, 0.86569, 0.71094, 0.82822, 0.70791, 0.81286, 0.77127, 0.62931, 0.77266, 0.61364, 0.70645, 0.47166, 0.70664, 0.45901, 0.77827, 0.27747, 0.76986, 0.2658, 0.70372, 0.24976, 0.71381, 0.24601, 0.77827, 0.23042, 0.84931, 0.20926, 0.90956, 0.17299, 1, 0.15077, 0.99967, 0.12906, 0.90192, 0.10369, 0.73693, 0.10198, 0.62482, 0.09131, 0.47272, 0.09133, 0.41325, 0.15082, 0.41868, 0.21991, 0.51856, 0.06331, 0.10816, 0.08383, 0.21696, 0.08905, 0.37532, 0.15903, 0.58726, 0.17538, 0.65706, 0.20118, 0.8029, 0.17918, 0.55644, 0.22166, 0.5802, 0.86259, 0.57962, 0.92346, 0.48534, 0.96691, 0.36881, 0.0945, 0.13259, 0.12688, 0.17831, 0.15986, 0.24682, 0.18036, 0.31268, 0.20607, 0.4235, 0.16074, 0.85403, 0.13624, 0.70122, 0.12096, 0.64049, 0.02396, 0.21811, 0.02732, 0.37839, 0.02557, 0.4972, 0.14476, 0.45736, 0.18019, 0.51689, 0.19692, 0.56636 ], + "triangles": [ 10, 11, 12, 9, 10, 12, 49, 9, 12, 60, 49, 12, 13, 60, 12, 61, 60, 13, 50, 49, 60, 50, 60, 61, 68, 8, 9, 68, 9, 49, 68, 49, 50, 7, 8, 68, 6, 7, 68, 61, 13, 14, 62, 61, 14, 50, 61, 62, 63, 62, 14, 59, 20, 21, 19, 20, 59, 51, 50, 62, 51, 62, 63, 51, 69, 68, 51, 68, 50, 6, 68, 69, 5, 6, 69, 18, 19, 59, 15, 63, 14, 59, 21, 22, 47, 51, 63, 47, 46, 51, 47, 63, 64, 15, 64, 63, 64, 15, 16, 71, 46, 47, 23, 59, 22, 69, 51, 70, 45, 46, 71, 70, 51, 2, 58, 18, 59, 58, 59, 23, 17, 18, 58, 70, 5, 69, 2, 51, 46, 1, 45, 71, 47, 48, 71, 47, 64, 48, 48, 72, 71, 1, 71, 72, 16, 48, 64, 45, 2, 46, 2, 45, 1, 70, 4, 5, 3, 70, 2, 3, 4, 70, 24, 58, 23, 72, 0, 1, 73, 55, 72, 55, 0, 72, 48, 73, 72, 57, 17, 58, 25, 57, 58, 56, 48, 16, 73, 48, 56, 56, 16, 17, 56, 17, 57, 52, 0, 55, 24, 25, 58, 44, 0, 52, 67, 44, 52, 52, 56, 53, 73, 52, 55, 56, 52, 73, 67, 52, 53, 26, 57, 25, 66, 67, 53, 56, 32, 35, 53, 56, 35, 56, 57, 32, 28, 31, 57, 57, 31, 32, 57, 27, 28, 26, 27, 57, 36, 53, 35, 43, 44, 67, 43, 67, 66, 34, 35, 32, 29, 31, 28, 30, 31, 29, 53, 54, 66, 53, 36, 54, 33, 34, 32, 37, 54, 36, 65, 43, 66, 38, 54, 37, 54, 65, 66, 39, 65, 54, 42, 43, 65, 38, 39, 54, 40, 42, 65, 40, 41, 42, 65, 39, 40 ], + "vertices": [ -189.36, 15.62, -201.35, 23.47, -220.09, 22.49, -245.95, 21.13, -251.28, 20.86, -257.58, 43.96, -257.57, 68.16, -255.02, 85.24, -252.47, 85.39, -238.71, 86.2, -232.52, 101.69, -216.61, 101.69, -203.78, 95.3, -189.58, 88.21, -164.51, 65.1, -148.19, 39.93, -140.06, 34.71, 152.82, 34.73, 177.57, 43.45, 197.97, 52.05, 214.72, 57.82, 227.6, 58.27, 234.42, 42.87, 231.94, 30.06, 224.01, 20.72, 206.91, 7.21, 186.23, -3.97, 168.34, -6.4, 149.9, -5.94, 142.35, -15.57, 52.04, -15.77, 44.33, -5.71, -25.52, -5.73, -31.75, -16.62, -121.07, -15.34, -126.81, -5.28, -134.7, -6.81, -136.54, -16.61, -144.22, -27.41, -154.63, -36.57, -172.47, -50.31, -183.41, -50.26, -194.09, -35.4, -206.56, -10.32, -207.4, 6.72, -212.65, 29.84, -212.64, 38.88, -183.37, 38.05, -149.38, 22.86, -226.43, 85.25, -216.33, 68.71, -213.76, 44.64, -179.34, 12.42, -171.29, 1.81, -158.6, -20.36, -169.42, 17.11, -148.52, 13.49, 166.82, 13.56, 196.76, 27.89, 218.14, 45.6, -211.08, 81.54, -195.15, 74.59, -178.93, 64.17, -168.84, 54.16, -156.19, 37.31, -178.5, -28.13, -190.55, -4.9, -198.07, 4.33, -245.79, 68.54, -244.14, 44.18, -245, 26.12, -186.36, 32.17, -168.92, 23.12, -160.69, 15.6 ], + "hull": 45, + "edges": [ 0, 2, 8, 10, 10, 12, 12, 14, 18, 20, 20, 22, 26, 28, 28, 30, 30, 32, 32, 34, 34, 36, 36, 38, 38, 40, 40, 42, 42, 44, 44, 46, 46, 48, 48, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 60, 62, 62, 64, 64, 66, 66, 68, 68, 70, 70, 72, 72, 74, 80, 82, 82, 84, 84, 86, 86, 88, 0, 88, 2, 90, 90, 92, 92, 94, 94, 96, 96, 32, 18, 98, 98, 100, 100, 102, 2, 4, 102, 4, 92, 102, 0, 104, 104, 106, 106, 108, 78, 80, 108, 78, 74, 76, 76, 78, 62, 56, 64, 70, 0, 110, 112, 114, 114, 116, 116, 118, 118, 42, 50, 116, 114, 34, 98, 120, 120, 122, 22, 24, 24, 26, 120, 24, 122, 124, 124, 126, 126, 128, 128, 96, 80, 130, 130, 132, 132, 134, 134, 88, 14, 16, 16, 18, 136, 16, 136, 138, 138, 140, 4, 6, 6, 8, 140, 6, 96, 112, 92, 142, 142, 144, 110, 146, 146, 112, 144, 146 ], + "width": 492, + "height": 152 + } + }, + "hoverboard-thruster-front": { + "hoverboard-thruster": { "x": 0.02, "y": -7.08, "rotation": 0.17, "width": 60, "height": 64 } + }, + "hoverboard-thruster-rear": { + "hoverboard-thruster": { "x": 1.1, "y": -6.29, "rotation": 0.17, "width": 60, "height": 64 } + }, + "hoverglow-front": { + "hoverglow-small": { + "x": 2.13, + "y": -2, + "scaleX": 0.303, + "scaleY": 0.495, + "rotation": 0.15, + "width": 274, + "height": 75 + } + }, + "hoverglow-rear": { + "hoverglow-small": { + "x": 1.39, + "y": -2.09, + "scaleX": 0.303, + "scaleY": 0.495, + "rotation": 0.61, + "width": 274, + "height": 75 + } + }, + "mouth": { + "mouth-grind": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 66, -98.93, -85.88, 0.22, 46, 11.28, -85.88, 0.78, 2, 66, -129.77, 1.84, 0.6, 46, -19.56, 1.84, 0.4, 2, 66, -74.12, 21.41, 0.6, 46, 36.09, 21.41, 0.4, 2, 66, -43.28, -66.32, 0.4, 46, 66.93, -66.32, 0.6 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + }, + "mouth-oooo": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 46, 11.28, -85.89, 0.22, 66, -98.93, -85.89, 0.78, 2, 46, -19.56, 1.85, 0.6, 66, -129.78, 1.85, 0.4, 2, 46, 36.1, 21.42, 0.6, 66, -74.12, 21.42, 0.4, 2, 46, 66.94, -66.32, 0.4, 66, -43.27, -66.32, 0.6 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + }, + "mouth-smile": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 66, -98.93, -85.89, 0.21075, 46, 11.28, -85.89, 0.78925, 2, 66, -129.77, 1.85, 0.6, 46, -19.56, 1.85, 0.4, 2, 66, -74.11, 21.42, 0.6, 46, 36.1, 21.42, 0.4, 2, 66, -43.27, -66.32, 0.40772, 46, 66.94, -66.32, 0.59228 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + } + }, + "muzzle": { + "muzzle01": { + "x": 151.97, + "y": 5.81, + "scaleX": 3.7361, + "scaleY": 3.7361, + "rotation": 0.15, + "width": 133, + "height": 79 + }, + "muzzle02": { + "x": 187.25, + "y": 5.9, + "scaleX": 4.0623, + "scaleY": 4.0623, + "rotation": 0.15, + "width": 135, + "height": 84 + }, + "muzzle03": { + "x": 231.96, + "y": 6.02, + "scaleX": 4.1325, + "scaleY": 4.1325, + "rotation": 0.15, + "width": 166, + "height": 106 + }, + "muzzle04": { + "x": 231.96, + "y": 6.02, + "scaleX": 4.0046, + "scaleY": 4.0046, + "rotation": 0.15, + "width": 149, + "height": 90 + }, + "muzzle05": { + "x": 293.8, + "y": 6.19, + "scaleX": 4.4673, + "scaleY": 4.4673, + "rotation": 0.15, + "width": 135, + "height": 75 + } + }, + "muzzle-glow": { + "muzzle-glow": { "width": 50, "height": 50 } + }, + "muzzle-ring": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "muzzle-ring2": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "muzzle-ring3": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "muzzle-ring4": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "neck": { + "neck": { "x": 9.77, "y": -3.01, "rotation": -55.22, "width": 36, "height": 41 } + }, + "portal-bg": { + "portal-bg": { "x": -3.1, "y": 7.25, "scaleX": 1.0492, "scaleY": 1.0492, "width": 266, "height": 266 } + }, + "portal-flare1": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare2": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare3": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare4": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare5": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare6": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare7": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare8": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare9": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare10": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-shade": { + "portal-shade": { "width": 266, "height": 266 } + }, + "portal-streaks1": { + "portal-streaks1": { "scaleX": 0.9774, "scaleY": 0.9774, "width": 252, "height": 256 } + }, + "portal-streaks2": { + "portal-streaks2": { "x": -1.64, "y": 2.79, "width": 250, "height": 249 } + }, + "rear-bracer": { + "rear-bracer": { "x": 11.15, "y": -2.2, "rotation": 66.17, "width": 56, "height": 72 } + }, + "rear-foot": { + "rear-foot": { + "type": "mesh", + "uvs": [ 0.48368, 0.1387, 0.51991, 0.21424, 0.551, 0.27907, 0.58838, 0.29816, 0.63489, 0.32191, 0.77342, 0.39267, 1, 0.73347, 1, 1, 0.54831, 0.99883, 0.31161, 1, 0, 1, 0, 0.41397, 0.13631, 0, 0.41717, 0 ], + "triangles": [ 8, 3, 4, 8, 4, 5, 8, 5, 6, 8, 6, 7, 11, 1, 10, 3, 9, 2, 2, 10, 1, 12, 13, 0, 0, 11, 12, 1, 11, 0, 2, 9, 10, 3, 8, 9 ], + "vertices": [ 2, 8, 10.45, 29.41, 0.90802, 9, -6.74, 49.62, 0.09198, 2, 8, 16.56, 29.27, 0.84259, 9, -2.65, 45.09, 0.15741, 2, 8, 21.8, 29.15, 0.69807, 9, 0.85, 41.2, 0.30193, 2, 8, 25.53, 31.43, 0.52955, 9, 5.08, 40.05, 0.47045, 2, 8, 30.18, 34.27, 0.39303, 9, 10.33, 38.62, 0.60697, 2, 8, 44.02, 42.73, 0.27525, 9, 25.98, 34.36, 0.72475, 2, 8, 76.47, 47.28, 0.21597, 9, 51.56, 13.9, 0.78403, 2, 8, 88.09, 36.29, 0.28719, 9, 51.55, -2.09, 0.71281, 2, 8, 52.94, -0.73, 0.47576, 9, 0.52, -1.98, 0.52424, 2, 8, 34.63, -20.23, 0.68757, 9, -26.23, -2.03, 0.31243, 2, 8, 10.44, -45.81, 0.84141, 9, -61.43, -2, 0.15859, 2, 8, -15.11, -21.64, 0.93283, 9, -61.4, 33.15, 0.06717, 1, 8, -22.57, 6.61, 1, 1, 8, -0.76, 29.67, 1 ], + "hull": 14, + "edges": [ 14, 12, 10, 12, 14, 16, 16, 18, 18, 20, 4, 18, 20, 22, 24, 26, 22, 24, 4, 2, 2, 20, 4, 6, 6, 16, 6, 8, 8, 10, 2, 0, 0, 26 ], + "width": 113, + "height": 60 + } + }, + "rear-shin": { + "rear-shin": { "x": 58.29, "y": -2.75, "rotation": 92.37, "width": 75, "height": 178 } + }, + "rear-thigh": { + "rear-thigh": { "x": 33.11, "y": -4.11, "rotation": 72.54, "width": 55, "height": 94 } + }, + "rear-upper-arm": { + "rear-upper-arm": { "x": 21.13, "y": 4.09, "rotation": 89.33, "width": 40, "height": 87 } + }, + "side-glow1": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.2353, "scaleY": 0.4132, "width": 274, "height": 75 } + }, + "side-glow2": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.2353, "scaleY": 0.4132, "width": 274, "height": 75 } + }, + "side-glow3": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.3586, "scaleY": 0.6297, "width": 274, "height": 75 } + }, + "torso": { + "torso": { + "type": "mesh", + "uvs": [ 0.6251, 0.12672, 1, 0.26361, 1, 0.28871, 1, 0.66021, 1, 0.68245, 0.92324, 0.69259, 0.95116, 0.84965, 0.77124, 1, 0.49655, 1, 0.27181, 1, 0.13842, 0.77196, 0.09886, 0.6817, 0.05635, 0.58471, 0, 0.45614, 0, 0.33778, 0, 0.19436, 0.14463, 0, 0.27802, 0, 0.72525, 0.27835, 0.76091, 0.46216, 0.84888, 0.67963, 0.68257, 0.63249, 0.53986, 0.3847, 0.25443, 0.3217, 0.30063, 0.55174, 0.39553, 0.79507, 0.26389, 0.17007, 0.5241, 0.18674, 0.71492, 0.76655, 0.82151, 0.72956, 0.27626, 0.4304, 0.62327, 0.52952, 0.3455, 0.66679, 0.53243, 0.2914 ], + "triangles": [ 18, 1, 2, 19, 2, 3, 18, 0, 1, 23, 15, 26, 27, 26, 16, 14, 15, 23, 15, 16, 26, 17, 27, 16, 13, 14, 23, 0, 27, 17, 13, 23, 30, 11, 12, 24, 21, 31, 19, 12, 13, 30, 24, 22, 31, 31, 22, 19, 12, 30, 24, 32, 24, 31, 24, 30, 22, 3, 20, 19, 32, 31, 21, 11, 24, 32, 4, 5, 3, 8, 28, 7, 7, 29, 6, 7, 28, 29, 9, 25, 8, 8, 25, 28, 9, 10, 25, 29, 5, 6, 10, 32, 25, 25, 21, 28, 25, 32, 21, 10, 11, 32, 28, 21, 29, 29, 20, 5, 29, 21, 20, 5, 20, 3, 20, 21, 19, 33, 26, 27, 22, 18, 19, 19, 18, 2, 33, 27, 18, 30, 23, 22, 22, 33, 18, 23, 33, 22, 33, 23, 26, 27, 0, 18 ], + "vertices": [ 2, 29, 44.59, -10.39, 0.88, 40, -17.65, 33.99, 0.12, 3, 28, 59.65, -45.08, 0.12189, 29, 17.13, -45.08, 0.26811, 40, 22.68, 15.82, 0.61, 3, 28, 55.15, -44.72, 0.1345, 29, 12.63, -44.72, 0.2555, 40, 23.43, 11.37, 0.61, 3, 27, 31.01, -39.45, 0.51133, 28, -11.51, -39.45, 0.30867, 40, 34.58, -54.57, 0.18, 3, 27, 27.01, -39.14, 0.53492, 28, -15.5, -39.14, 0.28508, 40, 35.25, -58.52, 0.18, 2, 27, 25.79, -31.5, 0.75532, 28, -16.73, -31.5, 0.24468, 1, 27, -2.61, -32, 1, 1, 27, -28.2, -12.29, 1, 1, 27, -26.08, 14.55, 1, 1, 27, -24.35, 36.5, 1, 2, 27, 17.6, 46.3, 0.8332, 28, -24.92, 46.3, 0.1668, 2, 27, 34.1, 48.89, 0.59943, 28, -8.42, 48.89, 0.40058, 3, 27, 51.83, 51.67, 0.29262, 28, 9.32, 51.67, 0.63181, 29, -33.2, 51.67, 0.07557, 3, 27, 75.34, 55.35, 0.06656, 28, 32.82, 55.35, 0.62298, 29, -9.7, 55.35, 0.31046, 2, 28, 54.06, 53.67, 0.37296, 29, 11.54, 53.67, 0.62704, 2, 28, 79.79, 51.64, 0.10373, 29, 37.27, 51.64, 0.89627, 1, 29, 71.04, 34.76, 1, 1, 29, 70.01, 21.72, 1, 1, 30, 36.74, 7.06, 1, 3, 30, 45.7, -24.98, 0.67, 28, 25.87, -18.9, 0.3012, 29, -16.65, -18.9, 0.0288, 2, 27, 28.69, -24.42, 0.77602, 28, -13.83, -24.42, 0.22398, 3, 30, 43.24, -56.49, 0.064, 27, 38.43, -8.84, 0.67897, 28, -4.09, -8.84, 0.25703, 3, 30, 22.02, -14.85, 0.29, 28, 41.48, 1.59, 0.53368, 29, -1.04, 1.59, 0.17632, 3, 30, -7.45, -8.33, 0.76, 28, 54.98, 28.59, 0.06693, 29, 12.46, 28.59, 0.17307, 3, 30, 3.91, -48.4, 0.25, 27, 55.87, 27.33, 0.15843, 28, 13.35, 27.33, 0.59157, 1, 27, 11.47, 21.51, 1, 2, 30, -11.09, 18.74, 0.416, 29, 39.6, 25.51, 0.584, 2, 30, 14.56, 20.03, 0.53, 29, 34.6, 0.33, 0.47, 1, 27, 14.12, -10.1, 1, 2, 27, 19.94, -21.03, 0.92029, 28, -22.58, -21.03, 0.07971, 3, 30, -2.08, -27.26, 0.29, 28, 35.31, 27.99, 0.49582, 29, -7.21, 27.99, 0.21418, 2, 30, 34.42, -39.19, 0.25, 28, 14.84, -4.5, 0.75, 2, 27, 34.87, 24.58, 0.67349, 28, -7.64, 24.58, 0.32651, 2, 30, 18.5, 1.59, 0.76, 29, 15.76, 1, 0.24 ], + "hull": 18, + "edges": [ 14, 12, 12, 10, 10, 8, 18, 20, 32, 34, 30, 32, 2, 4, 36, 4, 36, 38, 38, 40, 4, 6, 6, 8, 40, 6, 40, 42, 14, 16, 16, 18, 50, 16, 46, 52, 54, 36, 2, 0, 0, 34, 54, 0, 54, 32, 20, 50, 14, 56, 56, 42, 50, 56, 56, 58, 58, 40, 58, 10, 46, 60, 60, 48, 26, 60, 60, 44, 24, 26, 24, 48, 42, 62, 62, 44, 48, 62, 48, 64, 64, 50, 42, 64, 20, 22, 22, 24, 64, 22, 26, 28, 28, 30, 28, 46, 44, 66, 66, 54, 46, 66, 66, 36, 62, 38 ], + "width": 98, + "height": 180 + } + } + } + } +], +"events": { + "footstep": {} +}, +"animations": { + "aim": { + "slots": { + "crosshair": { + "attachment": [ + { "name": "crosshair" } + ] + } + }, + "bones": { + "front-fist": { + "rotate": [ + { "value": 36.08 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": -26.55 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "value": 62.31 } + ] + }, + "front-bracer": { + "rotate": [ + { "value": 9.11 } + ] + }, + "gun": { + "rotate": [ + { "value": -0.31 } + ] + } + }, + "ik": { + "aim-ik": [ + { "mix": 0.995 } + ] + }, + "transform": { + "aim-front-arm-transform": [ + { "mixRotate": 0.784, "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ], + "aim-head-transform": [ + { "mixRotate": 0.659, "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ], + "aim-torso-transform": [ + { "mixRotate": 0.423, "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ] + } + }, + "death": { + "slots": { + "eye": { + "attachment": [ + { "name": "eye-surprised" }, + { "time": 0.5333, "name": "eye-indifferent" }, + { "time": 2.2, "name": "eye-surprised" }, + { "time": 4.6, "name": "eye-indifferent" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "name": "mouth-oooo" }, + { "time": 0.5333, "name": "mouth-grind" }, + { "time": 1.4, "name": "mouth-oooo" }, + { "time": 2.1667, "name": "mouth-grind" }, + { "time": 4.5333, "name": "mouth-oooo" } + ] + } + }, + "bones": { + "head": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.015, -2.83, 0.036, 12.72 ] + }, + { + "time": 0.0667, + "value": 12.19, + "curve": [ 0.096, 11.68, 0.119, -1.14 ] + }, + { + "time": 0.1333, + "value": -6.86, + "curve": [ 0.149, -13.27, 0.21, -37.28 ] + }, + { + "time": 0.3, + "value": -36.86, + "curve": [ 0.354, -36.61, 0.412, -32.35 ] + }, + { + "time": 0.4667, + "value": -23.49, + "curve": [ 0.49, -19.87, 0.512, -3.29 ] + }, + { + "time": 0.5333, + "value": -3.24, + "curve": [ 0.56, -3.39, 0.614, -67.25 ] + }, + { + "time": 0.6333, + "value": -74.4, + "curve": [ 0.652, -81.58, 0.702, -88.94 ] + }, + { + "time": 0.7333, + "value": -88.93, + "curve": [ 0.805, -88.91, 0.838, -80.87 ] + }, + { + "time": 0.8667, + "value": -81.03, + "curve": [ 0.922, -81.32, 0.976, -85.29 ] + }, + { "time": 1, "value": -85.29, "curve": "stepped" }, + { + "time": 2.2333, + "value": -85.29, + "curve": [ 2.314, -85.29, 2.382, -68.06 ] + }, + { + "time": 2.4667, + "value": -63.48, + "curve": [ 2.57, -57.87, 2.916, -55.24 ] + }, + { + "time": 3.2, + "value": -55.1, + "curve": [ 3.447, -54.98, 4.135, -56.61 ] + }, + { + "time": 4.2667, + "value": -58.23, + "curve": [ 4.672, -63.24, 4.646, -82.69 ] + }, + { "time": 4.9333, "value": -85.29 } + ], + "scale": [ + { + "time": 0.4667, + "curve": [ 0.469, 1.005, 0.492, 1.065, 0.475, 1.018, 0.492, 0.94 ] + }, + { + "time": 0.5, + "x": 1.065, + "y": 0.94, + "curve": [ 0.517, 1.065, 0.541, 0.991, 0.517, 0.94, 0.542, 1.026 ] + }, + { + "time": 0.5667, + "x": 0.99, + "y": 1.025, + "curve": [ 0.593, 0.988, 0.609, 1.002, 0.595, 1.024, 0.607, 1.001 ] + }, + { "time": 0.6333 } + ] + }, + "neck": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.114, 1.33, 0.195, 4.13 ] + }, + { + "time": 0.2667, + "value": 4.13, + "curve": [ 0.351, 4.14, 0.444, -24.5 ] + }, + { + "time": 0.5, + "value": -24.69, + "curve": [ 0.571, -23.89, 0.55, 34.22 ] + }, + { + "time": 0.6667, + "value": 35.13, + "curve": [ 0.713, 34.81, 0.756, 22.76 ] + }, + { + "time": 0.8333, + "value": 22.82, + "curve": [ 0.868, 22.84, 0.916, 47.95 ] + }, + { "time": 0.9667, "value": 47.95, "curve": "stepped" }, + { + "time": 2.2333, + "value": 47.95, + "curve": [ 2.3, 47.95, 2.617, 18.72 ] + }, + { + "time": 2.6667, + "value": 18.51, + "curve": [ 3.172, 16.58, 4.06, 16.79 ] + }, + { + "time": 4.5333, + "value": 18.51, + "curve": [ 4.707, 19.13, 4.776, 41.11 ] + }, + { "time": 4.8, "value": 47.95 } + ] + }, + "torso": { + "rotate": [ + { + "value": -8.62, + "curve": [ 0.01, -16.71, 0.032, -33.6 ] + }, + { + "time": 0.0667, + "value": -33.37, + "curve": [ 0.182, -32.61, 0.298, 123.07 ] + }, + { + "time": 0.4667, + "value": 122.77, + "curve": [ 0.511, 122.69, 0.52, 100.2 ] + }, + { + "time": 0.5667, + "value": 88.96, + "curve": [ 0.588, 83.89, 0.667, 75.34 ] + }, + { + "time": 0.7, + "value": 75.34, + "curve": [ 0.767, 75.34, 0.9, 76.03 ] + }, + { "time": 0.9667, "value": 76.03 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -38.86, + "curve": [ 0.022, -40.38, 0.096, -41.92 ] + }, + { + "time": 0.1333, + "value": -41.92, + "curve": [ 0.176, -41.92, 0.216, -16.92 ] + }, + { + "time": 0.2333, + "value": -4.35, + "curve": [ 0.258, 13.69, 0.308, 60.35 ] + }, + { + "time": 0.4, + "value": 60.17, + "curve": [ 0.496, 59.98, 0.539, 33.63 ] + }, + { + "time": 0.5667, + "value": 23.06, + "curve": [ 0.595, 32.71, 0.675, 53.71 ] + }, + { + "time": 0.7333, + "value": 53.61, + "curve": [ 0.797, 53.51, 0.926, 30.98 ] + }, + { "time": 0.9333, "value": 19.57, "curve": "stepped" }, + { + "time": 1.9667, + "value": 19.57, + "curve": [ 2.245, 19.57, 2.702, 77.03 ] + }, + { + "time": 3.0667, + "value": 77.06, + "curve": [ 3.209, 77.33, 3.291, 67.99 ] + }, + { + "time": 3.4333, + "value": 67.96, + "curve": [ 3.608, 68.34, 3.729, 73.88 ] + }, + { + "time": 3.8333, + "value": 73.42, + "curve": [ 4.152, 73.91, 4.46, 71.98 ] + }, + { + "time": 4.6333, + "value": 64.77, + "curve": [ 4.688, 62.5, 4.847, 26.42 ] + }, + { "time": 4.8667, "value": 10.94 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": -44.7, + "curve": [ 0.033, -44.7, 0.12, 54.89 ] + }, + { + "time": 0.1333, + "value": 64.62, + "curve": [ 0.154, 79.18, 0.214, 79.42 ] + }, + { + "time": 0.2667, + "value": 63.4, + "curve": [ 0.293, 55.19, 0.332, 30.13 ] + }, + { + "time": 0.3667, + "value": 30.13, + "curve": [ 0.4, 30.13, 0.441, 39.87 ] + }, + { + "time": 0.4667, + "value": 55.13, + "curve": [ 0.488, 68.18, 0.52, 100.72 ] + }, + { + "time": 0.5333, + "value": 111.96, + "curve": [ 0.551, 126.88, 0.627, 185.97 ] + }, + { + "time": 0.6667, + "value": 185.97, + "curve": [ 0.692, 185.97, 0.736, 162.43 ] + }, + { + "time": 0.8, + "value": 158.01, + "curve": [ 0.9, 151.12, 1.017, 144.01 ] + }, + { "time": 1.1, "value": 144.01, "curve": "stepped" }, + { + "time": 2.3667, + "value": 144.01, + "curve": [ 2.492, 144.01, 2.742, 138.63 ] + }, + { + "time": 2.8667, + "value": 138.63, + "curve": [ 3.067, 138.63, 3.467, 138.63 ] + }, + { + "time": 3.6667, + "value": 138.63, + "curve": [ 3.883, 138.63, 4.317, 135.18 ] + }, + { + "time": 4.5333, + "value": 135.18, + "curve": [ 4.575, 135.18, 4.692, 131.59 ] + }, + { + "time": 4.7333, + "value": 131.59, + "curve": [ 4.758, 131.59, 4.517, 144.01 ] + }, + { "time": 4.8333, "value": 144.01 } + ], + "translate": [ + { + "time": 0.4667, + "curve": [ 0.517, 0, 0.617, -34.96, 0.517, 0, 0.617, -16.59 ] + }, + { "time": 0.6667, "x": -35.02, "y": -16.62 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 21.88, + "curve": [ 0.033, 21.88, 0.099, 20.44 ] + }, + { + "time": 0.1333, + "value": 9.43, + "curve": [ 0.164, -0.29, 0.162, -38.26 ] + }, + { + "time": 0.2, + "value": -38.05, + "curve": [ 0.24, -37.96, 0.228, -17.82 ] + }, + { + "time": 0.3333, + "value": -9.73, + "curve": [ 0.372, -6.76, 0.431, -0.74 ] + }, + { + "time": 0.4667, + "value": 6.47, + "curve": [ 0.489, 11.05, 0.503, 19.09 ] + }, + { + "time": 0.5333, + "value": 19.09, + "curve": [ 0.571, 19.09, 0.554, -42.67 ] + }, + { + "time": 0.6, + "value": -42.67, + "curve": [ 0.653, -42.67, 0.691, -13.8 ] + }, + { + "time": 0.7, + "value": -3.54, + "curve": [ 0.707, 3.8, 0.719, 24.94 ] + }, + { + "time": 0.8, + "value": 25.31, + "curve": [ 0.902, 24.75, 0.992, -0.34 ] + }, + { "time": 1, "value": -32.16, "curve": "stepped" }, + { + "time": 2.2333, + "value": -32.16, + "curve": [ 2.6, -32.16, 2.638, -5.3 ] + }, + { + "time": 2.7, + "value": -1.96, + "curve": [ 2.707, -1.56, 2.775, 1.67 ] + }, + { + "time": 2.8, + "value": 1.67, + "curve": [ 2.825, 1.67, 2.875, -0.39 ] + }, + { + "time": 2.9, + "value": -0.39, + "curve": [ 2.925, -0.39, 2.975, 0.26 ] + }, + { + "time": 3, + "value": 0.26, + "curve": [ 3.025, 0.26, 3.075, -1.81 ] + }, + { + "time": 3.1, + "value": -1.81, + "curve": [ 3.125, -1.81, 3.175, -0.52 ] + }, + { + "time": 3.2, + "value": -0.52, + "curve": [ 3.225, -0.52, 3.275, -2.41 ] + }, + { + "time": 3.3, + "value": -2.41, + "curve": [ 3.333, -2.41, 3.4, -0.38 ] + }, + { + "time": 3.4333, + "value": -0.38, + "curve": [ 3.467, -0.38, 3.533, -2.25 ] + }, + { + "time": 3.5667, + "value": -2.25, + "curve": [ 3.592, -2.25, 3.642, -0.33 ] + }, + { + "time": 3.6667, + "value": -0.33, + "curve": [ 3.7, -0.33, 3.767, -1.34 ] + }, + { + "time": 3.8, + "value": -1.34, + "curve": [ 3.825, -1.34, 3.862, -0.77 ] + }, + { + "time": 3.9, + "value": -0.77, + "curve": [ 3.942, -0.77, 3.991, -1.48 ] + }, + { + "time": 4, + "value": -1.87, + "curve": [ 4.167, -1.87, 4.5, -1.96 ] + }, + { + "time": 4.6667, + "value": -1.96, + "curve": [ 4.709, 18.05, 4.767, 34.55 ] + }, + { + "time": 4.8, + "value": 34.55, + "curve": [ 4.84, 34.24, 4.902, 12.03 ] + }, + { "time": 4.9333, "value": -18.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -2.33, + "curve": [ 0.019, 4.43, 0.069, 10.82 ] + }, + { + "time": 0.1, + "value": 10.6, + "curve": [ 0.148, 10.6, 0.123, -15.24 ] + }, + { + "time": 0.2, + "value": -15.35, + "curve": [ 0.266, -15.44, 0.316, -6.48 ] + }, + { + "time": 0.3333, + "value": -3.9, + "curve": [ 0.362, 0.43, 0.479, 22.36 ] + }, + { + "time": 0.5667, + "value": 22.01, + "curve": [ 0.61, 21.84, 0.627, 12.85 ] + }, + { + "time": 0.6333, + "value": 9.05, + "curve": [ 0.643, 2.77, 0.622, -39.43 ] + }, + { + "time": 0.7, + "value": -39.5, + "curve": [ 0.773, -39.57, 0.814, 14.77 ] + }, + { + "time": 0.8667, + "value": 14.81, + "curve": [ 0.965, 14.88, 1.1, 5.64 ] + }, + { "time": 1.1, "value": -6.08, "curve": "stepped" }, + { + "time": 2.2333, + "value": -6.08, + "curve": [ 2.307, -6.08, 2.427, -25.89 ] + }, + { + "time": 2.5333, + "value": -22.42, + "curve": [ 2.598, -20.38, 2.657, 5.73 ] + }, + { + "time": 2.7, + "value": 5.73, + "curve": [ 2.77, 5.73, 2.851, -5.38 ] + }, + { + "time": 2.9333, + "value": -5.38, + "curve": [ 3.008, -5.38, 3.087, -4.54 ] + }, + { + "time": 3.1667, + "value": -4.17, + "curve": [ 3.223, -3.91, 4.486, 5.73 ] + }, + { + "time": 4.6667, + "value": 5.73, + "curve": [ 4.733, 5.73, 4.886, -2.47 ] + }, + { "time": 4.9333, "value": -6.52 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.36, + "curve": [ 0.033, 10.36, 0.1, -32.89 ] + }, + { + "time": 0.1333, + "value": -32.89, + "curve": [ 0.183, -32.89, 0.283, -4.45 ] + }, + { + "time": 0.3333, + "value": -4.45, + "curve": [ 0.367, -4.45, 0.438, -6.86 ] + }, + { + "time": 0.4667, + "value": -8.99, + "curve": [ 0.529, -13.62, 0.605, -20.58 ] + }, + { + "time": 0.6333, + "value": -23.2, + "curve": [ 0.708, -30.18, 0.758, -35.56 ] + }, + { + "time": 0.8, + "value": -35.56, + "curve": [ 0.875, -35.56, 1.025, -23.2 ] + }, + { "time": 1.1, "value": -23.2 } + ] + }, + "gun": { + "rotate": [ + { + "value": -2.79, + "curve": [ 0.033, -2.79, 0.12, -7.22 ] + }, + { + "time": 0.1333, + "value": -8.52, + "curve": [ 0.168, -11.87, 0.29, -23.71 ] + }, + { + "time": 0.3333, + "value": -26.24, + "curve": [ 0.369, -28.31, 0.436, -29.75 ] + }, + { + "time": 0.5, + "value": -29.66, + "curve": [ 0.552, -29.58, 0.611, -25.47 ] + }, + { + "time": 0.6333, + "value": -22.68, + "curve": [ 0.656, -19.76, 0.68, -10.02 ] + }, + { + "time": 0.7, + "value": -6.49, + "curve": [ 0.722, -2.6, 0.75, -1.22 ] + }, + { + "time": 0.7667, + "value": -1.35, + "curve": [ 0.792, -1.55, 0.842, -19.74 ] + }, + { "time": 0.8667, "value": -19.8 } + ] + }, + "hip": { + "translate": [ + { + "curve": [ 0.098, -42.62, 0.166, -79.85, 0.029, 84.97, 0.109, 155.93 ] + }, + { + "time": 0.2667, + "x": -133.79, + "y": 152.44, + "curve": [ 0.361, -184.63, 0.392, -203.69, 0.42, 149.12, 0.467, -15.7 ] + }, + { + "time": 0.4667, + "x": -230.02, + "y": -113.87, + "curve": [ 0.523, -249.86, 0.565, -261.7, 0.473, -133.1, 0.583, -203.43 ] + }, + { + "time": 0.6, + "x": -268.57, + "y": -203.43, + "curve": [ 0.663, -280.98, 0.816, -290.05, 0.708, -203.43, 0.892, -203.5 ] + }, + { "time": 1, "x": -290.42, "y": -203.5 } + ] + }, + "front-thigh": { + "rotate": [ + { + "curve": [ 0.06, 1.02, 0.151, 45.23 ] + }, + { + "time": 0.1667, + "value": 54.01, + "curve": [ 0.19, 66.85, 0.358, 169.85 ] + }, + { + "time": 0.5, + "value": 169.51, + "curve": [ 0.628, 169.85, 0.692, 108.85 ] + }, + { + "time": 0.7, + "value": 97.74, + "curve": [ 0.723, 102.6, 0.805, 111.6 ] + }, + { + "time": 0.8667, + "value": 111.69, + "curve": [ 0.899, 111.83, 1.015, 109.15 ] + }, + { "time": 1.0667, "value": 95.8 } + ] + }, + "front-shin": { + "rotate": [ + { + "curve": [ 0.086, -0.02, 0.191, -24.25 ] + }, + { + "time": 0.2, + "value": -26.5, + "curve": [ 0.214, -29.92, 0.249, -40.51 ] + }, + { + "time": 0.3333, + "value": -40.57, + "curve": [ 0.431, -40.7, 0.459, -11.34 ] + }, + { + "time": 0.4667, + "value": -8.71, + "curve": [ 0.477, -5.16, 0.524, 17.13 ] + }, + { + "time": 0.6, + "value": 16.98, + "curve": [ 0.632, 17.09, 0.625, 2.76 ] + }, + { + "time": 0.6333, + "value": 2.76, + "curve": [ 0.648, 2.76, 0.653, 2.75 ] + }, + { + "time": 0.6667, + "value": 2.59, + "curve": [ 0.678, 2.39, 0.733, 2.53 ] + }, + { + "time": 0.7333, + "value": -9.43, + "curve": [ 0.745, -2.48, 0.782, 3.12 ] + }, + { + "time": 0.8, + "value": 4.28, + "curve": [ 0.832, 6.32, 0.895, 8.46 ] + }, + { + "time": 0.9333, + "value": 8.49, + "curve": [ 0.986, 8.53, 1.051, 6.38 ] + }, + { + "time": 1.0667, + "value": 2.28, + "curve": [ 1.078, 4.17, 1.103, 5.86 ] + }, + { + "time": 1.1333, + "value": 5.88, + "curve": [ 1.191, 5.93, 1.209, 4.56 ] + }, + { "time": 1.2333, "value": 2.52 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.12, 50.26 ] + }, + { + "time": 0.1333, + "value": 57.3, + "curve": [ 0.164, 73.34, 0.274, 147.18 ] + }, + { + "time": 0.3333, + "value": 147.1, + "curve": [ 0.475, 146.45, 0.583, 95.72 ] + }, + { + "time": 0.6, + "value": 79.66, + "curve": [ 0.62, 94.74, 0.732, 103.15 ] + }, + { + "time": 0.7667, + "value": 103.02, + "curve": [ 0.812, 102.85, 0.897, 95.75 ] + }, + { "time": 0.9333, "value": 83.01 } + ] + }, + "rear-shin": { + "rotate": [ + { + "curve": [ 0.021, -16.65, 0.091, -54.82 ] + }, + { + "time": 0.1667, + "value": -55.29, + "curve": [ 0.187, -55.42, 0.213, -52.52 ] + }, + { + "time": 0.2333, + "value": -45.98, + "curve": [ 0.242, -43.1, 0.311, -12.73 ] + }, + { + "time": 0.3333, + "value": -6.32, + "curve": [ 0.356, 0.13, 0.467, 24.5 ] + }, + { + "time": 0.5, + "value": 24.5, + "curve": [ 0.543, 24.5, 0.56, 3.78 ] + }, + { + "time": 0.5667, + "value": -3.53, + "curve": [ 0.585, 3.86, 0.659, 16.63 ] + }, + { + "time": 0.7, + "value": 16.56, + "curve": [ 0.782, 16.43, 0.896, 8.44 ] + }, + { + "time": 0.9333, + "value": 4.04, + "curve": [ 0.956, 6.84, 1.008, 8.41 ] + }, + { + "time": 1.0333, + "value": 8.41, + "curve": [ 1.067, 8.41, 1.122, 8.14 ] + }, + { "time": 1.1667, "value": 5.8 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -0.28, + "curve": [ 0.033, -0.28, 0.256, -66.71 ] + }, + { + "time": 0.3667, + "value": -66.84, + "curve": [ 0.418, -66.91, 0.499, -21.79 ] + }, + { + "time": 0.6, + "value": -21.52, + "curve": [ 0.652, -21.38, 0.665, -53.96 ] + }, + { + "time": 0.7, + "value": -54.26, + "curve": [ 0.757, -53.96, 0.843, -2.07 ] + }, + { + "time": 0.9333, + "value": -1.47, + "curve": [ 0.968, -2.07, 0.975, -19.96 ] + }, + { + "time": 1, + "value": -19.96, + "curve": [ 1.025, -19.96, 1.075, -12.42 ] + }, + { + "time": 1.1, + "value": -12.42, + "curve": [ 1.133, -12.42, 1.2, -18.34 ] + }, + { "time": 1.2333, "value": -18.34 } + ] + }, + "front-foot": { + "rotate": [ + { + "curve": [ 0.008, -11.33, 0.108, -57.71 ] + }, + { + "time": 0.1333, + "value": -57.71, + "curve": [ 0.175, -57.71, 0.229, 19.73 ] + }, + { + "time": 0.3, + "value": 19.34, + "curve": [ 0.354, 19.34, 0.4, -57.76 ] + }, + { + "time": 0.4333, + "value": -57.76, + "curve": [ 0.458, -57.76, 0.511, -3.56 ] + }, + { + "time": 0.5333, + "value": 3.7, + "curve": [ 0.563, 13.29, 0.633, 15.79 ] + }, + { + "time": 0.6667, + "value": 15.79, + "curve": [ 0.7, 15.79, 0.767, -48.75 ] + }, + { + "time": 0.8, + "value": -48.75, + "curve": [ 0.842, -48.75, 0.925, 4.7 ] + }, + { + "time": 0.9667, + "value": 4.7, + "curve": [ 1, 4.7, 1.067, -22.9 ] + }, + { + "time": 1.1, + "value": -22.9, + "curve": [ 1.142, -22.9, 1.225, -13.28 ] + }, + { "time": 1.2667, "value": -13.28 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": -0.28 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -0.28, + "curve": [ 0.008, -0.28, 0.003, -66.62 ] + }, + { + "time": 0.0667, + "value": -65.75, + "curve": [ 0.166, -64.42, 0.234, 14.35 ] + }, + { + "time": 0.2667, + "value": 38.25, + "curve": [ 0.294, 57.91, 0.392, 89.79 ] + }, + { + "time": 0.4667, + "value": 90.73, + "curve": [ 0.483, 90.73, 0.55, 177.66 ] + }, + { + "time": 0.5667, + "value": 177.66, + "curve": [ 0.733, 176.24, 0.75, 11.35 ] + }, + { + "time": 0.8, + "value": 11.35, + "curve": [ 0.886, 12.29, 0.911, 47.88 ] + }, + { + "time": 0.9333, + "value": 56.77, + "curve": [ 0.967, 70.59, 1.05, 86.46 ] + }, + { + "time": 1.1, + "value": 86.46, + "curve": [ 1.187, 86.46, 1.214, 66.44 ] + }, + { "time": 1.3333, "value": 64.55 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "value": -0.28, + "curve": [ 0, -7.97, 0.027, -18.69 ] + }, + { + "time": 0.0667, + "value": -19, + "curve": [ 0.166, -19.3, 0.208, 15.58 ] + }, + { + "time": 0.2667, + "value": 45.95, + "curve": [ 0.306, 66.24, 0.378, 99.08 ] + }, + { + "time": 0.4333, + "value": 99.08, + "curve": [ 0.497, 98.62, 0.488, -1.2 ] + }, + { + "time": 0.5667, + "value": -1.32, + "curve": [ 0.637, -0.84, 0.687, 94.41 ] + }, + { + "time": 0.7333, + "value": 94.33, + "curve": [ 0.832, 94.16, 0.895, 29.6 ] + }, + { + "time": 0.9667, + "value": 28.67, + "curve": [ 1.026, 28.67, 1.045, 53.14 ] + }, + { "time": 1.1, "value": 53.38 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.011, 4.5, 0.05, 11.42 ] + }, + { + "time": 0.0667, + "value": 11.42, + "curve": [ 0.1, 11.42, 0.136, -5.92 ] + }, + { + "time": 0.1667, + "value": -10.54, + "curve": [ 0.206, -16.51, 0.327, -22 ] + }, + { + "time": 0.3667, + "value": -24.47, + "curve": [ 0.413, -27.37, 0.467, -43.99 ] + }, + { + "time": 0.5, + "value": -43.99, + "curve": [ 0.533, -43.99, 0.552, 12.12 ] + }, + { + "time": 0.6333, + "value": 11.85, + "curve": [ 0.714, 11.59, 0.758, -34.13 ] + }, + { + "time": 0.8, + "value": -34.13, + "curve": [ 0.858, -34.13, 1.015, -12.47 ] + }, + { + "time": 1.0667, + "value": -8.85, + "curve": [ 1.121, -5.07, 1.219, -0.02 ] + }, + { + "time": 1.3333, + "value": 1.29, + "curve": [ 1.509, 3.3, 1.763, 2.75 ] + }, + { + "time": 1.8667, + "value": 2.78, + "curve": [ 1.974, 2.81, 2.108, 2.81 ] + }, + { + "time": 2.2, + "value": 2.78, + "curve": [ 2.315, 2.74, 2.374, 1.22 ] + }, + { + "time": 2.4667, + "value": 1.18, + "curve": [ 2.525, 1.18, 2.608, 10.79 ] + }, + { + "time": 2.6667, + "value": 10.79, + "curve": [ 2.725, 10.79, 2.893, 4.72 ] + }, + { + "time": 3.0333, + "value": 4.72, + "curve": [ 3.117, 4.72, 3.283, 7.93 ] + }, + { + "time": 3.3667, + "value": 7.93, + "curve": [ 3.492, 7.93, 3.775, 6.93 ] + }, + { + "time": 3.9, + "value": 6.93, + "curve": [ 3.981, 6.93, 4.094, 6.9 ] + }, + { + "time": 4.2, + "value": 8.44, + "curve": [ 4.267, 9.42, 4.401, 16.61 ] + }, + { + "time": 4.5, + "value": 16.33, + "curve": [ 4.582, 16.12, 4.709, 9.94 ] + }, + { + "time": 4.7333, + "value": 6.51, + "curve": [ 4.747, 4.57, 4.779, -1.76 ] + }, + { + "time": 4.8, + "value": -1.75, + "curve": [ 4.823, -1.73, 4.82, 4.47 ] + }, + { + "time": 4.8667, + "value": 6.04, + "curve": [ 4.899, 7.14, 4.913, 6.93 ] + }, + { "time": 4.9333, "value": 6.93 } + ] + }, + "hair2": { + "rotate": [ + { + "value": 10.61, + "curve": [ 0.075, 10.61, 0.05, 12.67 ] + }, + { + "time": 0.0667, + "value": 12.67, + "curve": [ 0.123, 12.67, 0.194, -16.51 ] + }, + { + "time": 0.2, + "value": -19.87, + "curve": [ 0.207, -23.48, 0.236, -31.68 ] + }, + { + "time": 0.3, + "value": -31.8, + "curve": [ 0.356, -31.9, 0.437, -25.61 ] + }, + { + "time": 0.4667, + "value": -19.29, + "curve": [ 0.485, -15.33, 0.529, 6.48 ] + }, + { + "time": 0.5667, + "value": 6.67, + "curve": [ 0.628, 6.97, 0.65, -46.39 ] + }, + { + "time": 0.7333, + "value": -46.3, + "curve": [ 0.843, -46.17, 0.941, -33.37 ] + }, + { + "time": 0.9667, + "value": -23.17, + "curve": [ 0.972, -20.98, 1.047, 15.21 ] + }, + { + "time": 1.1, + "value": 15.21, + "curve": [ 1.142, 15.21, 1.183, 10.73 ] + }, + { + "time": 1.2667, + "value": 10.61, + "curve": [ 1.45, 10.34, 1.817, 10.61 ] + }, + { + "time": 2, + "value": 10.61, + "curve": [ 2.075, 10.61, 2.225, 16.9 ] + }, + { + "time": 2.3, + "value": 16.9, + "curve": [ 2.327, 16.9, 2.347, 6.81 ] + }, + { + "time": 2.4, + "value": 6.83, + "curve": [ 2.492, 6.87, 2.602, 17.39 ] + }, + { + "time": 2.6667, + "value": 17.39, + "curve": [ 2.742, 17.39, 2.892, 10.67 ] + }, + { + "time": 2.9667, + "value": 10.64, + "curve": [ 3.187, 10.57, 3.344, 10.73 ] + }, + { + "time": 3.6, + "value": 11.4, + "curve": [ 3.766, 11.83, 3.874, 14.87 ] + }, + { + "time": 3.9333, + "value": 14.83, + "curve": [ 4.022, 14.76, 4.208, 9.49 ] + }, + { + "time": 4.3, + "value": 9.54, + "curve": [ 4.391, 9.58, 4.441, 14.82 ] + }, + { + "time": 4.5333, + "value": 14.84, + "curve": [ 4.642, 14.88, 4.692, 1.17 ] + }, + { + "time": 4.7667, + "value": 1.24, + "curve": [ 4.823, 1.3, 4.818, 18.35 ] + }, + { + "time": 4.8667, + "value": 18.38, + "curve": [ 4.905, 18.41, 4.901, 10.61 ] + }, + { "time": 4.9333, "value": 10.61 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.048, 0, 0.129, -12.73 ] + }, + { + "time": 0.1667, + "value": -15.95, + "curve": [ 0.221, -20.66, 0.254, -21.62 ] + }, + { + "time": 0.3, + "value": -21.59, + "curve": [ 0.458, -21.46, 0.46, -1.67 ] + }, + { + "time": 0.6333, + "value": -1.71, + "curve": [ 0.71, -1.73, 0.715, -4 ] + }, + { + "time": 0.7667, + "value": -3.97, + "curve": [ 0.866, -3.92, 0.84, 0.02 ] + }, + { "time": 1, "curve": "stepped" }, + { + "time": 2, + "curve": [ 2.275, 0, 2.867, -5.8 ] + }, + { + "time": 3.1, + "value": -6.44, + "curve": [ 3.327, -7.06, 3.71, -6.23 ] + }, + { + "time": 3.9333, + "value": -5.41, + "curve": [ 4.168, -4.53, 4.488, -2.83 ] + }, + { "time": 4.8 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.025, 0, 0.09, -3.66 ] + }, + { + "time": 0.1, + "value": -4.55, + "curve": [ 0.143, -8.4, 0.223, -17.07 ] + }, + { + "time": 0.2333, + "value": -18.31, + "curve": [ 0.282, -24.44, 0.35, -29 ] + }, + { + "time": 0.3667, + "value": -30.07, + "curve": [ 0.405, -32.58, 0.442, -33.03 ] + }, + { + "time": 0.4667, + "value": -32.99, + "curve": [ 0.491, -33.04, 0.505, -23.56 ] + }, + { + "time": 0.5333, + "value": -23.55, + "curve": [ 0.571, -23.67, 0.599, -27.21 ] + }, + { + "time": 0.6333, + "value": -27.21, + "curve": [ 0.669, -27.2, 0.742, -10.43 ] + }, + { + "time": 0.7667, + "value": -7.79, + "curve": [ 0.788, -5.53, 0.796, -4.42 ] + }, + { + "time": 0.8333, + "value": -2.9, + "curve": [ 0.875, -1.21, 0.933, 0 ] + }, + { "time": 0.9667, "curve": "stepped" }, + { + "time": 2.4333, + "curve": [ 2.517, 0, 2.683, 4.63 ] + }, + { + "time": 2.7667, + "value": 4.66, + "curve": [ 3.084, 4.76, 3.248, 4.37 ] + }, + { + "time": 3.4, + "value": 3.74, + "curve": [ 3.596, 2.92, 3.755, 2.18 ] + }, + { + "time": 3.8667, + "value": 1.72, + "curve": [ 4.136, 0.59, 4.471, 0 ] + }, + { "time": 4.8 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0, 0, 0.041, 10.74 ] + }, + { + "time": 0.0667, + "value": 14.16, + "curve": [ 0.075, 15.22, 0.148, 18.04 ] + }, + { + "time": 0.2, + "value": 18.13, + "curve": [ 0.251, 18.23, 0.307, -4.75 ] + }, + { + "time": 0.3667, + "value": -5.06, + "curve": [ 0.412, -5.3, 0.47, -0.96 ] + }, + { + "time": 0.5, + "value": 2.21, + "curve": [ 0.512, 3.48, 0.595, 20.31 ] + }, + { + "time": 0.6333, + "value": 24.87, + "curve": [ 0.647, 26.53, 0.719, 29.33 ] + }, + { + "time": 0.8, + "value": 29.22, + "curve": [ 0.859, 29.14, 0.9, 28.48 ] + }, + { + "time": 0.9333, + "value": 26.11, + "curve": [ 0.981, 22.72, 0.998, 2.06 ] + }, + { "time": 1.1, "value": 2.21 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.047, -0.21, 0.048, 7.86 ] + }, + { + "time": 0.0667, + "value": 13.27, + "curve": [ 0.083, 18.05, 0.135, 24.44 ] + }, + { + "time": 0.2, + "value": 24.02, + "curve": [ 0.225, 24.02, 0.28, 6.32 ] + }, + { + "time": 0.3, + "value": 3.1, + "curve": [ 0.323, -0.58, 0.382, -7.12 ] + }, + { + "time": 0.4667, + "value": -7.45, + "curve": [ 0.512, -7.66, 0.538, 12.13 ] + }, + { + "time": 0.5667, + "value": 16.46, + "curve": [ 0.609, 22.72, 0.672, 27.4 ] + }, + { + "time": 0.7333, + "value": 27.55, + "curve": [ 0.827, 27.4, 0.933, 23.23 ] + }, + { + "time": 0.9667, + "value": 19.11, + "curve": [ 0.998, 15.27, 1.092, -2.53 ] + }, + { + "time": 1.1333, + "value": -2.53, + "curve": [ 1.158, -2.53, 1.208, 0 ] + }, + { "time": 1.2333, "curve": "stepped" }, + { + "time": 2, + "curve": [ 2.075, 0, 2.248, 0.35 ] + }, + { + "time": 2.3333, + "value": 0.78, + "curve": [ 2.585, 2.06, 2.805, 3.46 ] + }, + { + "time": 3.2, + "value": 3.5, + "curve": [ 3.593, 3.54, 3.979, 2.36 ] + }, + { + "time": 4.1667, + "value": 1.55, + "curve": [ 4.391, 0.59, 4.447, 0.04 ] + }, + { + "time": 4.6, + "value": 0.04, + "curve": [ 4.642, 0.04, 4.742, 0 ] + }, + { "time": 4.9333 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.025, 0, 0.09, 1.43, 0.025, 0, 0.075, -34.76 ] + }, + { + "time": 0.1, + "x": 1.59, + "y": -34.76, + "curve": [ 0.214, 3.33, 0.375, 5.34, 0.192, -34.76, 0.441, -21.17 ] + }, + { + "time": 0.4667, + "x": 5.34, + "y": -12.57, + "curve": [ 0.492, 5.34, 0.55, 5.24, 0.482, -7.36, 0.504, 4.03 ] + }, + { + "time": 0.5667, + "x": 5.11, + "y": 4.01, + "curve": [ 0.658, 4.45, 0.679, 3.19, 0.649, 3.98, 0.642, -16.84 ] + }, + { + "time": 0.7, + "x": 2.8, + "y": -16.74, + "curve": [ 0.787, 1.15, 0.881, -1.29, 0.772, -16.62, 0.82, 8.95 ] + }, + { + "time": 0.9, + "x": -1.72, + "y": 8.91, + "curve": [ 0.961, -3.06, 1.025, -3.58, 0.975, 8.87, 0.951, -1.37 ] + }, + { + "time": 1.1, + "x": -3.58, + "y": -1.45, + "curve": [ 1.292, -3.58, 2.002, -2.4, 1.292, -1.56, 1.975, -1.45 ] + }, + { + "time": 2.1667, + "x": -1.39, + "y": -1.45, + "curve": [ 2.25, -0.88, 2.503, 1.38, 2.283, -1.45, 2.603, -12.44 ] + }, + { + "time": 2.6667, + "x": 2.13, + "y": -14.45, + "curve": [ 2.766, 2.59, 2.999, 2.81, 2.835, -19.73, 3.003, -25.2 ] + }, + { + "time": 3.1333, + "x": 2.91, + "y": -26.08, + "curve": [ 3.392, 3.1, 4.199, 4.05, 3.483, -28.44, 4.129, -27.23 ] + }, + { + "time": 4.3667, + "x": 4.81, + "y": -19.59, + "curve": [ 4.429, 5.1, 4.594, 8.54, 4.538, -14.08, 4.583, -7.88 ] + }, + { + "time": 4.6667, + "x": 8.65, + "y": -4.56, + "curve": [ 4.794, 8.86, 4.806, 5.93, 4.691, -3.59, 4.8, -1.61 ] + }, + { "time": 4.9333, "x": 5.8, "y": -1.99 } + ] + } + }, + "ik": { + "front-foot-ik": [ + { "mix": 0 } + ], + "front-leg-ik": [ + { "mix": 0, "bendPositive": false } + ], + "rear-foot-ik": [ + { "mix": 0.005 } + ], + "rear-leg-ik": [ + { "mix": 0.005, "bendPositive": false } + ] + } + }, + "hoverboard": { + "slots": { + "exhaust1": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "exhaust2": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "exhaust3": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "hoverboard-board": { + "attachment": [ + { "name": "hoverboard-board" } + ] + }, + "hoverboard-thruster-front": { + "attachment": [ + { "name": "hoverboard-thruster" } + ] + }, + "hoverboard-thruster-rear": { + "attachment": [ + { "name": "hoverboard-thruster" } + ] + }, + "hoverglow-front": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "hoverglow-rear": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "side-glow1": { + "attachment": [ + { "name": "hoverglow-small" }, + { "time": 0.9667 } + ] + }, + "side-glow2": { + "attachment": [ + { "time": 0.0667, "name": "hoverglow-small" }, + { "time": 1 } + ] + }, + "side-glow3": { + "attachment": [ + { "name": "hoverglow-small" }, + { "time": 0.9667 } + ] + } + }, + "bones": { + "hoverboard-controller": { + "translate": [ + { + "x": 319.55, + "y": -1.59, + "curve": [ 0.064, 319.55, 0.2, 347.85, 0.058, -1.2, 0.2, 23.11 ] + }, + { + "time": 0.2667, + "x": 347.66, + "y": 39.62, + "curve": [ 0.35, 347.41, 0.476, 341.47, 0.323, 53.58, 0.44, 85.82 ] + }, + { + "time": 0.5333, + "x": 338.47, + "y": 85.72, + "curve": [ 0.603, 334.83, 0.913, 319.65, 0.621, 85.62, 0.88, -1.53 ] + }, + { "time": 1, "x": 319.55, "y": -1.59 } + ] + }, + "hip": { + "translate": [ + { + "x": -53.49, + "y": 32.14, + "curve": [ 0.061, -53.77, 0.093, -51.81, 0.044, 16.34, 0.063, 9.67 ] + }, + { + "time": 0.1333, + "x": -49.31, + "y": 7.01, + "curve": [ 0.3, -35.27, 0.461, -20.06, 0.314, 9.52, 0.408, 121.09 ] + }, + { + "time": 0.5667, + "x": -20.06, + "y": 122.72, + "curve": [ 0.716, -20.09, 0.912, -53.29, 0.753, 121.8, 0.946, 51.85 ] + }, + { "time": 1, "x": -53.49, "y": 32.14 } + ] + }, + "exhaust1": { + "scale": [ + { + "x": 1.593, + "y": 0.964, + "curve": [ 0.033, 1.593, 0.1, 1, 0.033, 0.964, 0.1, 0.713 ] + }, + { + "time": 0.1333, + "y": 0.713, + "curve": [ 0.15, 1, 0.183, 1.774, 0.15, 0.713, 0.183, 0.883 ] + }, + { + "time": 0.2, + "x": 1.774, + "y": 0.883, + "curve": [ 0.242, 1.774, 0.325, 1.181, 0.242, 0.883, 0.325, 0.649 ] + }, + { + "time": 0.3667, + "x": 1.181, + "y": 0.649, + "curve": [ 0.408, 1.181, 0.492, 1.893, 0.408, 0.649, 0.492, 0.819 ] + }, + { + "time": 0.5333, + "x": 1.893, + "y": 0.819, + "curve": [ 0.558, 1.893, 0.608, 1.18, 0.558, 0.819, 0.608, 0.686 ] + }, + { + "time": 0.6333, + "x": 1.18, + "y": 0.686, + "curve": [ 0.658, 1.18, 0.708, 1.903, 0.658, 0.686, 0.708, 0.855 ] + }, + { + "time": 0.7333, + "x": 1.903, + "y": 0.855, + "curve": [ 0.767, 1.903, 0.833, 1.311, 0.767, 0.855, 0.833, 0.622 ] + }, + { + "time": 0.8667, + "x": 1.311, + "y": 0.622, + "curve": [ 0.9, 1.311, 0.967, 1.593, 0.9, 0.622, 0.967, 0.964 ] + }, + { "time": 1, "x": 1.593, "y": 0.964 } + ] + }, + "exhaust2": { + "scale": [ + { + "x": 1.88, + "y": 0.832, + "curve": [ 0.025, 1.88, 0.075, 1.311, 0.025, 0.832, 0.075, 0.686 ] + }, + { + "time": 0.1, + "x": 1.311, + "y": 0.686, + "curve": [ 0.133, 1.311, 0.2, 2.01, 0.133, 0.686, 0.208, 0.736 ] + }, + { + "time": 0.2333, + "x": 2.01, + "y": 0.769, + "curve": [ 0.267, 2.01, 0.333, 1, 0.282, 0.831, 0.333, 0.91 ] + }, + { + "time": 0.3667, + "y": 0.91, + "curve": [ 0.4, 1, 0.467, 1.699, 0.4, 0.91, 0.474, 0.891 ] + }, + { + "time": 0.5, + "x": 1.699, + "y": 0.86, + "curve": [ 0.517, 1.699, 0.55, 1.181, 0.54, 0.813, 0.55, 0.713 ] + }, + { + "time": 0.5667, + "x": 1.181, + "y": 0.713, + "curve": [ 0.617, 1.181, 0.717, 1.881, 0.617, 0.713, 0.717, 0.796 ] + }, + { + "time": 0.7667, + "x": 1.881, + "y": 0.796, + "curve": [ 0.8, 1.881, 0.867, 1.3, 0.8, 0.796, 0.867, 0.649 ] + }, + { + "time": 0.9, + "x": 1.3, + "y": 0.649, + "curve": [ 0.925, 1.3, 0.975, 1.88, 0.925, 0.649, 0.975, 0.832 ] + }, + { "time": 1, "x": 1.88, "y": 0.832 } + ] + }, + "hoverboard-thruster-front": { + "rotate": [ + { + "curve": [ 0.125, 0, 0.375, 24.06 ] + }, + { + "time": 0.5, + "value": 24.06, + "curve": [ 0.625, 24.06, 0.875, 0 ] + }, + { "time": 1 } + ] + }, + "hoverglow-front": { + "scale": [ + { + "x": 0.849, + "y": 1.764, + "curve": [ 0.017, 0.849, 0.05, 0.835, 0.017, 1.764, 0.05, 2.033 ] + }, + { + "time": 0.0667, + "x": 0.835, + "y": 2.033, + "curve": [ 0.092, 0.835, 0.142, 0.752, 0.092, 2.033, 0.142, 1.584 ] + }, + { + "time": 0.1667, + "x": 0.752, + "y": 1.584, + "curve": [ 0.183, 0.752, 0.217, 0.809, 0.183, 1.584, 0.217, 1.71 ] + }, + { + "time": 0.2333, + "x": 0.809, + "y": 1.71, + "curve": [ 0.25, 0.809, 0.283, 0.717, 0.25, 1.71, 0.283, 1.45 ] + }, + { + "time": 0.3, + "x": 0.717, + "y": 1.45, + "curve": [ 0.317, 0.717, 0.35, 0.777, 0.317, 1.45, 0.35, 1.698 ] + }, + { + "time": 0.3667, + "x": 0.777, + "y": 1.698, + "curve": [ 0.4, 0.781, 0.45, 0.685, 0.375, 1.698, 0.45, 1.173 ] + }, + { + "time": 0.4667, + "x": 0.685, + "y": 1.173, + "curve": [ 0.492, 0.685, 0.542, 0.825, 0.492, 1.173, 0.542, 1.572 ] + }, + { + "time": 0.5667, + "x": 0.825, + "y": 1.572, + "curve": [ 0.611, 0.816, 0.63, 0.727, 0.611, 1.577, 0.606, 1.255 ] + }, + { + "time": 0.6667, + "x": 0.725, + "y": 1.241, + "curve": [ 0.692, 0.725, 0.742, 0.895, 0.692, 1.241, 0.749, 1.799 ] + }, + { + "time": 0.7667, + "x": 0.895, + "y": 1.857, + "curve": [ 0.783, 0.895, 0.796, 0.892, 0.796, 1.955, 0.817, 1.962 ] + }, + { + "time": 0.8333, + "x": 0.845, + "y": 1.962, + "curve": [ 0.845, 0.831, 0.883, 0.802, 0.85, 1.962, 0.872, 1.704 ] + }, + { + "time": 0.9, + "x": 0.802, + "y": 1.491, + "curve": [ 0.917, 0.802, 0.95, 0.845, 0.907, 1.441, 0.936, 1.508 ] + }, + { + "time": 0.9667, + "x": 0.845, + "y": 1.627, + "curve": [ 0.975, 0.845, 0.992, 0.849, 0.973, 1.652, 0.992, 1.764 ] + }, + { "time": 1, "x": 0.849, "y": 1.764 } + ] + }, + "hoverboard-thruster-rear": { + "rotate": [ + { + "curve": [ 0.125, 0, 0.375, 24.06 ] + }, + { + "time": 0.5, + "value": 24.06, + "curve": [ 0.625, 24.06, 0.875, 0 ] + }, + { "time": 1 } + ] + }, + "hoverglow-rear": { + "scale": [ + { + "x": 0.845, + "y": 1.31, + "curve": [ 0.017, 0.845, 0.117, 0.899, 0.017, 1.31, 0.117, 2.033 ] + }, + { + "time": 0.1333, + "x": 0.899, + "y": 2.033, + "curve": [ 0.15, 0.899, 0.183, 0.752, 0.15, 2.033, 0.183, 1.574 ] + }, + { + "time": 0.2, + "x": 0.752, + "y": 1.574, + "curve": [ 0.225, 0.752, 0.275, 0.809, 0.225, 1.574, 0.275, 1.71 ] + }, + { + "time": 0.3, + "x": 0.809, + "y": 1.71, + "curve": [ 0.317, 0.809, 0.35, 0.717, 0.317, 1.71, 0.35, 1.397 ] + }, + { + "time": 0.3667, + "x": 0.717, + "y": 1.397, + "curve": [ 0.383, 0.717, 0.417, 0.777, 0.383, 1.397, 0.417, 1.45 ] + }, + { + "time": 0.4333, + "x": 0.777, + "y": 1.45, + "curve": [ 0.45, 0.777, 0.496, 0.689, 0.45, 1.45, 0.481, 1.168 ] + }, + { + "time": 0.5333, + "x": 0.685, + "y": 1.173, + "curve": [ 0.565, 0.682, 0.617, 0.758, 0.575, 1.177, 0.617, 1.297 ] + }, + { + "time": 0.6333, + "x": 0.758, + "y": 1.297, + "curve": [ 0.658, 0.758, 0.708, 0.725, 0.658, 1.297, 0.708, 1.241 ] + }, + { + "time": 0.7333, + "x": 0.725, + "y": 1.241, + "curve": [ 0.772, 0.732, 0.796, 0.893, 0.782, 1.238, 0.778, 1.854 ] + }, + { + "time": 0.8333, + "x": 0.895, + "y": 1.857, + "curve": [ 0.878, 0.9, 0.992, 0.845, 0.88, 1.86, 0.992, 1.31 ] + }, + { "time": 1, "x": 0.845, "y": 1.31 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -85.92, + "curve": [ 0.08, -85.59, 0.284, -62.7 ] + }, + { + "time": 0.3667, + "value": -55.14, + "curve": [ 0.438, -48.65, 0.551, -43.21 ] + }, + { + "time": 0.6333, + "value": -43.21, + "curve": [ 0.716, -43.22, 0.908, -85.92 ] + }, + { "time": 1, "value": -85.92 } + ], + "translate": [ + { + "x": -0.59, + "y": -2.94, + "curve": [ 0.1, -1.21, 0.275, -1.74, 0.092, -2.94, 0.275, -6.39 ] + }, + { + "time": 0.3667, + "x": -1.74, + "y": -6.39, + "curve": [ 0.433, -1.74, 0.567, 0.72, 0.433, -6.39, 0.587, -4.48 ] + }, + { + "time": 0.6333, + "x": 0.72, + "y": -4.21, + "curve": [ 0.725, 0.72, 0.908, -0.08, 0.743, -3.57, 0.908, -2.94 ] + }, + { "time": 1, "x": -0.59, "y": -2.94 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": 7.61, + "curve": [ 0.143, 7.62, 0.247, -23.17 ] + }, + { + "time": 0.2667, + "value": -26.56, + "curve": [ 0.281, -29.08, 0.351, -37.36 ] + }, + { + "time": 0.4333, + "value": -37.2, + "curve": [ 0.513, -37.05, 0.562, -29.88 ] + }, + { + "time": 0.6, + "value": -25.18, + "curve": [ 0.621, -22.58, 0.694, -3.98 ] + }, + { + "time": 0.8, + "value": 3.63, + "curve": [ 0.861, 8.03, 0.946, 7.57 ] + }, + { "time": 1, "value": 7.61 } + ], + "translate": [ + { + "curve": [ 0.117, 0, 0.35, 0.52, 0.117, 0, 0.35, -3.27 ] + }, + { + "time": 0.4667, + "x": 0.52, + "y": -3.27, + "curve": [ 0.6, 0.52, 0.867, 0, 0.6, -3.27, 0.867, 0 ] + }, + { "time": 1 } + ], + "shear": [ + { + "y": 19.83, + "curve": [ 0.117, 0, 0.35, 15.28, 0.117, 19.83, 0.35, 28.31 ] + }, + { + "time": 0.4667, + "x": 15.28, + "y": 28.31, + "curve": [ 0.6, 15.28, 0.867, 0, 0.6, 28.31, 0.867, 19.83 ] + }, + { "time": 1, "y": 19.83 } + ] + }, + "board-ik": { + "translate": [ + { + "x": 393.62, + "curve": [ 0.083, 393.62, 0.25, 393.48, 0.083, 0, 0.25, 117.69 ] + }, + { + "time": 0.3333, + "x": 393.48, + "y": 117.69, + "curve": [ 0.375, 393.48, 0.458, 393.62, 0.375, 117.69, 0.458, 83.82 ] + }, + { "time": 0.5, "x": 393.62, "y": 83.82 }, + { "time": 0.6667, "x": 393.62, "y": 30.15 }, + { "time": 1, "x": 393.62 } + ] + }, + "front-thigh": { + "translate": [ + { "x": -7.49, "y": 8.51 } + ] + }, + "front-leg-target": { + "translate": [ + { + "time": 0.3667, + "curve": [ 0.428, 10.83, 0.567, 12.78, 0.414, 7.29, 0.567, 8.79 ] + }, + { + "time": 0.6, + "x": 12.78, + "y": 8.79, + "curve": [ 0.692, 12.78, 0.772, 11.27, 0.692, 8.79, 0.766, 8.62 ] + }, + { "time": 0.8667 } + ] + }, + "rear-leg-target": { + "translate": [ + { + "time": 0.4667, + "curve": [ 0.492, 0, 0.534, 4.47, 0.492, 0, 0.542, 1.63 ] + }, + { + "time": 0.5667, + "x": 4.53, + "y": 1.77, + "curve": [ 0.622, 4.64, 0.717, 3.31, 0.615, 2.06, 0.71, 2.1 ] + }, + { "time": 0.8 } + ] + }, + "exhaust3": { + "scale": [ + { + "x": 1.882, + "y": 0.81, + "curve": [ 0.017, 1.882, 0.167, 1.3, 0.017, 0.81, 0.167, 0.649 ] + }, + { + "time": 0.2, + "x": 1.3, + "y": 0.649, + "curve": [ 0.225, 1.3, 0.275, 2.051, 0.225, 0.649, 0.275, 0.984 ] + }, + { + "time": 0.3, + "x": 2.051, + "y": 0.984, + "curve": [ 0.325, 2.051, 0.375, 1.311, 0.325, 0.984, 0.384, 0.715 ] + }, + { + "time": 0.4, + "x": 1.311, + "y": 0.686, + "curve": [ 0.433, 1.311, 0.5, 1.86, 0.426, 0.638, 0.5, 0.537 ] + }, + { + "time": 0.5333, + "x": 1.86, + "y": 0.537, + "curve": [ 0.567, 1.86, 0.633, 1.187, 0.567, 0.537, 0.604, 0.854 ] + }, + { + "time": 0.6667, + "x": 1.187, + "y": 0.854, + "curve": [ 0.7, 1.187, 0.767, 1.549, 0.707, 0.854, 0.774, 0.775 ] + }, + { + "time": 0.8, + "x": 1.549, + "y": 0.746, + "curve": [ 0.817, 1.549, 0.85, 1.181, 0.815, 0.729, 0.85, 0.713 ] + }, + { + "time": 0.8667, + "x": 1.181, + "y": 0.713, + "curve": [ 0.9, 1.181, 0.967, 1.882, 0.9, 0.713, 0.967, 0.81 ] + }, + { "time": 1, "x": 1.882, "y": 0.81 } + ] + }, + "side-glow1": { + "rotate": [ + { "value": 51.12, "curve": "stepped" }, + { "time": 0.0667, "value": 43.82, "curve": "stepped" }, + { "time": 0.1, "value": 40.95, "curve": "stepped" }, + { "time": 0.1667, "value": 27.78, "curve": "stepped" }, + { "time": 0.2, "value": 10.24, "curve": "stepped" }, + { "time": 0.2667, "curve": "stepped" }, + { "time": 0.8, "value": -25.81 } + ], + "translate": [ + { "x": 338.28, "y": 40.22, "curve": "stepped" }, + { "time": 0.0667, "x": 331.2, "y": 30.39, "curve": "stepped" }, + { "time": 0.1, "x": 318.63, "y": 20.59, "curve": "stepped" }, + { "time": 0.1667, "x": 302.45, "y": 9.64, "curve": "stepped" }, + { "time": 0.2, "x": 276.87, "y": 1.13, "curve": "stepped" }, + { "time": 0.2667, "x": 248.16, "curve": "stepped" }, + { "time": 0.3, "x": 221.36, "curve": "stepped" }, + { "time": 0.3667, "x": 195.69, "curve": "stepped" }, + { "time": 0.4, "x": 171.08, "curve": "stepped" }, + { "time": 0.4667, "x": 144.84, "curve": "stepped" }, + { "time": 0.5, "x": 121.22, "curve": "stepped" }, + { "time": 0.5667, "x": 91.98, "curve": "stepped" }, + { "time": 0.6, "x": 62.63, "curve": "stepped" }, + { "time": 0.6667, "x": 30.78, "curve": "stepped" }, + { "time": 0.7, "curve": "stepped" }, + { "time": 0.7667, "x": -28.45, "curve": "stepped" }, + { "time": 0.8, "x": -67.49, "y": 16.82, "curve": "stepped" }, + { "time": 0.8667, "x": -83.07, "y": 24.36, "curve": "stepped" }, + { "time": 0.9, "x": -93.81, "y": 29.55 } + ], + "scale": [ + { "x": 0.535, "curve": "stepped" }, + { "time": 0.0667, "x": 0.594, "curve": "stepped" }, + { "time": 0.1, "x": 0.844, "curve": "stepped" }, + { "time": 0.1667, "curve": "stepped" }, + { "time": 0.8, "x": 0.534, "curve": "stepped" }, + { "time": 0.8667, "x": 0.428, "y": 0.801, "curve": "stepped" }, + { "time": 0.9, "x": 0.349, "y": 0.654 } + ] + }, + "side-glow2": { + "rotate": [ + { "time": 0.0667, "value": 51.12, "curve": "stepped" }, + { "time": 0.1, "value": 43.82, "curve": "stepped" }, + { "time": 0.1667, "value": 40.95, "curve": "stepped" }, + { "time": 0.2, "value": 27.78, "curve": "stepped" }, + { "time": 0.2667, "value": 10.24, "curve": "stepped" }, + { "time": 0.3, "curve": "stepped" }, + { "time": 0.8667, "value": -25.81 } + ], + "translate": [ + { "time": 0.0667, "x": 338.28, "y": 40.22, "curve": "stepped" }, + { "time": 0.1, "x": 331.2, "y": 30.39, "curve": "stepped" }, + { "time": 0.1667, "x": 318.63, "y": 20.59, "curve": "stepped" }, + { "time": 0.2, "x": 302.45, "y": 9.64, "curve": "stepped" }, + { "time": 0.2667, "x": 276.87, "y": 1.13, "curve": "stepped" }, + { "time": 0.3, "x": 248.16, "curve": "stepped" }, + { "time": 0.3667, "x": 221.36, "curve": "stepped" }, + { "time": 0.4, "x": 195.69, "curve": "stepped" }, + { "time": 0.4667, "x": 171.08, "curve": "stepped" }, + { "time": 0.5, "x": 144.84, "curve": "stepped" }, + { "time": 0.5667, "x": 121.22, "curve": "stepped" }, + { "time": 0.6, "x": 91.98, "curve": "stepped" }, + { "time": 0.6667, "x": 62.63, "curve": "stepped" }, + { "time": 0.7, "x": 30.78, "curve": "stepped" }, + { "time": 0.7667, "curve": "stepped" }, + { "time": 0.8, "x": -28.45, "curve": "stepped" }, + { "time": 0.8667, "x": -67.49, "y": 16.82, "curve": "stepped" }, + { "time": 0.9, "x": -83.07, "y": 24.36, "curve": "stepped" }, + { "time": 0.9667, "x": -93.81, "y": 29.55 } + ], + "scale": [ + { "time": 0.0667, "x": 0.535, "curve": "stepped" }, + { "time": 0.1, "x": 0.594, "curve": "stepped" }, + { "time": 0.1667, "x": 0.844, "curve": "stepped" }, + { "time": 0.2, "curve": "stepped" }, + { "time": 0.8667, "x": 0.534, "curve": "stepped" }, + { "time": 0.9, "x": 0.428, "y": 0.801, "curve": "stepped" }, + { "time": 0.9667, "x": 0.349, "y": 0.654 } + ] + }, + "torso": { + "rotate": [ + { + "value": -34.73, + "curve": [ 0.034, -36.31, 0.162, -39.33 ] + }, + { + "time": 0.2667, + "value": -39.37, + "curve": [ 0.384, -39.37, 0.491, -29.52 ] + }, + { + "time": 0.5, + "value": -28.86, + "curve": [ 0.525, -26.95, 0.571, -21.01 ] + }, + { + "time": 0.6333, + "value": -21.01, + "curve": [ 0.725, -21.01, 0.969, -33.35 ] + }, + { "time": 1, "value": -34.73 } + ] + }, + "neck": { + "rotate": [ + { + "value": 10.2, + "curve": [ 0.07, 12.09, 0.189, 16.03 ] + }, + { + "time": 0.2667, + "value": 16.14, + "curve": [ 0.333, 16.14, 0.449, 8.03 ] + }, + { + "time": 0.5, + "value": 5.83, + "curve": [ 0.542, 4.02, 0.6, 2.68 ] + }, + { + "time": 0.6333, + "value": 2.68, + "curve": [ 0.725, 2.68, 0.943, 8.57 ] + }, + { "time": 1, "value": 10.2 } + ] + }, + "head": { + "rotate": [ + { + "value": 10.2, + "curve": [ 0.044, 11.52, 0.2, 16.12 ] + }, + { + "time": 0.2667, + "value": 16.14, + "curve": [ 0.375, 16.17, 0.492, 2.65 ] + }, + { + "time": 0.6333, + "value": 2.68, + "curve": [ 0.725, 2.7, 0.963, 9.26 ] + }, + { "time": 1, "value": 10.2 } + ], + "translate": [ + { + "curve": [ 0.03, -0.24, 0.2, -4.22, 0.051, -1.06, 0.2, -3.62 ] + }, + { + "time": 0.2667, + "x": -4.22, + "y": -3.62, + "curve": [ 0.358, -4.22, 0.542, 0.84, 0.358, -3.62, 0.542, 6.01 ] + }, + { + "time": 0.6333, + "x": 0.84, + "y": 6.01, + "curve": [ 0.725, 0.84, 0.939, 0.32, 0.725, 6.01, 0.945, 1.14 ] + }, + { "time": 1 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": -11.18, + "curve": [ 0.064, -14.82, 0.25, -20.01 ] + }, + { + "time": 0.3333, + "value": -20.01, + "curve": [ 0.429, -20.12, 0.58, 5.12 ] + }, + { + "time": 0.6, + "value": 8.67, + "curve": [ 0.617, 11.72, 0.687, 20.52 ] + }, + { + "time": 0.7667, + "value": 20.55, + "curve": [ 0.848, 20.7, 0.963, -9.43 ] + }, + { "time": 1, "value": -11.18 } + ] + }, + "hair3": { + "rotate": [ + { + "value": 9.61, + "curve": [ 0.014, 8.51, 0.075, 2.63 ] + }, + { + "time": 0.1, + "value": 2.63, + "curve": [ 0.15, 2.63, 0.25, 13.52 ] + }, + { + "time": 0.3, + "value": 13.52, + "curve": [ 0.35, 13.52, 0.45, 11.28 ] + }, + { + "time": 0.5, + "value": 11.28, + "curve": [ 0.575, 11.28, 0.725, 18.13 ] + }, + { + "time": 0.8, + "value": 18.13, + "curve": [ 0.85, 18.13, 0.978, 11.07 ] + }, + { "time": 1, "value": 9.61 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -17.7, + "curve": [ 0.008, -17.7, 0.025, -23.73 ] + }, + { + "time": 0.0333, + "value": -23.73, + "curve": [ 0.067, -23.73, 0.154, -4.4 ] + }, + { + "time": 0.1667, + "value": -1.92, + "curve": [ 0.197, 4.09, 0.236, 12.91 ] + }, + { + "time": 0.2667, + "value": 17.56, + "curve": [ 0.301, 22.68, 0.342, 27.97 ] + }, + { + "time": 0.3667, + "value": 27.97, + "curve": [ 0.4, 27.97, 0.467, -1.45 ] + }, + { + "time": 0.5, + "value": -1.45, + "curve": [ 0.517, -1.45, 0.55, 3.16 ] + }, + { + "time": 0.5667, + "value": 3.16, + "curve": [ 0.583, 3.16, 0.617, -8.9 ] + }, + { + "time": 0.6333, + "value": -8.9, + "curve": [ 0.642, -8.9, 0.658, -5.4 ] + }, + { + "time": 0.6667, + "value": -5.4, + "curve": [ 0.683, -5.4, 0.717, -15.32 ] + }, + { + "time": 0.7333, + "value": -15.32, + "curve": [ 0.75, -15.32, 0.783, -9.19 ] + }, + { + "time": 0.8, + "value": -9.19, + "curve": [ 0.817, -9.19, 0.85, -23.6 ] + }, + { + "time": 0.8667, + "value": -23.6, + "curve": [ 0.883, -23.6, 0.917, -17.38 ] + }, + { + "time": 0.9333, + "value": -17.38, + "curve": [ 0.942, -17.38, 0.958, -20.46 ] + }, + { + "time": 0.9667, + "value": -20.46, + "curve": [ 0.975, -20.46, 0.992, -17.7 ] + }, + { "time": 1, "value": -17.7 } + ] + }, + "hair1": { + "rotate": [ + { + "value": 9.61, + "curve": [ 0.06, 9.04, 0.25, 8.9 ] + }, + { + "time": 0.3333, + "value": 8.9, + "curve": [ 0.392, 8.9, 0.508, 14.58 ] + }, + { + "time": 0.5667, + "value": 14.58, + "curve": [ 0.675, 14.58, 0.956, 10.28 ] + }, + { "time": 1, "value": 9.61 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -3.82, + "curve": [ 0.017, -3.82, 0.064, -9.16 ] + }, + { + "time": 0.1333, + "value": -9.09, + "curve": [ 0.178, -9.04, 0.234, 1.29 ] + }, + { + "time": 0.2667, + "value": 5.98, + "curve": [ 0.276, 7.27, 0.336, 17.1 ] + }, + { + "time": 0.3667, + "value": 17.1, + "curve": [ 0.413, 17.1, 0.467, 1.59 ] + }, + { + "time": 0.5, + "value": 1.59, + "curve": [ 0.533, 1.59, 0.567, 13.63 ] + }, + { + "time": 0.6, + "value": 13.63, + "curve": [ 0.617, 13.63, 0.683, 0.78 ] + }, + { + "time": 0.7, + "value": 0.78, + "curve": [ 0.717, 0.78, 0.75, 12.01 ] + }, + { + "time": 0.7667, + "value": 11.9, + "curve": [ 0.792, 11.73, 0.817, -0.85 ] + }, + { + "time": 0.8333, + "value": -0.85, + "curve": [ 0.85, -0.85, 0.88, 1.99 ] + }, + { + "time": 0.9, + "value": 1.82, + "curve": [ 0.916, 1.68, 0.95, -6.9 ] + }, + { + "time": 0.9667, + "value": -6.9, + "curve": [ 0.975, -6.9, 0.992, -3.82 ] + }, + { "time": 1, "value": -3.82 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 31.65, + "curve": [ 0.108, 31.65, 0.325, 13.01 ] + }, + { + "time": 0.4333, + "value": 13.01, + "curve": [ 0.71, 13.01, 0.917, 31.65 ] + }, + { "time": 1, "value": 31.65 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 31, + "curve": [ 0.108, 31, 0.325, 12.76 ] + }, + { + "time": 0.4333, + "value": 12.79, + "curve": [ 0.587, 12.82, 0.917, 31 ] + }, + { "time": 1, "value": 31 } + ] + }, + "gun": { + "rotate": [ + { + "value": 1.95, + "curve": [ 0.083, 1.95, 0.245, 36.73 ] + }, + { + "time": 0.3333, + "value": 36.71, + "curve": [ 0.439, 36.69, 0.589, 10.68 ] + }, + { + "time": 0.6333, + "value": 8.75, + "curve": [ 0.701, 5.81, 0.917, 1.95 ] + }, + { "time": 1, "value": 1.95 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 2.35 ] + }, + { + "time": 0.1333, + "value": 2.35, + "curve": [ 0.225, 2.35, 0.408, -2.4 ] + }, + { + "time": 0.5, + "value": -2.4, + "curve": [ 0.567, -2.4, 0.7, 1.44 ] + }, + { + "time": 0.7667, + "value": 1.44, + "curve": [ 0.825, 1.44, 0.942, 0 ] + }, + { "time": 1 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.063, 0.77, 0.106, 1.42 ] + }, + { + "time": 0.1667, + "value": 1.42, + "curve": [ 0.259, 1.42, 0.344, -1.25 ] + }, + { + "time": 0.4667, + "value": -1.26, + "curve": [ 0.656, -1.26, 0.917, -0.78 ] + }, + { "time": 1 } + ] + }, + "head-control": { + "translate": [ + { + "x": 0.37, + "y": -11.17, + "curve": [ 0.133, 0.37, 0.335, -10.23, 0.133, -11.17, 0.335, 3.15 ] + }, + { + "time": 0.5333, + "x": -10.23, + "y": 3.15, + "curve": [ 0.71, -10.23, 0.883, 0.37, 0.71, 3.15, 0.883, -11.17 ] + }, + { "time": 1, "x": 0.37, "y": -11.17 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.46, + "y": 10.15, + "curve": [ 0.103, 1.46, 0.249, 1.36, 0.103, 10.15, 0.249, -4.39 ] + }, + { + "time": 0.4, + "x": 1.36, + "y": -4.39, + "curve": [ 0.621, 1.36, 0.85, 1.46, 0.621, -4.39, 0.85, 10.15 ] + }, + { "time": 1, "x": 1.46, "y": 10.15 } + ] + }, + "back-shoulder": { + "translate": [ + { + "x": 1.4, + "y": 0.44, + "curve": [ 0.088, 1.4, 0.208, -2.47, 0.088, 0.44, 0.208, 8.61 ] + }, + { + "time": 0.3333, + "x": -2.47, + "y": 8.61, + "curve": [ 0.572, -2.47, 0.833, 1.4, 0.572, 8.61, 0.833, 0.44 ] + }, + { "time": 1, "x": 1.4, "y": 0.44 } + ] + } + }, + "transform": { + "front-foot-board-transform": [ + { "mixRotate": 0.997 } + ], + "rear-foot-board-transform": [ + {} + ], + "toes-board": [ + { "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ] + }, + "attachments": { + "default": { + "front-foot": { + "front-foot": { + "deform": [ + { + "offset": 26, + "vertices": [ -0.02832, -5.37024, -0.02832, -5.37024, 3.8188, -3.7757, -0.02832, -5.37024, -3.82159, 3.77847 ] + } + ] + } + }, + "front-shin": { + "front-shin": { + "deform": [ + { + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + }, + { + "time": 0.3667, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -11.66571, -9.07211, -25.65866, -17.53735, -25.53217, -16.50978, -11.78232, -11.26097, 0, 0, 0.60487, -1.63589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0, 0, -2.64522, -7.35739, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0.60487, -1.63589, 0.60487, -1.63589, 0.60487, -1.63589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0, 0, -10.06873, -12.0999 ] + }, + { + "time": 0.5333, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -7.00775, -8.24771, -6.45482, -6.49312, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + }, + { + "time": 1, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + } + ] + } + }, + "hoverboard-board": { + "hoverboard-board": { + "deform": [ + { + "curve": [ 0.067, 0, 0.2, 1 ] + }, + { + "time": 0.2667, + "offset": 1, + "vertices": [ 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 3.55673, -3.0E-4, 3.55673, -3.0E-4, 0, 0, 0, 0, 0, 0, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, 0, 0, 0, 0, 0, 0, 0, 0, -4.90558, 0.11214, -9.40706, 6.2E-4, -6.34871, 4.3E-4, -6.34925, -6.57018, -6.34925, -6.57018, -6.34871, 4.3E-4, -2.3308, 1.7E-4, -2.33133, -6.57045, -2.33133, -6.57045, -2.3308, 1.7E-4, 0, 0, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 3.3297, 4.44005, 3.3297, 4.44005, 3.3297, 4.44005, 1.2E-4, 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, 1.2E-4, 2.45856, 1.2E-4, 2.45856, -9.40694, 2.45918, 1.88063, 0.44197, -2.9E-4, -3.54808, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.46227, 1.7E-4, 0, 0, 0, 0, 1.2E-4, 2.45856 ], + "curve": [ 0.45, 0, 0.817, 1 ] + }, + { "time": 1 } + ] + } + }, + "rear-foot": { + "rear-foot": { + "deform": [ + { + "offset": 28, + "vertices": [ -1.93078, 1.34782, -0.31417, 2.33363, 3.05122, 0.33946, 2.31472, -2.01678, 2.17583, -2.05795, -0.04277, -2.99459, 1.15429, 0.26328, 0.97501, -0.67169 ] + } + ] + } + } + } + } + }, + "idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-foot-target": { + "translate": [ + { "x": -69.06 } + ] + }, + "hip": { + "rotate": [ + { + "curve": [ 0.073, 0.35, 0.303, 1.27 ] + }, + { + "time": 0.4, + "value": 1.28, + "curve": [ 0.615, 1.3, 0.847, -1.41 ] + }, + { + "time": 1.2, + "value": -1.38, + "curve": [ 1.344, -1.37, 1.602, -0.28 ] + }, + { "time": 1.6667 } + ], + "translate": [ + { + "x": -11.97, + "y": -23.15, + "curve": [ 0.059, -12.96, 0.258, -15.19, 0.142, -23.15, 0.341, -24.89 ] + }, + { + "time": 0.4667, + "x": -15.14, + "y": -26.74, + "curve": [ 0.62, -15.1, 0.788, -13.28, 0.597, -28.66, 0.75, -30.01 ] + }, + { + "time": 0.9, + "x": -12.02, + "y": -30.01, + "curve": [ 0.978, -11.13, 1.175, -9.05, 1.036, -29.94, 1.234, -28.08 ] + }, + { + "time": 1.3333, + "x": -9.06, + "y": -26.64, + "curve": [ 1.501, -9.06, 1.614, -10.95, 1.454, -24.89, 1.609, -23.15 ] + }, + { "time": 1.6667, "x": -11.97, "y": -23.15 } + ] + }, + "rear-foot-target": { + "translate": [ + { "x": 48.87 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -60.87, + "curve": [ 0.154, -60.85, 0.452, -68.65 ] + }, + { + "time": 0.8333, + "value": -68.65, + "curve": [ 1.221, -68.65, 1.542, -60.87 ] + }, + { "time": 1.6667, "value": -60.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 42.46, + "curve": [ 0.029, 42.97, 0.134, 45.28 ] + }, + { + "time": 0.3333, + "value": 45.27, + "curve": [ 0.578, 45.26, 0.798, 40.07 ] + }, + { + "time": 0.8333, + "value": 39.74, + "curve": [ 0.878, 39.32, 1.019, 38.23 ] + }, + { + "time": 1.2, + "value": 38.22, + "curve": [ 1.377, 38.22, 1.619, 41.68 ] + }, + { "time": 1.6667, "value": 42.46 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 39.2, + "curve": [ 0.185, 39.22, 0.5, 29.37 ] + }, + { + "time": 0.6667, + "value": 29.37, + "curve": [ 0.917, 29.37, 1.417, 39.2 ] + }, + { "time": 1.6667, "value": 39.2 } + ] + }, + "head": { + "rotate": [ + { + "value": -6.75, + "curve": [ 0.176, -7.88, 0.349, -8.95 ] + }, + { + "time": 0.4667, + "value": -8.95, + "curve": [ 0.55, -8.95, 0.697, -6.77 ] + }, + { + "time": 0.8333, + "value": -5.44, + "curve": [ 0.88, -4.98, 1.05, -4.12 ] + }, + { + "time": 1.1333, + "value": -4.12, + "curve": [ 1.266, -4.12, 1.469, -5.48 ] + }, + { "time": 1.6667, "value": -6.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "curve": [ 0.086, 0, 0.233, 2.48 ] + }, + { + "time": 0.3333, + "value": 4.13, + "curve": [ 0.429, 5.7, 0.711, 10.06 ] + }, + { + "time": 0.8333, + "value": 10.06, + "curve": [ 0.926, 10.06, 1.092, 4.21 ] + }, + { + "time": 1.2, + "value": 2.78, + "curve": [ 1.349, 0.8, 1.551, 0 ] + }, + { "time": 1.6667 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "curve": [ 0.063, 0.54, 0.367, 3.39 ] + }, + { + "time": 0.5333, + "value": 3.39, + "curve": [ 0.696, 3.39, 0.939, -1.63 ] + }, + { + "time": 1.2, + "value": -1.61, + "curve": [ 1.42, -1.59, 1.574, -0.67 ] + }, + { "time": 1.6667 } + ] + }, + "gun": { + "rotate": [ + { + "curve": [ 0.099, 0.27, 0.367, 1.23 ] + }, + { + "time": 0.5333, + "value": 1.23, + "curve": [ 0.665, 1.23, 0.937, -0.56 ] + }, + { + "time": 1.1333, + "value": -0.55, + "curve": [ 1.316, -0.55, 1.582, -0.21 ] + }, + { "time": 1.6667 } + ] + }, + "torso": { + "rotate": [ + { + "value": -22.88, + "curve": [ 0.099, -23.45, 0.363, -24.74 ] + }, + { + "time": 0.5333, + "value": -24.74, + "curve": [ 0.706, -24.74, 0.961, -20.97 ] + }, + { + "time": 1.1333, + "value": -20.97, + "curve": [ 1.355, -20.97, 1.567, -22.28 ] + }, + { "time": 1.6667, "value": -22.88 } + ] + }, + "neck": { + "rotate": [ + { + "value": 3.78, + "curve": [ 0.167, 3.78, 0.5, 5.45 ] + }, + { + "time": 0.6667, + "value": 5.45, + "curve": [ 0.917, 5.45, 1.417, 3.78 ] + }, + { "time": 1.6667, "value": 3.78 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.067, 0.33, 0.341, 2.54 ] + }, + { + "time": 0.5333, + "value": 2.54, + "curve": [ 0.734, 2.55, 0.982, -0.94 ] + }, + { + "time": 1.1333, + "value": -0.93, + "curve": [ 1.365, -0.91, 1.549, -0.56 ] + }, + { "time": 1.6667 } + ] + }, + "torso3": { + "rotate": [ + { + "value": -2.15, + "curve": [ 0.052, -1.9, 0.384, -0.15 ] + }, + { + "time": 0.5333, + "value": -0.14, + "curve": [ 0.762, -0.13, 0.895, -3.1 ] + }, + { + "time": 1.1333, + "value": -3.1, + "curve": [ 1.348, -3.1, 1.592, -2.46 ] + }, + { "time": 1.6667, "value": -2.15 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.067, 0, 0.213, 2.86 ] + }, + { + "time": 0.2667, + "value": 3.65, + "curve": [ 0.358, 4.99, 0.535, 7.92 ] + }, + { + "time": 0.6667, + "value": 7.92, + "curve": [ 0.809, 7.92, 1.067, 5.49 ] + }, + { + "time": 1.1333, + "value": 4.7, + "curve": [ 1.245, 3.34, 1.525, 0 ] + }, + { "time": 1.6667 } + ] + }, + "hair2": { + "rotate": [ + { + "curve": [ 0.067, 0, 0.225, -7.97 ] + }, + { + "time": 0.2667, + "value": -9.75, + "curve": [ 0.316, -11.84, 0.519, -16.66 ] + }, + { + "time": 0.6667, + "value": -16.66, + "curve": [ 0.817, -16.66, 1.029, -11.43 ] + }, + { + "time": 1.1333, + "value": -9.14, + "curve": [ 1.25, -6.56, 1.525, 0 ] + }, + { "time": 1.6667 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.1, 0, 0.3, 1.32 ] + }, + { + "time": 0.4, + "value": 1.32, + "curve": [ 0.55, 1.32, 0.866, 0.93 ] + }, + { + "time": 1, + "value": 0.73, + "curve": [ 1.189, 0.46, 1.5, 0 ] + }, + { "time": 1.6667 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.118, -0.44, 0.3, -8.52 ] + }, + { + "time": 0.4, + "value": -8.52, + "curve": [ 0.55, -8.52, 0.85, 1.96 ] + }, + { + "time": 1, + "value": 1.96, + "curve": [ 1.167, 1.96, 1.577, 0.38 ] + }, + { "time": 1.6667 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.098, 1.46, 0.3, 4.49, 0.17, 0.13, 0.316, -3.28 ] + }, + { + "time": 0.4, + "x": 4.55, + "y": -5.95, + "curve": [ 0.53, 4.64, 0.776, 2.59, 0.492, -8.89, 0.668, -14.21 ] + }, + { + "time": 0.8667, + "x": 1.42, + "y": -14.26, + "curve": [ 0.966, 0.15, 1.109, -2.91, 0.994, -14.26, 1.144, -10.58 ] + }, + { + "time": 1.2333, + "x": -3.02, + "y": -8.26, + "curve": [ 1.342, -3.02, 1.568, -1.48, 1.317, -6.1, 1.558, 0 ] + }, + { "time": 1.6667 } + ] + }, + "front-shoulder": { + "translate": [ + { + "curve": [ 0.21, 0, 0.525, -1.72, 0.21, 0, 0.525, 4.08 ] + }, + { + "time": 0.8333, + "x": -1.72, + "y": 4.08, + "curve": [ 1.15, -1.72, 1.46, 0, 1.15, 4.08, 1.46, 0 ] + }, + { "time": 1.6667 } + ] + } + } + }, + "idle-turn": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-upper-arm": { + "rotate": [ + { + "value": -302.77, + "curve": [ 0, -406.9, 0.125, -420.87 ] + }, + { "time": 0.2667, "value": -420.87 } + ], + "translate": [ + { + "x": 2.24, + "y": -4.98, + "curve": [ 0.067, 2.24, 0.111, 0, 0.067, -4.98, 0.111, 0 ] + }, + { "time": 0.2667 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 248.56, + "curve": [ 0, 371.28, 0.062, 399.2 ] + }, + { "time": 0.1333, "value": 399.2 } + ], + "translate": [ + { + "x": -2.84, + "y": 37.28, + "curve": [ 0.033, -2.84, 0.069, 0, 0.033, 37.28, 0.069, 0 ] + }, + { "time": 0.1333 } + ] + }, + "gun": { + "rotate": [ + { + "value": -3.95, + "curve": [ 0, -10.4, 0.019, -20.43 ] + }, + { + "time": 0.0333, + "value": -20.45, + "curve": [ 0.044, -20.47, 0.125, 0 ] + }, + { "time": 0.2 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.2, + "curve": [ 0, 6.27, 0.125, 3.78 ] + }, + { "time": 0.2667, "value": 3.78 } + ] + }, + "hip": { + "translate": [ + { + "x": -2.69, + "y": -6.79, + "curve": [ 0.067, -2.69, 0.2, -11.97, 0.067, -6.79, 0.2, -23.15 ] + }, + { "time": 0.2667, "x": -11.97, "y": -23.15 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -15.54, + "curve": [ 0, -3.08, 0.034, 18.44 ] + }, + { + "time": 0.0667, + "value": 19.02, + "curve": [ 0.108, 19.75, 0.169, 0 ] + }, + { "time": 0.2667 } + ], + "scale": [ + { + "x": 0.94, + "curve": [ 0, 0.962, 0.024, 1.237, 0, 1, 0.026, 0.947 ] + }, + { + "time": 0.0667, + "x": 1.236, + "y": 0.947, + "curve": [ 0.117, 1.235, 0.189, 1, 0.117, 0.947, 0.189, 1 ] + }, + { "time": 0.2667 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 11.75, + "curve": [ 0, -7.97, 0.017, -33.4 ] + }, + { + "time": 0.0333, + "value": -33.39, + "curve": [ 0.049, -33.37, 0.131, 0 ] + }, + { "time": 0.2 } + ] + }, + "torso": { + "rotate": [ + { + "value": -18.25, + "curve": [ 0, -10.59, 0.125, -22.88 ] + }, + { "time": 0.2667, "value": -22.88 } + ], + "scale": [ + { + "y": 1.03, + "curve": [ 0.067, 1, 0.132, 1, 0.067, 1.03, 0.132, 1 ] + }, + { "time": 0.2667 } + ] + }, + "head": { + "rotate": [ + { + "value": 5.12, + "curve": [ 0, -6.34, 0.125, -6.75 ] + }, + { "time": 0.2667, "value": -6.75 } + ], + "scale": [ + { + "y": 1.03, + "curve": [ 0.067, 1, 0.107, 1, 0.067, 1.03, 0.107, 1 ] + }, + { "time": 0.2667 } + ] + }, + "rear-foot-target": { + "translate": [ + { + "x": -58.39, + "y": 30.48, + "curve": [ 0, -7.15, 0.047, 16.62, 0, 12.71, 0.039, 0.22 ] + }, + { + "time": 0.1, + "x": 34.14, + "y": -0.19, + "curve": [ 0.136, 45.79, 0.163, 48.87, 0.133, -0.41, 0.163, 0 ] + }, + { "time": 0.2, "x": 48.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 6.69, + "curve": [ 0, 19.76, 0.039, 56.53 ] + }, + { + "time": 0.0667, + "value": 56.63, + "curve": [ 0.114, 56.79, 0.189, 42.46 ] + }, + { "time": 0.2667, "value": 42.46 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": -1.85, + "curve": [ 0.014, -8.91, 0.047, -28.4 ] + }, + { + "time": 0.1, + "value": -28.89, + "curve": [ 0.144, -29.29, 0.262, -21.77 ] + }, + { "time": 0.2667 } + ], + "translate": [ + { + "x": 9.97, + "y": 0.82, + "curve": [ 0, -54.41, 0.078, -69.06, 0, 0.15, 0.078, 0 ] + }, + { "time": 0.1667, "x": -69.06 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -9.01, + "curve": [ 0.044, -9.01, 0.072, 7.41 ] + }, + { + "time": 0.1333, + "value": 10.08, + "curve": [ 0.166, 11.47, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -16.49, + "curve": [ 0.044, -16.49, 0.101, -5.98 ] + }, + { + "time": 0.1333, + "value": -2.95, + "curve": [ 0.162, -0.34, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -3.85, + "curve": [ 0.044, -3.85, 0.072, 6.91 ] + }, + { + "time": 0.1333, + "value": 8.05, + "curve": [ 0.166, 8.65, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair2": { + "rotate": [ + { + "value": 1.25, + "curve": [ 0.044, 1.25, 0.072, 8.97 ] + }, + { + "time": 0.1333, + "value": 8.6, + "curve": [ 0.166, 8.4, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "front-thigh": { + "translate": [ + { + "x": 12.21, + "y": 1.89, + "curve": [ 0.033, 12.21, 0.1, 0, 0.033, 1.89, 0.1, 0 ] + }, + { "time": 0.1333 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -16.11, + "y": -1.38, + "curve": [ 0.033, -16.11, 0.1, 0, 0.033, -1.38, 0.1, 0 ] + }, + { "time": 0.1333 } + ] + }, + "torso3": { + "rotate": [ + { "time": 0.2667, "value": -2.15 } + ] + }, + "head-control": { + "translate": [ + { + "x": -13.72, + "y": -34.7, + "curve": [ 0.067, -13.72, 0.2, 0, 0.067, -34.7, 0.2, 0 ] + }, + { "time": 0.2667 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.13, + "y": -14.31, + "curve": [ 0.067, 1.13, 0.2, 0, 0.067, -14.31, 0.2, 0 ] + }, + { "time": 0.2667 } + ] + } + } + }, + "jump": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" }, + { "time": 0.1, "name": "front-fist-closed" }, + { "time": 0.8333, "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { + "value": 55.08, + "curve": [ 0.007, 46.66, 0.043, 26.3 ] + }, + { + "time": 0.0667, + "value": 22.84, + "curve": [ 0.1, 17.99, 0.165, 15.78 ] + }, + { + "time": 0.2333, + "value": 15.71, + "curve": [ 0.309, 15.63, 0.408, 46.67 ] + }, + { + "time": 0.5, + "value": 63.6, + "curve": [ 0.56, 74.72, 0.762, 91.48 ] + }, + { + "time": 0.9667, + "value": 91.81, + "curve": [ 1.068, 92.01, 1.096, 22.05 ] + }, + { + "time": 1.1667, + "value": 22.25, + "curve": [ 1.18, 22.29, 1.176, 56.17 ] + }, + { + "time": 1.2, + "value": 56.16, + "curve": [ 1.246, 56.15, 1.263, 54.94 ] + }, + { "time": 1.3333, "value": 55.08 } + ], + "translate": [ + { "x": -5.13, "y": 11.55 } + ] + }, + "torso": { + "rotate": [ + { + "value": -45.57, + "curve": [ 0.022, -44.61, 0.03, -39.06 ] + }, + { + "time": 0.0667, + "value": -35.29, + "curve": [ 0.12, -29.77, 0.28, -19.95 ] + }, + { + "time": 0.4333, + "value": -19.95, + "curve": [ 0.673, -19.95, 0.871, -22.38 ] + }, + { + "time": 0.9667, + "value": -27.08, + "curve": [ 1.094, -33.33, 1.176, -44.93 ] + }, + { "time": 1.3333, "value": -45.57 } + ], + "translate": [ + { "x": -3.79, "y": -0.77 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 12.81, + "curve": [ 0.067, 12.81, 0.242, 67.88 ] + }, + { + "time": 0.2667, + "value": 74.11, + "curve": [ 0.314, 86.02, 0.454, 92.23 ] + }, + { + "time": 0.5667, + "value": 92.24, + "curve": [ 0.753, 92.26, 0.966, 67.94 ] + }, + { + "time": 1, + "value": 61.32, + "curve": [ 1.039, 53.75, 1.218, 12.68 ] + }, + { "time": 1.3333, "value": 12.81 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -115.64, + "curve": [ 0.067, -117.17, 0.125, -117.15 ] + }, + { + "time": 0.1667, + "value": -117.15, + "curve": [ 0.225, -117.15, 0.332, -108.76 ] + }, + { + "time": 0.4, + "value": -107.15, + "curve": [ 0.48, -105.26, 0.685, -103.49 ] + }, + { + "time": 0.7667, + "value": -101.97, + "curve": [ 0.826, -100.87, 0.919, -92.3 ] + }, + { + "time": 1, + "value": -92.28, + "curve": [ 1.113, -92.26, 1.297, -114.22 ] + }, + { "time": 1.3333, "value": -115.64 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -40.21, + "curve": [ 0.054, -35.46, 0.15, -31.12 ] + }, + { + "time": 0.2, + "value": -31.12, + "curve": [ 0.308, -31.12, 0.547, -80.12 ] + }, + { + "time": 0.6333, + "value": -96.56, + "curve": [ 0.697, -108.56, 0.797, -112.54 ] + }, + { + "time": 0.8667, + "value": -112.6, + "curve": [ 1.137, -112.84, 1.274, -49.19 ] + }, + { "time": 1.3333, "value": -40.21 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 20.54, + "curve": [ 0.054, 32.23, 0.192, 55.84 ] + }, + { + "time": 0.2333, + "value": 62.58, + "curve": [ 0.29, 71.87, 0.375, 79.28 ] + }, + { + "time": 0.4333, + "value": 79.18, + "curve": [ 0.555, 78.98, 0.684, 27.54 ] + }, + { + "time": 0.7333, + "value": 13.28, + "curve": [ 0.786, -1.85, 0.874, -24.76 ] + }, + { + "time": 1, + "value": -25.45, + "curve": [ 1.165, -26.36, 1.303, 9.1 ] + }, + { "time": 1.3333, "value": 20.54 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16, + "curve": [ 0.114, -39.59, 0.3, -45.61 ] + }, + { + "time": 0.4, + "value": -45.61, + "curve": [ 0.442, -45.61, 0.537, -21.54 ] + }, + { + "time": 0.5667, + "value": -15.4, + "curve": [ 0.592, -10.23, 0.692, 11.89 ] + }, + { + "time": 0.7333, + "value": 11.73, + "curve": [ 0.783, 11.54, 0.831, 1.8 ] + }, + { + "time": 0.8667, + "value": -5.78, + "curve": [ 0.897, -12.22, 0.901, -14.22 ] + }, + { + "time": 0.9333, + "value": -14.51, + "curve": [ 0.974, -14.89, 0.976, 10.38 ] + }, + { + "time": 1, + "value": 10.55, + "curve": [ 1.027, 10.74, 1.023, -8.44 ] + }, + { + "time": 1.0333, + "value": -8.42, + "curve": [ 1.059, -8.36, 1.074, 10.12 ] + }, + { + "time": 1.1, + "value": 10.22, + "curve": [ 1.168, 10.48, 1.27, -36.07 ] + }, + { "time": 1.3333, "value": -36.16 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.5, + "curve": [ 0.048, 36.1, 0.168, 20.45 ] + }, + { + "time": 0.3, + "value": 20.45, + "curve": [ 0.476, 20.45, 0.571, 33.76 ] + }, + { + "time": 0.6, + "value": 38.67, + "curve": [ 0.642, 45.8, 0.681, 57.44 ] + }, + { + "time": 0.7333, + "value": 62.91, + "curve": [ 0.829, 72.8, 0.996, 77.61 ] + }, + { + "time": 1.0333, + "value": 80.37, + "curve": [ 1.082, 83.94, 1.148, 90.6 ] + }, + { + "time": 1.2, + "value": 90.6, + "curve": [ 1.248, 90.46, 1.317, 53.07 ] + }, + { "time": 1.3333, "value": 49.06 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.022, 25.12, 0.187, -0.89 ] + }, + { + "time": 0.2, + "value": -2.52, + "curve": [ 0.257, -9.92, 0.372, -17.38 ] + }, + { + "time": 0.4333, + "value": -17.41, + "curve": [ 0.54, -17.47, 0.659, -16.91 ] + }, + { + "time": 0.7667, + "value": -12.1, + "curve": [ 0.907, -5.79, 1.025, 14.58 ] + }, + { + "time": 1.1, + "value": 20.58, + "curve": [ 1.191, 27.85, 1.283, 29.67 ] + }, + { "time": 1.3333, "value": 29.67 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.88, + "curve": [ 0.104, 11.82, 0.179, 11.15 ] + }, + { + "time": 0.2, + "value": 10.08, + "curve": [ 0.255, 7.29, 0.405, -8.15 ] + }, + { + "time": 0.4333, + "value": -9.35, + "curve": [ 0.508, -12.48, 0.595, -13.14 ] + }, + { + "time": 0.6667, + "value": -12.61, + "curve": [ 0.714, -12.26, 0.815, -5.57 ] + }, + { + "time": 0.8333, + "value": -4.08, + "curve": [ 0.883, -0.07, 1.045, 12.77 ] + }, + { + "time": 1.1, + "value": 15.06, + "curve": [ 1.208, 19.6, 1.279, 20.64 ] + }, + { "time": 1.3333, "value": 20.73 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.14, + "curve": [ 0.008, 12.19, 0.197, -23.53 ] + }, + { + "time": 0.3333, + "value": -23.95, + "curve": [ 0.509, -23.95, 0.667, -2.66 ] + }, + { + "time": 0.7333, + "value": -2.66, + "curve": [ 0.792, -2.66, 0.908, -13.32 ] + }, + { + "time": 0.9667, + "value": -13.32, + "curve": [ 1.158, -13.11, 1.241, -1.58 ] + }, + { "time": 1.3333, "value": -1.58 } + ], + "scale": [ + { + "curve": [ 0.041, 1, 0.052, 0.962, 0.041, 1, 0.052, 1.137 ] + }, + { + "time": 0.1, + "x": 0.954, + "y": 1.137, + "curve": [ 0.202, 0.962, 0.318, 1, 0.202, 1.137, 0.252, 1.002 ] + }, + { "time": 0.4667 }, + { + "time": 1.0667, + "x": 1.002, + "curve": [ 1.092, 1.002, 1.126, 1.143, 1.092, 1, 1.128, 0.975 ] + }, + { + "time": 1.1667, + "x": 1.144, + "y": 0.973, + "curve": [ 1.204, 1.145, 1.233, 0.959, 1.206, 0.972, 1.227, 1.062 ] + }, + { + "time": 1.2667, + "x": 0.958, + "y": 1.063, + "curve": [ 1.284, 0.958, 1.292, 1.001, 1.288, 1.063, 1.288, 1.001 ] + }, + { "time": 1.3333 } + ] + }, + "hip": { + "translate": [ + { + "y": -45.46, + "curve": [ 0.042, -0.09, 0.15, 15.22, 0.031, 44.98, 0.123, 289.73 ] + }, + { + "time": 0.2, + "x": 15.22, + "y": 415.85, + "curve": [ 0.332, 15.22, 0.539, -34.52, 0.271, 532.93, 0.483, 720.5 ] + }, + { + "time": 0.7667, + "x": -34.52, + "y": 721.6, + "curve": [ 0.888, -34.52, 1.057, -21.95, 1.049, 721.17, 1.098, 379.84 ] + }, + { + "time": 1.1333, + "x": -15.67, + "y": 266.77, + "curve": [ 1.144, -14.77, 1.188, -10.53, 1.15, 213.72, 1.172, -61.32 ] + }, + { + "time": 1.2333, + "x": -6.53, + "y": -61.34, + "curve": [ 1.272, -3.22, 1.311, 0.05, 1.291, -61.36, 1.296, -44.8 ] + }, + { "time": 1.3333, "y": -45.46 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -74.19, + "curve": [ 0, -51.14, 0.042, -12.54 ] + }, + { + "time": 0.1667, + "value": -12.28, + "curve": [ 0.285, -12.32, 0.37, -74.44 ] + }, + { + "time": 0.4333, + "value": -92.92, + "curve": [ 0.498, -111.86, 0.617, -140.28 ] + }, + { + "time": 0.9, + "value": -140.84, + "curve": [ 1.004, -141.04, 1.09, -47.87 ] + }, + { + "time": 1.1, + "value": -37.44, + "curve": [ 1.108, -29.83, 1.14, -21.18 ] + }, + { + "time": 1.1667, + "value": -21.08, + "curve": [ 1.18, -21.03, 1.191, -50.65 ] + }, + { + "time": 1.2, + "value": -53.17, + "curve": [ 1.22, -58.53, 1.271, -73.38 ] + }, + { "time": 1.3333, "value": -74.19 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 7.35, + "curve": [ 0, 4.8, 0.05, -26.64 ] + }, + { + "time": 0.0667, + "value": -26.64, + "curve": [ 0.192, -26.64, 0.442, -11.77 ] + }, + { + "time": 0.5667, + "value": -11.77, + "curve": [ 0.692, -11.77, 0.942, -19.36 ] + }, + { + "time": 1.0667, + "value": -19.36, + "curve": [ 1.133, -19.36, 1.32, 3.82 ] + }, + { "time": 1.3333, "value": 7.35 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": -7.14 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.36, + "curve": [ 0.022, 16.28, 0.15, 30.81 ] + }, + { + "time": 0.2, + "value": 30.81, + "curve": [ 0.258, 30.81, 0.375, 13.26 ] + }, + { + "time": 0.4333, + "value": 13.26, + "curve": [ 0.508, 13.26, 0.658, 15.05 ] + }, + { + "time": 0.7333, + "value": 14.98, + "curve": [ 0.789, 14.94, 0.828, 13.62 ] + }, + { + "time": 0.8667, + "value": 12.72, + "curve": [ 0.887, 12.25, 0.984, 9.83 ] + }, + { + "time": 1.0333, + "value": 8.6, + "curve": [ 1.045, 8.31, 1.083, 7.55 ] + }, + { + "time": 1.1333, + "value": 7.13, + "curve": [ 1.175, 6.78, 1.283, 6.18 ] + }, + { "time": 1.3333, "value": 6.18 } + ] + }, + "front-leg-target": { + "translate": [ + { "x": -13.95, "y": -30.34 } + ] + }, + "rear-leg-target": { + "rotate": [ + { "value": -38.43 } + ], + "translate": [ + { "x": 85, "y": -33.59 } + ] + }, + "front-foot-target": { + "rotate": [ + { "value": -62.54 } + ], + "translate": [ + { "x": 16.34, "y": 0.18 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": 18.55 } + ], + "translate": [ + { "x": -176.39, "y": 134.12 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "value": -143.73, + "curve": [ 0.083, -144.24, 0.167, -74.26 ] + }, + { + "time": 0.2667, + "value": -52.76, + "curve": [ 0.342, -36.57, 0.513, -36.57 ] + }, + { + "time": 0.6333, + "value": -30.97, + "curve": [ 0.724, -26.78, 0.848, -17.06 ] + }, + { + "time": 0.9667, + "value": -16.74, + "curve": [ 1.167, -16.2, 1.272, -144.17 ] + }, + { "time": 1.3333, "value": -143.73 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -1.57, + "curve": [ 0, -24.71, 0.162, -60.88 ] + }, + { + "time": 0.2667, + "value": -60.83, + "curve": [ 0.342, -60.8, 0.582, -43.5 ] + }, + { + "time": 0.7, + "value": -39.45, + "curve": [ 0.773, -36.94, 0.832, -36.78 ] + }, + { + "time": 0.9667, + "value": -36.6, + "curve": [ 1.054, -36.49, 1.092, -37.37 ] + }, + { + "time": 1.1667, + "value": -33.26, + "curve": [ 1.237, -29.37, 1.147, -1.41 ] + }, + { "time": 1.2, "value": -1.57 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0, 13.59, 0.117, 18.21 ] + }, + { + "time": 0.1333, + "value": 18.21, + "curve": [ 0.167, 18.21, 0.26, 12.95 ] + }, + { + "time": 0.3, + "value": 11.56, + "curve": [ 0.382, 8.7, 0.55, 9.43 ] + }, + { + "time": 0.6667, + "value": 9.32, + "curve": [ 0.843, 9.15, 0.918, -7.34 ] + }, + { "time": 1.3333, "value": -6.81 } + ], + "translate": [ + { + "time": 0.6667, + "curve": [ 0.781, 0, 0.972, 16.03, 0.781, 0, 0.972, 0.92 ] + }, + { + "time": 1.1333, + "x": 16.03, + "y": 0.92, + "curve": [ 1.211, 16.03, 1.281, 0, 1.211, 0.92, 1.281, 0 ] + }, + { "time": 1.3333 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.001, -3.88, 0.063, 16.18 ] + }, + { + "time": 0.1667, + "value": 16.14, + "curve": [ 0.242, 16.1, 0.249, 16.07 ] + }, + { + "time": 0.3333, + "value": 13.46, + "curve": [ 0.442, 10.09, 0.573, -2.2 ] + }, + { + "time": 0.6, + "value": -6.04, + "curve": [ 0.614, -8.05, 0.717, -33.44 ] + }, + { + "time": 0.7667, + "value": -33.44, + "curve": [ 0.809, -33.44, 0.835, -31.32 ] + }, + { + "time": 0.8667, + "value": -27.36, + "curve": [ 0.874, -26.47, 0.903, -14.28 ] + }, + { + "time": 0.9333, + "value": -14.47, + "curve": [ 0.956, -14.62, 0.944, -25.91 ] + }, + { + "time": 1, + "value": -25.96, + "curve": [ 1.062, -26.02, 1.051, -1.87 ] + }, + { + "time": 1.0667, + "value": -1.87, + "curve": [ 1.096, -1.87, 1.096, -16.09 ] + }, + { + "time": 1.1333, + "value": -16.08, + "curve": [ 1.169, -16.08, 1.153, -3.38 ] + }, + { + "time": 1.2, + "value": -3.38, + "curve": [ 1.234, -3.38, 1.271, -6.07 ] + }, + { "time": 1.3333, "value": -6.07 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0, -3.17, 0.042, 16.33 ] + }, + { + "time": 0.0667, + "value": 16.33, + "curve": [ 0.21, 15.74, 0.208, -12.06 ] + }, + { + "time": 0.3333, + "value": -12.21, + "curve": [ 0.417, -12.3, 0.552, -3.98 ] + }, + { + "time": 0.6667, + "value": 1.52, + "curve": [ 0.726, 4.35, 0.817, 4.99 ] + }, + { + "time": 0.8667, + "value": 4.99, + "curve": [ 0.901, 4.99, 0.912, -29.05 ] + }, + { + "time": 0.9667, + "value": -27.45, + "curve": [ 0.987, -26.83, 1.018, -5.42 ] + }, + { + "time": 1.0667, + "value": -5.46, + "curve": [ 1.107, -5.22, 1.095, -33.51 ] + }, + { + "time": 1.1333, + "value": -33.28, + "curve": [ 1.162, -33.57, 1.192, 8.04 ] + }, + { + "time": 1.2667, + "value": 7.86, + "curve": [ 1.302, 7.77, 1.313, 2.7 ] + }, + { "time": 1.3333, "value": 2.7 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.001, -3.12, 0.074, 14.66 ] + }, + { + "time": 0.1333, + "value": 14.66, + "curve": [ 0.188, 14.8, 0.293, 9.56 ] + }, + { + "time": 0.3333, + "value": 5.99, + "curve": [ 0.381, 1.72, 0.55, -11.11 ] + }, + { + "time": 0.6667, + "value": -11.11, + "curve": [ 0.833, -11.11, 0.933, 22.54 ] + }, + { + "time": 1.1, + "value": 22.54, + "curve": [ 1.158, 22.54, 1.275, -6.81 ] + }, + { "time": 1.3333, "value": -6.81 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 4.52, + "curve": [ 0.013, 2.33, 0.092, -9.75 ] + }, + { + "time": 0.1333, + "value": -9.75, + "curve": [ 0.175, -9.75, 0.291, -1.26 ] + }, + { + "time": 0.3333, + "value": 0.96, + "curve": [ 0.359, 2.3, 0.543, 4.25 ] + }, + { + "time": 0.6, + "value": 4.68, + "curve": [ 0.683, 5.3, 0.771, 5.92 ] + }, + { + "time": 0.8333, + "value": 6.48, + "curve": [ 0.871, 6.82, 1.083, 11.37 ] + }, + { + "time": 1.1667, + "value": 11.37, + "curve": [ 1.208, 11.37, 1.317, 6.18 ] + }, + { "time": 1.3333, "value": 4.52 } + ], + "translate": [ + { + "curve": [ 0, 0, 0.082, -2.24, 0, 0, 0.082, -0.42 ] + }, + { + "time": 0.1667, + "x": -2.98, + "y": -0.56, + "curve": [ 0.232, -2.24, 0.298, 0, 0.232, -0.42, 0.298, 0 ] + }, + { "time": 0.3333, "curve": "stepped" }, + { + "time": 0.8667, + "curve": [ 0.889, 0, 0.912, 0.26, 0.889, 0, 0.912, 0.06 ] + }, + { + "time": 0.9333, + "x": 0.68, + "y": 0.23, + "curve": [ 1.016, 2.22, 1.095, 5.9, 1.023, 0.97, 1.095, 1.99 ] + }, + { + "time": 1.1667, + "x": 6.47, + "y": 2.18, + "curve": [ 1.23, 5.75, 1.286, 0, 1.23, 1.94, 1.286, 0 ] + }, + { "time": 1.3333 } + ] + }, + "torso3": { + "rotate": [ + { + "value": 4.52, + "curve": [ 0.025, 4.52, 0.075, -6.17 ] + }, + { + "time": 0.1, + "value": -6.17, + "curve": [ 0.175, -6.17, 0.381, -0.71 ] + }, + { + "time": 0.4, + "value": -0.25, + "curve": [ 0.447, 0.87, 0.775, 4.84 ] + }, + { + "time": 0.9, + "value": 4.84, + "curve": [ 1.008, 4.84, 1.225, 4.52 ] + }, + { "time": 1.3333, "value": 4.52 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.138, -2.4, 0.227, -10.44, 0.123, 1.05, 0.227, 2.7 ] + }, + { + "time": 0.3667, + "x": -10.44, + "y": 2.7, + "curve": [ 0.484, -10.44, 0.585, -5.63, 0.484, 2.7, 0.629, -23.62 ] + }, + { + "time": 0.7333, + "x": -2.29, + "y": -26.61, + "curve": [ 0.818, -0.39, 0.962, 1.21, 0.858, -30.17, 0.972, -28.75 ] + }, + { + "time": 1.1, + "x": 1.25, + "y": -28.75, + "curve": [ 1.192, 1.28, 1.234, 0.98, 1.224, -28.75, 1.235, -2.15 ] + }, + { "time": 1.3333 } + ] + }, + "front-shoulder": { + "translate": [ + { + "curve": [ 0.031, -2.22, 0.065, -3.73, 0.02, -3.25, 0.065, -14.74 ] + }, + { + "time": 0.1, + "x": -3.73, + "y": -14.74, + "curve": [ 0.216, -3.73, 0.384, -0.17, 0.216, -14.74, 0.402, -12.51 ] + }, + { + "time": 0.5, + "x": 1.63, + "y": -9.51, + "curve": [ 0.632, 3.69, 0.935, 7.41, 0.585, -6.91, 0.909, 10.86 ] + }, + { + "time": 1.1, + "x": 7.45, + "y": 10.99, + "curve": [ 1.18, 7.46, 1.265, 2.86, 1.193, 11.05, 1.294, 3.38 ] + }, + { "time": 1.3333 } + ] + } + }, + "ik": { + "front-foot-ik": [ + { + "mix": 0, + "curve": [ 0.3, 0, 0.9, 1, 0.3, 0, 0.9, 0 ] + }, + { "time": 1.2 } + ], + "front-leg-ik": [ + { + "mix": 0, + "bendPositive": false, + "curve": [ 0.3, 0, 0.9, 1, 0.3, 0, 0.9, 0 ] + }, + { "time": 1.2, "bendPositive": false } + ], + "rear-foot-ik": [ + { "mix": 0 } + ], + "rear-leg-ik": [ + { "mix": 0, "bendPositive": false } + ] + }, + "events": [ + { "time": 1.2, "name": "footstep" } + ] + }, + "portal": { + "slots": { + "clipping": { + "attachment": [ + { "name": "clipping" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "time": 0.9, "name": "mouth-grind" }, + { "time": 2.2667, "name": "mouth-smile" } + ] + }, + "portal-bg": { + "attachment": [ + { "name": "portal-bg" }, + { "time": 3 } + ] + }, + "portal-flare1": { + "attachment": [ + { "time": 1.1, "name": "portal-flare1" }, + { "time": 1.1333, "name": "portal-flare2" }, + { "time": 1.1667, "name": "portal-flare3" }, + { "time": 1.2, "name": "portal-flare1" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3333 } + ] + }, + "portal-flare2": { + "attachment": [ + { "time": 1.1, "name": "portal-flare2" }, + { "time": 1.1333, "name": "portal-flare3" }, + { "time": 1.1667, "name": "portal-flare1" }, + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667 } + ] + }, + "portal-flare3": { + "attachment": [ + { "time": 1.2, "name": "portal-flare3" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667 } + ] + }, + "portal-flare4": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare1" }, + { "time": 1.2667, "name": "portal-flare2" }, + { "time": 1.3333 } + ] + }, + "portal-flare5": { + "attachment": [ + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3333 } + ] + }, + "portal-flare6": { + "attachment": [ + { "time": 1.2667, "name": "portal-flare3" }, + { "time": 1.3333 } + ] + }, + "portal-flare7": { + "attachment": [ + { "time": 1.1333, "name": "portal-flare2" }, + { "time": 1.1667 } + ] + }, + "portal-flare8": { + "attachment": [ + { "time": 1.2, "name": "portal-flare3" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667 } + ] + }, + "portal-flare9": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3 } + ] + }, + "portal-flare10": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare1" }, + { "time": 1.2667, "name": "portal-flare3" }, + { "time": 1.3 } + ] + }, + "portal-shade": { + "attachment": [ + { "name": "portal-shade" }, + { "time": 3 } + ] + }, + "portal-streaks1": { + "attachment": [ + { "name": "portal-streaks1" }, + { "time": 3 } + ] + }, + "portal-streaks2": { + "attachment": [ + { "name": "portal-streaks2" }, + { "time": 3 } + ] + } + }, + "bones": { + "portal-root": { + "translate": [ + { + "x": -458.35, + "y": 105.19, + "curve": [ 0.333, -458.22, 0.669, -457.86, 0.934, 105.19, 0.671, 105.19 ] + }, + { + "time": 1, + "x": -456.02, + "y": 105.19, + "curve": [ 1.339, -454.14, 2.208, -447.28, 1.35, 105.19, 2.05, 105.19 ] + }, + { + "time": 2.4, + "x": -439.12, + "y": 105.19, + "curve": [ 2.463, -436.44, 2.502, -432.92, 2.487, 105.19, 2.512, 105.09 ] + }, + { + "time": 2.6, + "x": -432.58, + "y": 105.09, + "curve": [ 2.784, -431.94, 2.978, -446.6, 2.772, 105.09, 2.933, 105.19 ] + }, + { "time": 3.0333, "x": -457.42, "y": 105.19 } + ], + "scale": [ + { + "x": 0.003, + "y": 0.006, + "curve": [ 0.329, 0.044, 0.347, 0.117, 0.329, 0.097, 0.37, 0.249 ] + }, + { + "time": 0.4, + "x": 0.175, + "y": 0.387, + "curve": [ 0.63, 0.619, 0.663, 0.723, 0.609, 1.338, 0.645, 1.524 ] + }, + { + "time": 0.7333, + "x": 0.724, + "y": 1.52, + "curve": [ 0.798, 0.725, 0.907, 0.647, 0.797, 1.517, 0.895, 1.424 ] + }, + { + "time": 1, + "x": 0.645, + "y": 1.426, + "curve": [ 1.095, 0.643, 1.139, 0.688, 1.089, 1.428, 1.115, 1.513 ] + }, + { + "time": 1.2333, + "x": 0.685, + "y": 1.516, + "curve": [ 1.325, 0.683, 1.508, 0.636, 1.343, 1.518, 1.467, 1.4 ] + }, + { + "time": 1.6, + "x": 0.634, + "y": 1.401, + "curve": [ 1.728, 0.631, 1.946, 0.687, 1.722, 1.402, 1.924, 1.522 ] + }, + { + "time": 2.0667, + "x": 0.688, + "y": 1.522, + "curve": [ 2.189, 0.69, 2.289, 0.649, 2.142, 1.522, 2.265, 1.417 ] + }, + { + "time": 2.4, + "x": 0.65, + "y": 1.426, + "curve": [ 2.494, 0.651, 2.504, 0.766, 2.508, 1.434, 2.543, 1.566 ] + }, + { + "time": 2.6, + "x": 0.766, + "y": 1.568, + "curve": [ 2.73, 0.765, 3.006, 0.098, 2.767, 1.564, 2.997, 0.1 ] + }, + { "time": 3.0333, "x": 0.007, "y": 0.015 } + ] + }, + "portal-streaks1": { + "rotate": [ + {}, + { "time": 3.1667, "value": 1200 } + ], + "translate": [ + { + "x": 15.15, + "curve": [ 0.162, 15.15, 0.432, 12.6, 0.162, 0, 0.432, -3.86 ] + }, + { + "time": 0.6667, + "x": 10.9, + "y": -6.44, + "curve": [ 0.794, 9.93, 0.912, 9.21, 0.794, -7.71, 0.912, -8.66 ] + }, + { + "time": 1, + "x": 9.21, + "y": -8.66, + "curve": [ 1.083, 9.21, 1.25, 21.53, 1.083, -8.66, 1.265, -4.9 ] + }, + { + "time": 1.3333, + "x": 21.53, + "y": -3.19, + "curve": [ 1.5, 21.53, 1.939, 12.3, 1.446, -0.37, 1.9, 6.26 ] + }, + { + "time": 2.0667, + "x": 11.26, + "y": 6.26, + "curve": [ 2.239, 9.85, 2.389, 9.68, 2.208, 6.26, 2.523, 0.51 ] + }, + { + "time": 2.5667, + "x": 9.39, + "y": -0.8, + "curve": [ 2.657, 9.24, 2.842, 9.21, 2.646, -3.2, 2.842, -8.91 ] + }, + { "time": 2.9333, "x": 9.21, "y": -8.91 } + ], + "scale": [ + { + "curve": [ 0.167, 1, 0.5, 1.053, 0.167, 1, 0.5, 1.053 ] + }, + { + "time": 0.6667, + "x": 1.053, + "y": 1.053, + "curve": [ 0.833, 1.053, 1.167, 0.986, 0.833, 1.053, 1.167, 0.986 ] + }, + { + "time": 1.3333, + "x": 0.986, + "y": 0.986, + "curve": [ 1.5, 0.986, 1.833, 1.053, 1.5, 0.986, 1.833, 1.053 ] + }, + { "time": 2, "x": 1.053, "y": 1.053 } + ] + }, + "portal-streaks2": { + "rotate": [ + {}, + { "time": 3.1667, "value": 600 } + ], + "translate": [ + { "x": -2.11 }, + { "time": 1, "x": -2.11, "y": 6.63 }, + { "time": 1.9333, "x": -2.11 } + ], + "scale": [ + { + "x": 1.014, + "y": 1.014, + "curve": [ 0.229, 0.909, 0.501, 0.755, 0.242, 0.892, 0.502, 0.768 ] + }, + { + "time": 0.8667, + "x": 0.745, + "y": 0.745, + "curve": [ 1.282, 0.733, 2.021, 0.699, 1.27, 0.719, 2.071, 0.709 ] + }, + { + "time": 2.2, + "x": 0.7, + "y": 0.704, + "curve": [ 2.315, 0.7, 2.421, 0.794, 2.311, 0.701, 2.485, 0.797 ] + }, + { + "time": 2.5667, + "x": 0.794, + "y": 0.794, + "curve": [ 2.734, 0.794, 2.99, 0.323, 2.714, 0.789, 3.019, 0.341 ] + }, + { "time": 3.1667, "x": 0, "y": 0 } + ] + }, + "portal-shade": { + "translate": [ + { "x": -29.68 } + ], + "scale": [ + { "x": 0.714, "y": 0.714 } + ] + }, + "portal": { + "rotate": [ + {}, + { "time": 3.1667, "value": 600 } + ] + }, + "clipping": { + "translate": [ + { "x": -476.55, "y": 2.27 } + ], + "scale": [ + { "x": 0.983, "y": 1.197 } + ] + }, + "hip": { + "rotate": [ + { + "time": 1.0667, + "value": 22.74, + "curve": [ 1.163, 18.84, 1.77, 8.77 ] + }, + { + "time": 1.9, + "value": 7.82, + "curve": [ 2.271, 5.1, 2.89, 0 ] + }, + { "time": 3.1667 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { + "time": 1.0667, + "x": -694.16, + "y": 183.28, + "curve": [ 1.091, -602.08, 1.138, -427.59, 1.115, 185.6, 1.171, 133.18 ] + }, + { + "time": 1.2333, + "x": -316.97, + "y": 55.29, + "curve": [ 1.317, -220.27, 1.512, -123.21, 1.271, 8.68, 1.461, -83.18 ] + }, + { + "time": 1.6, + "x": -95.53, + "y": -112.23, + "curve": [ 1.718, -58.25, 2.037, -22.54, 1.858, -166.17, 2.109, -31.4 ] + }, + { + "time": 2.1667, + "x": -14.82, + "y": -31.12, + "curve": [ 2.294, -7.28, 2.442, -7.2, 2.274, -30.6, 2.393, -36.76 ] + }, + { + "time": 2.6, + "x": -7.2, + "y": -36.96, + "curve": [ 2.854, -7.2, 3.071, -11.87, 2.786, -36.27, 3.082, -22.98 ] + }, + { "time": 3.1667, "x": -11.97, "y": -23.15 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "time": 1.0667, "value": 41.6, "curve": "stepped" }, + { + "time": 1.2333, + "value": 41.6, + "curve": [ 1.258, 41.6, 1.379, 35.46 ] + }, + { + "time": 1.4, + "value": 30.09, + "curve": [ 1.412, 27.04, 1.433, 10.65 ] + }, + { "time": 1.4333, "value": -0.28 }, + { "time": 1.6, "value": 2.44 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { + "time": 1.0667, + "x": -591.13, + "y": 438.46, + "curve": [ 1.076, -539.77, 1.206, -268.1, 1.117, 418.44, 1.21, 333.18 ] + }, + { + "time": 1.2333, + "x": -225.28, + "y": 304.53, + "curve": [ 1.265, -175.22, 1.393, -74.21, 1.296, 226.52, 1.401, 49.61 ] + }, + { + "time": 1.4333, + "x": -52.32, + "y": 0.2, + "curve": [ 1.454, -40.85, 1.616, 40.87, 1.466, 0.17, 1.614, 0.04 ] + }, + { "time": 1.6667, "x": 45.87, "y": 0.01 }, + { "time": 1.9333, "x": 48.87 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "time": 1.0667, + "value": 32.08, + "curve": [ 1.108, 32.08, 1.192, 35.16 ] + }, + { + "time": 1.2333, + "value": 35.16, + "curve": [ 1.258, 35.16, 1.317, 2.23 ] + }, + { + "time": 1.3333, + "value": -4.74, + "curve": [ 1.351, -12.14, 1.429, -34.96 ] + }, + { + "time": 1.6, + "value": -34.77, + "curve": [ 1.765, -34.58, 1.897, -17.25 ] + }, + { "time": 1.9333 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { + "time": 1.0667, + "x": -533.93, + "y": 363.75, + "curve": [ 1.074, -480.85, 1.18, -261.31, 1.094, 362.3, 1.195, 267.77 ] + }, + { + "time": 1.2333, + "x": -201.23, + "y": 199.93, + "curve": [ 1.269, -161.38, 1.294, -140.32, 1.274, 126.67, 1.308, 77.12 ] + }, + { + "time": 1.3333, + "x": -124.08, + "y": 0.2, + "curve": [ 1.426, -85.6, 1.633, -69.06, 1.45, 0.48, 1.633, 0 ] + }, + { "time": 1.7333, "x": -69.06 } + ] + }, + "torso": { + "rotate": [ + { + "time": 1.0667, + "value": 27.02, + "curve": [ 1.187, 26.86, 1.291, 7.81 ] + }, + { + "time": 1.3333, + "value": -2.62, + "curve": [ 1.402, -19.72, 1.429, -48.64 ] + }, + { + "time": 1.4667, + "value": -56.31, + "curve": [ 1.509, -64.87, 1.62, -77.14 ] + }, + { + "time": 1.7333, + "value": -77.34, + "curve": [ 1.837, -76.89, 1.895, -71.32 ] + }, + { + "time": 2, + "value": -57.52, + "curve": [ 2.104, -43.83, 2.189, -28.59 ] + }, + { + "time": 2.3, + "value": -29.03, + "curve": [ 2.413, -29.48, 2.513, -36.79 ] + }, + { + "time": 2.6667, + "value": -36.79, + "curve": [ 2.814, -36.95, 2.947, -22.88 ] + }, + { "time": 3.1667, "value": -22.88 } + ] + }, + "neck": { + "rotate": [ + { + "time": 1.0667, + "value": -3.57, + "curve": [ 1.146, -3.66, 1.15, -13.5 ] + }, + { + "time": 1.2333, + "value": -13.5, + "curve": [ 1.428, -13.5, 1.443, 11.58 ] + }, + { + "time": 1.5667, + "value": 11.42, + "curve": [ 1.658, 11.3, 1.775, 3.78 ] + }, + { + "time": 1.8667, + "value": 3.78, + "curve": [ 1.92, 3.78, 2.036, 8.01 ] + }, + { + "time": 2.1, + "value": 7.93, + "curve": [ 2.266, 7.72, 2.42, 3.86 ] + }, + { + "time": 2.5333, + "value": 3.86, + "curve": [ 2.783, 3.86, 3.004, 3.78 ] + }, + { "time": 3.1667, "value": 3.78 } + ] + }, + "head": { + "rotate": [ + { + "time": 1.0667, + "value": 16.4, + "curve": [ 1.133, 9.9, 1.207, 1.87 ] + }, + { + "time": 1.3333, + "value": 1.67, + "curve": [ 1.46, 1.56, 1.547, 47.54 ] + }, + { + "time": 1.7333, + "value": 47.55, + "curve": [ 1.897, 47.56, 2.042, 5.68 ] + }, + { + "time": 2.0667, + "value": 0.86, + "curve": [ 2.074, -0.61, 2.086, -2.81 ] + }, + { + "time": 2.1, + "value": -5.31, + "curve": [ 2.145, -13.07, 2.216, -23.65 ] + }, + { + "time": 2.2667, + "value": -23.71, + "curve": [ 2.334, -23.79, 2.426, -13.43 ] + }, + { + "time": 2.4667, + "value": -9.18, + "curve": [ 2.498, -5.91, 2.604, 2.53 ] + }, + { + "time": 2.6667, + "value": 2.52, + "curve": [ 2.738, 2.24, 2.85, -8.76 ] + }, + { + "time": 2.9333, + "value": -8.67, + "curve": [ 3.036, -8.55, 3.09, -7.09 ] + }, + { "time": 3.1667, "value": -6.75 } + ], + "scale": [ + { + "time": 1.3333, + "curve": [ 1.392, 1, 1.526, 1, 1.392, 1, 1.508, 1.043 ] + }, + { + "time": 1.5667, + "x": 0.992, + "y": 1.043, + "curve": [ 1.598, 0.985, 1.676, 0.955, 1.584, 1.043, 1.672, 1.04 ] + }, + { + "time": 1.7333, + "x": 0.954, + "y": 1.029, + "curve": [ 1.843, 0.954, 1.933, 1, 1.825, 1.013, 1.933, 1 ] + }, + { "time": 2 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "time": 0.9, + "value": 39.24, + "curve": [ 0.968, 39.93, 1.267, 85.31 ] + }, + { + "time": 1.4667, + "value": 112.27, + "curve": [ 1.555, 124.24, 1.576, 126.44 ] + }, + { + "time": 1.6333, + "value": 126.44, + "curve": [ 1.782, 126.44, 1.992, 94.55 ] + }, + { + "time": 2.1, + "value": 79.96, + "curve": [ 2.216, 64.26, 2.407, 34.36 ] + }, + { + "time": 2.5667, + "value": 33.38, + "curve": [ 2.815, 31.87, 3.1, 39.2 ] + }, + { "time": 3.1667, "value": 39.2 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "time": 1.0667, + "value": 56.07, + "curve": [ 1.138, 59.21, 1.192, 59.65 ] + }, + { + "time": 1.2333, + "value": 59.46, + "curve": [ 1.295, 59.17, 1.45, 22.54 ] + }, + { "time": 1.4667, "value": -0.84 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "time": 1.0667, + "value": 118.03, + "curve": [ 1.075, 93.64, 1.358, -34.03 ] + }, + { + "time": 1.6667, + "value": -33.94, + "curve": [ 1.808, -33.89, 1.879, -25 ] + }, + { + "time": 1.9667, + "value": -25.19, + "curve": [ 2.09, -25.46, 2.312, -34.58 ] + }, + { + "time": 2.3667, + "value": -38.36, + "curve": [ 2.465, -45.18, 2.557, -60.1 ] + }, + { + "time": 2.8333, + "value": -61.1, + "curve": [ 2.843, -61.06, 3.16, -60.87 ] + }, + { "time": 3.1667, "value": -60.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "time": 1.0667, + "value": 0.66, + "curve": [ 1.108, 0.66, 1.221, 44.95 ] + }, + { + "time": 1.2333, + "value": 49.25, + "curve": [ 1.263, 59.42, 1.342, 68.06 ] + }, + { + "time": 1.3667, + "value": 68.34, + "curve": [ 1.409, 68.8, 1.476, 4.9 ] + }, + { + "time": 1.5, + "value": -2.05, + "curve": [ 1.529, -10.3, 1.695, -15.95 ] + }, + { + "time": 1.7333, + "value": -17.38, + "curve": [ 1.807, -20.1, 1.878, -21.19 ] + }, + { + "time": 1.9333, + "value": -21.08, + "curve": [ 2.073, -20.8, 2.146, -7.63 ] + }, + { + "time": 2.1667, + "value": -3.64, + "curve": [ 2.186, 0.12, 2.275, 15.28 ] + }, + { + "time": 2.3333, + "value": 21.78, + "curve": [ 2.392, 28.31, 2.575, 37.66 ] + }, + { + "time": 2.7, + "value": 39.43, + "curve": [ 2.947, 42.93, 3.02, 42.46 ] + }, + { "time": 3.1667, "value": 42.46 } + ] + }, + "front-thigh": { + "translate": [ + { "time": 1.1, "x": -6.41, "y": 18.23, "curve": "stepped" }, + { "time": 1.1333, "x": -6.41, "y": 18.23 }, + { "time": 1.2, "x": 1.61, "y": 3.66 }, + { "time": 1.2333, "x": 4.5, "y": -3.15 }, + { "time": 1.3667, "x": -3.79, "y": 2.94 }, + { "time": 1.4, "x": -8.37, "y": 8.72 }, + { "time": 1.4333, "x": -11.26, "y": 16.99 }, + { "time": 1.4667, "x": -9.89, "y": 24.73, "curve": "stepped" }, + { "time": 1.8667, "x": -9.89, "y": 24.73 }, + { "time": 2.1 } + ] + }, + "front-foot-tip": { + "rotate": [ + { "time": 1.0667, "value": 42.55, "curve": "stepped" }, + { "time": 1.1333, "value": 42.55 }, + { "time": 1.2333, "value": 17.71 }, + { "time": 1.3667, "value": 3.63 }, + { "time": 1.4333 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "time": 1.0667, + "value": 108.71, + "curve": [ 1.082, 108.29, 1.437, 50.73 ] + }, + { + "time": 1.5667, + "value": 24.87, + "curve": [ 1.62, 14.2, 1.66, -11.74 ] + }, + { + "time": 1.7333, + "value": -11.74, + "curve": [ 1.961, -11.73, 2.172, 1.66 ] + }, + { + "time": 2.2667, + "value": 7.88, + "curve": [ 2.331, 12.13, 2.439, 18.65 ] + }, + { + "time": 2.5333, + "value": 18.72, + "curve": [ 2.788, 18.91, 3.145, -0.3 ] + }, + { "time": 3.1667 } + ] + }, + "front-fist": { + "rotate": [ + { + "time": 1.1, + "value": 6.32, + "curve": [ 1.11, 3.31, 1.153, -5.07 ] + }, + { + "time": 1.2333, + "value": -5.13, + "curve": [ 1.311, -5.19, 1.364, 34.65 ] + }, + { + "time": 1.4667, + "value": 34.53, + "curve": [ 1.574, 34.41, 1.547, -55.78 ] + }, + { + "time": 1.8667, + "value": -54.7, + "curve": [ 1.947, -54.7, 2.03, -53.94 ] + }, + { + "time": 2.1333, + "value": -42.44, + "curve": [ 2.215, -33.42, 2.358, -4.43 ] + }, + { + "time": 2.4, + "value": 0.03, + "curve": [ 2.444, 4.66, 2.536, 8.2 ] + }, + { + "time": 2.6333, + "value": 8.2, + "curve": [ 2.733, 8.19, 2.804, -0.67 ] + }, + { + "time": 2.9, + "value": -0.82, + "curve": [ 3.127, -1.16, 3.093, 0 ] + }, + { "time": 3.1667 } + ] + }, + "gun": { + "rotate": [ + { + "time": 1.2667, + "curve": [ 1.35, 0, 1.549, 7.49 ] + }, + { + "time": 1.6, + "value": 9.5, + "curve": [ 1.663, 12.02, 1.846, 19.58 ] + }, + { + "time": 1.9333, + "value": 19.43, + "curve": [ 1.985, 19.4, 2.057, 2.98 ] + }, + { + "time": 2.2, + "value": 2.95, + "curve": [ 2.304, 3.55, 2.458, 10.8 ] + }, + { + "time": 2.5, + "value": 10.8, + "curve": [ 2.642, 10.8, 2.873, -2.54 ] + }, + { + "time": 2.9333, + "value": -2.55, + "curve": [ 3.09, -2.57, 3.08, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair2": { + "rotate": [ + { + "time": 1.0667, + "value": 26.19, + "curve": [ 1.158, 26.19, 1.368, 26 ] + }, + { + "time": 1.4333, + "value": 24.43, + "curve": [ 1.534, 22.03, 2, -29.14 ] + }, + { + "time": 2.2, + "value": -29.14, + "curve": [ 2.292, -29.14, 2.475, 6.71 ] + }, + { + "time": 2.5667, + "value": 6.71, + "curve": [ 2.675, 6.71, 2.814, -5.06 ] + }, + { + "time": 2.9, + "value": -5.06, + "curve": [ 2.973, -5.06, 3.123, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair4": { + "rotate": [ + { + "time": 1.0667, + "value": 5.21, + "curve": [ 1.108, 5.21, 1.192, 26.19 ] + }, + { + "time": 1.2333, + "value": 26.19, + "curve": [ 1.317, 26.19, 1.483, 10.63 ] + }, + { + "time": 1.5667, + "value": 10.63, + "curve": [ 1.627, 10.63, 1.642, 17.91 ] + }, + { + "time": 1.7, + "value": 17.94, + "curve": [ 1.761, 17.97, 1.774, 8.22 ] + }, + { + "time": 1.8, + "value": 3.33, + "curve": [ 1.839, -4.21, 1.95, -22.67 ] + }, + { + "time": 2, + "value": -22.67, + "curve": [ 2.025, -22.67, 2.123, -21.86 ] + }, + { + "time": 2.1667, + "value": -18.71, + "curve": [ 2.228, -14.31, 2.294, -0.3 ] + }, + { + "time": 2.3667, + "value": 6.36, + "curve": [ 2.433, 12.45, 2.494, 19.21 ] + }, + { + "time": 2.6, + "value": 19.21, + "curve": [ 2.729, 19.21, 2.854, 6.75 ] + }, + { + "time": 2.9333, + "value": 4.62, + "curve": [ 3.09, 0.45, 3.062, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair3": { + "rotate": [ + { + "time": 1.4333, + "curve": [ 1.45, 0, 1.452, 11.29 ] + }, + { + "time": 1.5, + "value": 11.21, + "curve": [ 1.596, 11.06, 1.573, -14.17 ] + }, + { + "time": 1.7333, + "value": -20.4, + "curve": [ 1.851, -24.98, 1.943, -28.45 ] + }, + { + "time": 2.2, + "value": -28.75, + "curve": [ 2.317, -28.75, 2.55, 7.04 ] + }, + { + "time": 2.6667, + "value": 7.04, + "curve": [ 2.792, 7.04, 2.885, -5.19 ] + }, + { + "time": 2.9667, + "value": -5.19, + "curve": [ 3.037, -5.19, 3.096, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair1": { + "rotate": [ + { + "time": 1.2333, + "curve": [ 1.283, 0, 1.349, 3.99 ] + }, + { + "time": 1.4333, + "value": 6.58, + "curve": [ 1.497, 8.54, 1.683, 9.35 ] + }, + { + "time": 1.7667, + "value": 9.35, + "curve": [ 1.825, 9.35, 1.945, -8.71 ] + }, + { + "time": 2, + "value": -11.15, + "curve": [ 2.058, -13.71, 2.2, -14.97 ] + }, + { + "time": 2.2667, + "value": -14.97, + "curve": [ 2.367, -14.97, 2.567, 18.77 ] + }, + { + "time": 2.6667, + "value": 18.77, + "curve": [ 2.733, 18.77, 2.817, 8.29 ] + }, + { + "time": 2.8667, + "value": 6.51, + "curve": [ 2.988, 2.17, 3.058, 0 ] + }, + { "time": 3.1667 } + ] + }, + "flare1": { + "rotate": [ + { "time": 1.1, "value": 8.2 } + ], + "translate": [ + { "time": 1.1, "x": -19.97, "y": 149.68 }, + { "time": 1.2, "x": 3.85, "y": 152.43 }, + { "time": 1.2333, "x": -15.42, "y": 152.29 } + ], + "scale": [ + { + "time": 1.1, + "x": 0.805, + "y": 0.805, + "curve": [ 1.119, 0.763, 1.16, 1.162, 1.117, 0.805, 1.15, 0.605 ] + }, + { + "time": 1.1667, + "x": 1.279, + "y": 0.605, + "curve": [ 1.177, 1.47, 1.192, 2.151, 1.175, 0.605, 1.192, 0.911 ] + }, + { + "time": 1.2, + "x": 2.151, + "y": 0.911, + "curve": [ 1.208, 2.151, 1.231, 1.668, 1.208, 0.911, 1.227, 0.844 ] + }, + { + "time": 1.2333, + "x": 1.608, + "y": 0.805, + "curve": [ 1.249, 1.205, 1.283, 0.547, 1.254, 0.685, 1.283, 0.416 ] + }, + { "time": 1.3, "x": 0.547, "y": 0.416 } + ], + "shear": [ + { "time": 1.1, "y": 4.63 }, + { "time": 1.2333, "x": -5.74, "y": 4.63 } + ] + }, + "flare2": { + "rotate": [ + { "time": 1.1, "value": 12.29 } + ], + "translate": [ + { "time": 1.1, "x": -8.63, "y": 132.96 }, + { "time": 1.2, "x": 4.35, "y": 132.93 } + ], + "scale": [ + { "time": 1.1, "x": 0.864, "y": 0.864 }, + { "time": 1.1667, "x": 0.945, "y": 0.945 }, + { "time": 1.2, "x": 1.511, "y": 1.081 } + ], + "shear": [ + { "time": 1.1, "y": 24.03 } + ] + }, + "flare3": { + "rotate": [ + { "time": 1.1667, "value": 2.88 } + ], + "translate": [ + { "time": 1.1667, "x": 3.24, "y": 114.81 } + ], + "scale": [ + { "time": 1.1667, "x": 0.668, "y": 0.668 } + ], + "shear": [ + { "time": 1.1667, "y": 38.59 } + ] + }, + "flare4": { + "rotate": [ + { "time": 1.1667, "value": -8.64 } + ], + "translate": [ + { "time": 1.1667, "x": -3.82, "y": 194.06 }, + { "time": 1.2667, "x": -1.82, "y": 198.47, "curve": "stepped" }, + { "time": 1.3, "x": -1.94, "y": 187.81 } + ], + "scale": [ + { "time": 1.1667, "x": 0.545, "y": 0.545 }, + { "time": 1.2667, "x": 0.757, "y": 0.757 } + ], + "shear": [ + { "time": 1.1667, "x": 7.42, "y": -22.04 } + ] + }, + "flare5": { + "translate": [ + { "time": 1.2, "x": -11.17, "y": 176.42 }, + { "time": 1.2333, "x": -8.56, "y": 179.04, "curve": "stepped" }, + { "time": 1.3, "x": -14.57, "y": 168.69 } + ], + "scale": [ + { "time": 1.2333, "x": 1.146 }, + { "time": 1.3, "x": 0.703, "y": 0.61 } + ], + "shear": [ + { "time": 1.2, "x": 6.9 } + ] + }, + "flare6": { + "rotate": [ + { "time": 1.2333, "value": -5.36 }, + { "time": 1.2667, "value": -0.54 } + ], + "translate": [ + { "time": 1.2333, "x": 14.52, "y": 204.67 }, + { "time": 1.2667, "x": 19.16, "y": 212.9, "curve": "stepped" }, + { "time": 1.3, "x": 9.23, "y": 202.85 } + ], + "scale": [ + { "time": 1.2333, "x": 0.777, "y": 0.49 }, + { "time": 1.2667, "x": 0.777, "y": 0.657 }, + { "time": 1.3, "x": 0.475, "y": 0.401 } + ] + }, + "flare7": { + "rotate": [ + { "time": 1.1, "value": 5.98 }, + { "time": 1.1333, "value": 32.82 } + ], + "translate": [ + { "time": 1.1, "x": -6.34, "y": 112.98 }, + { "time": 1.1333, "x": 2.66, "y": 111.6 } + ], + "scale": [ + { "time": 1.1, "x": 0.588, "y": 0.588 } + ], + "shear": [ + { "time": 1.1333, "x": -19.93 } + ] + }, + "flare8": { + "rotate": [ + { "time": 1.2333, "value": -6.85 } + ], + "translate": [ + { "time": 1.1667, "x": 66.67, "y": 125.52, "curve": "stepped" }, + { "time": 1.2, "x": 58.24, "y": 113.53, "curve": "stepped" }, + { "time": 1.2333, "x": 40.15, "y": 114.69 } + ], + "scale": [ + { "time": 1.1667, "x": 1.313, "y": 1.203 }, + { "time": 1.2333, "x": 1.038, "y": 0.95 } + ], + "shear": [ + { "time": 1.2, "y": -13.01 } + ] + }, + "flare9": { + "rotate": [ + { "time": 1.1667, "value": 2.9 } + ], + "translate": [ + { "time": 1.1667, "x": 28.45, "y": 151.35, "curve": "stepped" }, + { "time": 1.2, "x": 48.8, "y": 191.09, "curve": "stepped" }, + { "time": 1.2333, "x": 52, "y": 182.52, "curve": "stepped" }, + { "time": 1.2667, "x": 77.01, "y": 195.96 } + ], + "scale": [ + { "time": 1.1667, "x": 0.871, "y": 1.073 }, + { "time": 1.2, "x": 0.927, "y": 0.944 }, + { "time": 1.2333, "x": 1.165, "y": 1.336 } + ], + "shear": [ + { "time": 1.1667, "x": 7.95, "y": 25.48 } + ] + }, + "flare10": { + "rotate": [ + { "time": 1.1667, "value": 2.18 } + ], + "translate": [ + { "time": 1.1667, "x": 55.64, "y": 137.64, "curve": "stepped" }, + { "time": 1.2, "x": 90.49, "y": 151.07, "curve": "stepped" }, + { "time": 1.2333, "x": 114.06, "y": 153.05, "curve": "stepped" }, + { "time": 1.2667, "x": 90.44, "y": 164.61 } + ], + "scale": [ + { "time": 1.1667, "x": 2.657, "y": 0.891 }, + { "time": 1.2, "x": 3.314, "y": 1.425 }, + { "time": 1.2333, "x": 2.871, "y": 0.924 }, + { "time": 1.2667, "x": 2.317, "y": 0.775 } + ], + "shear": [ + { "time": 1.1667, "x": -1.35 } + ] + }, + "torso2": { + "rotate": [ + { + "time": 1, + "curve": [ 1.117, 0, 1.255, 24.94 ] + }, + { + "time": 1.4, + "value": 24.94, + "curve": [ 1.477, 24.94, 1.59, -17.62 ] + }, + { + "time": 1.6333, + "value": -19.48, + "curve": [ 1.717, -23.1, 1.784, -26.12 ] + }, + { + "time": 1.9333, + "value": -26.14, + "curve": [ 2.067, -26.15, 2.158, 4.3 ] + }, + { + "time": 2.3, + "value": 4.22, + "curve": [ 2.45, 4.13, 2.579, -1.76 ] + }, + { + "time": 2.7333, + "value": -1.8, + "curve": [ 2.816, -1.82, 2.857, -2.94 ] + }, + { + "time": 2.9333, + "value": -2.99, + "curve": [ 3.056, -3.08, 3.09, 0 ] + }, + { "time": 3.1667 } + ] + }, + "torso3": { + "rotate": [ + { + "time": 1.3, + "curve": [ 1.352, 0, 1.408, 6.47 ] + }, + { + "time": 1.4667, + "value": 6.43, + "curve": [ 1.55, 6.39, 1.723, -5.05 ] + }, + { + "time": 1.7333, + "value": -5.53, + "curve": [ 1.782, -7.72, 1.843, -16.94 ] + }, + { + "time": 1.9667, + "value": -16.86, + "curve": [ 2.111, -16.78, 2.259, -3.97 ] + }, + { + "time": 2.4, + "value": -2.43, + "curve": [ 2.525, -1.12, 2.639, -0.5 ] + }, + { + "time": 2.7333, + "value": -0.49, + "curve": [ 2.931, -0.47, 2.999, -2.15 ] + }, + { "time": 3.1667, "value": -2.15 } + ] + }, + "head-control": { + "translate": [ + { + "time": 1.2333, + "curve": [ 1.25, 0, 1.474, 6.89, 1.25, 0, 1.496, 0.98 ] + }, + { + "time": 1.6667, + "x": 11.99, + "y": -6.42, + "curve": [ 1.743, 14.01, 1.86, 14.33, 1.785, -11.55, 1.86, -27.1 ] + }, + { + "time": 1.9667, + "x": 13.91, + "y": -26.88, + "curve": [ 2.074, 13.49, 2.244, 8.13, 2.074, -26.65, 2.215, -21.78 ] + }, + { + "time": 2.3, + "x": 6.07, + "y": -16.64, + "curve": [ 2.416, 1.84, 2.497, -1.41, 2.417, -9.57, 2.526, -1.72 ] + }, + { + "time": 2.5667, + "x": -3.78, + "y": -1.71, + "curve": [ 2.661, -6.98, 2.76, -8.76, 2.692, -1.68, 2.821, -15.75 ] + }, + { + "time": 2.9, + "x": -8.32, + "y": -16.7, + "curve": [ 2.962, -8.12, 3.082, -0.04, 2.958, -17.39, 3.089, 0 ] + }, + { "time": 3.1667 } + ] + }, + "front-shoulder": { + "translate": [ + { + "time": 1.3333, + "curve": [ 1.488, 0, 1.717, 0.21, 1.488, 0, 1.688, -30.29 ] + }, + { + "time": 1.9, + "x": 0.83, + "y": -30.29, + "curve": [ 2.078, 1.43, 2.274, 2.88, 2.071, -30.29, 2.289, 4.48 ] + }, + { + "time": 2.4333, + "x": 2.89, + "y": 4.59, + "curve": [ 2.604, 2.89, 2.677, -0.68, 2.57, 4.7, 2.694, -2.43 ] + }, + { + "time": 2.7667, + "x": -0.67, + "y": -2.47, + "curve": [ 2.866, -0.67, 2.986, -0.07, 2.882, -2.47, 3.036, -0.06 ] + }, + { "time": 3.1667 } + ] + } + }, + "ik": { + "rear-leg-ik": [ + { "time": 3.1667, "softness": 10, "bendPositive": false } + ] + } + }, + "run": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" } + ] + } + }, + "bones": { + "front-thigh": { + "translate": [ + { + "x": -5.14, + "y": 11.13, + "curve": [ 0.033, -7.77, 0.112, -9.03, 0.034, 11.13, 0.108, 9.74 ] + }, + { + "time": 0.1667, + "x": -9.03, + "y": 7.99, + "curve": [ 0.23, -9.05, 0.314, -1.34, 0.236, 5.93, 0.28, 3.22 ] + }, + { + "time": 0.3333, + "x": 0.41, + "y": 3.19, + "curve": [ 0.352, 2.09, 0.449, 11.16, 0.384, 3.16, 0.449, 4.98 ] + }, + { + "time": 0.5, + "x": 11.17, + "y": 6.76, + "curve": [ 0.571, 10.79, 0.621, -1.83, 0.542, 8.21, 0.625, 11.13 ] + }, + { "time": 0.6667, "x": -5.14, "y": 11.13 } + ] + }, + "torso": { + "rotate": [ + { + "value": -37.66, + "curve": [ 0.034, -37.14, 0.107, -36.21 ] + }, + { + "time": 0.1333, + "value": -36.21, + "curve": [ 0.158, -36.21, 0.209, -38.8 ] + }, + { + "time": 0.2333, + "value": -38.79, + "curve": [ 0.259, -38.78, 0.313, -38.03 ] + }, + { + "time": 0.3333, + "value": -37.66, + "curve": [ 0.357, -37.21, 0.4, -36.21 ] + }, + { + "time": 0.4333, + "value": -36.21, + "curve": [ 0.458, -36.21, 0.539, -38.8 ] + }, + { + "time": 0.5667, + "value": -38.8, + "curve": [ 0.592, -38.8, 0.645, -38 ] + }, + { "time": 0.6667, "value": -37.66 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -16.41, + "y": 1.55, + "curve": [ 0.013, -15.67, 0.183, -8.55, 0.03, 2.39, 0.183, 6.17 ] + }, + { + "time": 0.2333, + "x": -8.55, + "y": 6.17, + "curve": [ 0.308, -8.55, 0.492, -19.75, 0.308, 6.17, 0.492, 0.61 ] + }, + { + "time": 0.5667, + "x": -19.75, + "y": 0.61, + "curve": [ 0.592, -19.75, 0.641, -18.06, 0.592, 0.61, 0.632, 0.78 ] + }, + { "time": 0.6667, "x": -16.41, "y": 1.55 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -39.03, + "curve": [ 0.051, -0.1, 0.145, 88.36 ] + }, + { + "time": 0.2333, + "value": 88.36, + "curve": [ 0.28, 88.76, 0.324, 59.52 ] + }, + { + "time": 0.3333, + "value": 51.13, + "curve": [ 0.358, 30.2, 0.445, -74.91 ] + }, + { + "time": 0.5667, + "value": -75.82, + "curve": [ 0.599, -76.06, 0.642, -55.72 ] + }, + { "time": 0.6667, "value": -39.03 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 20.54, + "curve": [ 0.052, 11.42, 0.089, 0.13 ] + }, + { + "time": 0.1333, + "value": 0.15, + "curve": [ 0.186, 0.17, 0.221, 26.29 ] + }, + { + "time": 0.2333, + "value": 32.37, + "curve": [ 0.247, 39.19, 0.286, 61.45 ] + }, + { + "time": 0.3333, + "value": 61.58, + "curve": [ 0.371, 61.69, 0.42, 55.79 ] + }, + { "time": 0.4667, "value": 49.68 }, + { "time": 0.6667, "value": 20.54 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16, + "curve": [ 0.014, -38.8, 0.036, -43.27 ] + }, + { + "time": 0.0667, + "value": -43.37, + "curve": [ 0.102, -43.49, 0.182, -28.46 ] + }, + { + "time": 0.2, + "value": -23.04, + "curve": [ 0.23, -13.87, 0.264, 3.86 ] + }, + { + "time": 0.3333, + "value": 3.7, + "curve": [ 0.38, 3.64, 0.535, -16.22 ] + }, + { "time": 0.5667, "value": -21.29 }, + { "time": 0.6667, "value": -36.16 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.5, + "curve": [ 0.028, 23.74, 0.128, -79.86 ] + }, + { + "time": 0.2333, + "value": -79.87, + "curve": [ 0.38, -79.88, 0.403, 63.25 ] + }, + { + "time": 0.5667, + "value": 64.13, + "curve": [ 0.607, 64.35, 0.644, 53.1 ] + }, + { "time": 0.6667, "value": 40.5 } + ], + "translate": [ + { + "x": -3.79, + "y": -0.77, + "curve": [ 0.044, -4.58, 0.169, -5.48, 0.044, 0.93, 0.169, 2.85 ] + }, + { + "time": 0.2333, + "x": -5.48, + "y": 2.85, + "curve": [ 0.346, -5.48, 0.475, -2.68, 0.346, 2.85, 0.475, -3.13 ] + }, + { + "time": 0.5667, + "x": -2.68, + "y": -3.13, + "curve": [ 0.611, -2.68, 0.642, -3.34, 0.611, -3.13, 0.642, -1.73 ] + }, + { "time": 0.6667, "x": -3.79, "y": -0.77 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": 28.28 }, + { + "time": 0.2333, + "value": -11.12, + "curve": [ 0.252, -14.12, 0.297, -19.37 ] + }, + { + "time": 0.3333, + "value": -19.38, + "curve": [ 0.435, -19.41, 0.522, 38.96 ] + }, + { + "time": 0.5667, + "value": 38.87, + "curve": [ 0.619, 38.76, 0.644, 32.01 ] + }, + { "time": 0.6667, "value": 28.28 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.88, + "curve": [ 0.024, 11.4, 0.075, 9.74 ] + }, + { + "time": 0.1, + "value": 9.74, + "curve": [ 0.125, 9.74, 0.208, 13.36 ] + }, + { + "time": 0.2333, + "value": 13.36, + "curve": [ 0.258, 13.36, 0.321, 12.2 ] + }, + { + "time": 0.3333, + "value": 11.88, + "curve": [ 0.365, 11.06, 0.408, 9.72 ] + }, + { + "time": 0.4333, + "value": 9.72, + "curve": [ 0.458, 9.72, 0.542, 13.36 ] + }, + { + "time": 0.5667, + "value": 13.36, + "curve": [ 0.592, 13.36, 0.636, 12.48 ] + }, + { "time": 0.6667, "value": 11.88 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.14, + "curve": [ 0.02, 11.99, 0.039, 8.94 ] + }, + { + "time": 0.0667, + "value": 8.93, + "curve": [ 0.122, 8.9, 0.232, 15.8 ] + }, + { + "time": 0.2667, + "value": 15.81, + "curve": [ 0.325, 15.82, 0.357, 8.95 ] + }, + { + "time": 0.4, + "value": 8.93, + "curve": [ 0.444, 8.91, 0.568, 15.8 ] + }, + { + "time": 0.6, + "value": 15.77, + "curve": [ 0.632, 15.74, 0.649, 14.05 ] + }, + { "time": 0.6667, "value": 13.14 } + ], + "scale": [ + { + "curve": [ 0.014, 0.996, 0.068, 0.991, 0.027, 1.005, 0.083, 1.012 ] + }, + { + "time": 0.1, + "x": 0.991, + "y": 1.012, + "curve": [ 0.128, 0.991, 0.205, 1.018, 0.128, 1.012, 0.197, 0.988 ] + }, + { + "time": 0.2333, + "x": 1.018, + "y": 0.988, + "curve": [ 0.272, 1.018, 0.305, 1.008, 0.262, 0.988, 0.311, 0.995 ] + }, + { + "time": 0.3333, + "curve": [ 0.351, 0.995, 0.417, 0.987, 0.359, 1.006, 0.417, 1.013 ] + }, + { + "time": 0.4333, + "x": 0.987, + "y": 1.013, + "curve": [ 0.467, 0.987, 0.533, 1.02, 0.467, 1.013, 0.533, 0.989 ] + }, + { + "time": 0.5667, + "x": 1.02, + "y": 0.989, + "curve": [ 0.592, 1.02, 0.652, 1.004, 0.592, 0.989, 0.644, 0.996 ] + }, + { "time": 0.6667 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.36, + "curve": [ 0.022, 16.28, 0.087, 20.25 ] + }, + { + "time": 0.1333, + "value": 20.19, + "curve": [ 0.168, 20.32, 0.254, -8.82 ] + }, + { + "time": 0.2667, + "value": -11.88, + "curve": [ 0.291, -17.91, 0.344, -24.11 ] + }, + { + "time": 0.4, + "value": -23.88, + "curve": [ 0.448, -23.69, 0.533, -15.47 ] + }, + { "time": 0.5667, "value": -8.69 }, + { "time": 0.6667, "value": 12.36 } + ] + }, + "hip": { + "rotate": [ + { "value": -8.24 } + ], + "translate": [ + { + "x": -3.6, + "y": -34.1, + "curve": [ 0.042, -3.84, 0.118, 7.62, 0.042, -33.74, 0.112, 20.55 ] + }, + { + "time": 0.1667, + "x": 7.61, + "y": 20.36, + "curve": [ 0.194, 7.6, 0.21, 5.06, 0.204, 20.65, 0.217, -8.69 ] + }, + { + "time": 0.2333, + "x": 1.68, + "y": -18.48, + "curve": [ 0.279, -4.99, 0.297, -5.64, 0.254, -31.08, 0.292, -34.55 ] + }, + { + "time": 0.3333, + "x": -5.76, + "y": -35, + "curve": [ 0.379, -5.9, 0.451, 6.8, 0.384, -35.56, 0.428, 17.6 ] + }, + { + "time": 0.5, + "x": 6.61, + "y": 17.01, + "curve": [ 0.536, 6.47, 0.545, 3.56, 0.533, 16.75, 0.548, -8.71 ] + }, + { + "time": 0.5667, + "x": 0.35, + "y": -18.81, + "curve": [ 0.597, -4.07, 0.642, -3.45, 0.584, -28.58, 0.642, -34.32 ] + }, + { "time": 0.6667, "x": -3.6, "y": -34.1 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": -62.54, + "curve": [ 0.015, -74.19, 0.056, -103.19 ] + }, + { + "time": 0.0667, + "value": -111.08, + "curve": [ 0.092, -129.44, 0.189, -146.55 ] + }, + { + "time": 0.2333, + "value": -146.32, + "curve": [ 0.285, -146.06, 0.32, -125.1 ] + }, + { "time": 0.3333, "value": -117.24 }, + { + "time": 0.5, + "value": -35.07, + "curve": [ 0.522, -28.64, 0.546, -24.84 ] + }, + { + "time": 0.5667, + "value": -24.9, + "curve": [ 0.595, -25, 0.623, -40.82 ] + }, + { "time": 0.6667, "value": -62.54 } + ], + "translate": [ + { "x": 16.34, "y": 0.18 }, + { + "time": 0.0667, + "x": -101.43, + "y": 8.04, + "curve": [ 0.085, -131.35, 0.129, -207.69, 0.08, 14.9, 0.124, 113.28 ] + }, + { + "time": 0.1667, + "x": -207.92, + "y": 145.81, + "curve": [ 0.196, -208.13, 0.21, -202.91, 0.186, 160.26, 0.206, 163.48 ] + }, + { + "time": 0.2333, + "x": -189.94, + "y": 163.85, + "curve": [ 0.27, -169.94, 0.31, -126.19, 0.269, 164.35, 0.316, 85.97 ] + }, + { + "time": 0.3333, + "x": -90.56, + "y": 78.57, + "curve": [ 0.355, -57.99, 0.376, -29.14, 0.35, 71.55, 0.376, 66.4 ] + }, + { + "time": 0.4, + "x": 2.87, + "y": 66.38, + "curve": [ 0.412, 19.24, 0.469, 90.73, 0.429, 66.37, 0.469, 70.66 ] + }, + { + "time": 0.5, + "x": 117.18, + "y": 70.46, + "curve": [ 0.522, 136.24, 0.542, 151.33, 0.539, 70.2, 0.555, 38.25 ] + }, + { + "time": 0.5667, + "x": 151.49, + "y": 25.29, + "curve": [ 0.578, 146.76, 0.586, 133.13, 0.572, 19.7, 0.582, 12.23 ] + }, + { "time": 0.6, "x": 115.02, "y": 0.1 }, + { "time": 0.6667, "x": 16.34, "y": 0.18 } + ] + }, + "front-leg-target": { + "translate": [ + { "x": -13.95, "y": -30.34 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": 18.55 }, + { + "time": 0.2333, + "value": 167.84, + "curve": [ 0.246, 153.66, 0.256, 129.74 ] + }, + { + "time": 0.2667, + "value": 124.32, + "curve": [ 0.296, 124.43, 0.313, 129.93 ] + }, + { + "time": 0.3667, + "value": 129.87, + "curve": [ 0.421, 128.32, 0.519, 0.98 ] + }, + { + "time": 0.5667, + "curve": [ 0.6, 0.27, 0.642, 4.73 ] + }, + { "time": 0.6667, "value": 18.55 } + ], + "translate": [ + { + "x": -176.39, + "y": 134.12, + "curve": [ 0.018, -142.26, 0.054, -94.41, 0.01, 120.96, 0.044, 84.08 ] + }, + { + "time": 0.0667, + "x": -73.56, + "y": 76.68, + "curve": [ 0.086, -42.82, 0.194, 101.2, 0.098, 66.73, 0.198, 60.88 ] + }, + { "time": 0.2333, "x": 98.32, "y": 32.17 }, + { "time": 0.2667, "x": 49.13, "y": -0.63 }, + { + "time": 0.4, + "x": -147.9, + "y": 0.32, + "curve": [ 0.414, -168.78, 0.478, -284.76, 0.43, 30.09, 0.478, 129.14 ] + }, + { + "time": 0.5, + "x": -283.37, + "y": 167.12, + "curve": [ 0.526, -285.66, 0.548, -280.54, 0.516, 194.84, 0.55, 216.53 ] + }, + { + "time": 0.5667, + "x": -266.98, + "y": 216.12, + "curve": [ 0.581, -256.27, 0.643, -206.54, 0.61, 214.82, 0.65, 145.33 ] + }, + { "time": 0.6667, "x": -176.39, "y": 134.12 } + ] + }, + "rear-leg-target": { + "translate": [ + { "x": 85, "y": -33.59 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "value": -147.04, + "curve": [ 0.033, -113.4, 0.161, 44.34 ] + }, + { + "time": 0.2333, + "value": 43.48, + "curve": [ 0.24, 43.41, 0.282, 35.72 ] + }, + { + "time": 0.3, + "value": 0.29, + "curve": [ 0.347, 0.28, 0.396, 4.27 ] + }, + { + "time": 0.4, + "curve": [ 0.424, -23.8, 0.525, -181.39 ] + }, + { + "time": 0.5667, + "value": -181.39, + "curve": [ 0.592, -181.39, 0.642, -169.09 ] + }, + { "time": 0.6667, "value": -147.04 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -0.25, + "curve": [ 0.008, -0.25, 0.056, 1.73 ] + }, + { + "time": 0.0667, + "value": -7.68, + "curve": [ 0.075, -43.13, 0.15, -130.44 ] + }, + { + "time": 0.2, + "value": -130.08, + "curve": [ 0.239, -129.79, 0.272, -126.8 ] + }, + { + "time": 0.3, + "value": -116.24, + "curve": [ 0.333, -103.91, 0.348, -86.1 ] + }, + { + "time": 0.3667, + "value": -71.08, + "curve": [ 0.386, -55.25, 0.415, -32.44 ] + }, + { + "time": 0.4333, + "value": -21.63, + "curve": [ 0.47, -0.01, 0.542, 33.42 ] + }, + { + "time": 0.5667, + "value": 33.2, + "curve": [ 0.622, 32.7, 0.569, 0.64 ] + }, + { "time": 0.6667, "value": -0.25 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.087, -6.81, 0.143, -5.75 ] + }, + { + "time": 0.1667, + "value": -4.3, + "curve": [ 0.183, -3.28, 0.209, 2.79 ] + }, + { + "time": 0.2333, + "value": 2.78, + "curve": [ 0.262, 2.77, 0.305, -6.63 ] + }, + { + "time": 0.3333, + "value": -6.64, + "curve": [ 0.419, -6.68, 0.49, -4.84 ] + }, + { + "time": 0.5, + "value": -4.38, + "curve": [ 0.518, -3.56, 0.574, 2.32 ] + }, + { + "time": 0.6, + "value": 2.33, + "curve": [ 0.643, 2.35, 0.633, -6.81 ] + }, + { "time": 0.6667, "value": -6.81 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.014, -3.17, 0.109, 43.93 ] + }, + { + "time": 0.1333, + "value": 43.95, + "curve": [ 0.177, 43.97, 0.192, -13.76 ] + }, + { + "time": 0.2667, + "value": -13.83, + "curve": [ 0.302, -13.72, 0.322, -8.86 ] + }, + { + "time": 0.3333, + "value": -6.6, + "curve": [ 0.349, -3.5, 0.436, 41.1 ] + }, + { + "time": 0.4667, + "value": 41.05, + "curve": [ 0.51, 40.99, 0.549, -14.06 ] + }, + { + "time": 0.6, + "value": -14.18, + "curve": [ 0.63, -14.26, 0.656, -9.04 ] + }, + { "time": 0.6667, "value": -6.81 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.079, -6.83, 0.108, 0.3 ] + }, + { + "time": 0.1333, + "value": 1.96, + "curve": [ 0.177, 4.89, 0.208, 6.28 ] + }, + { + "time": 0.2333, + "value": 6.29, + "curve": [ 0.313, 6.31, 0.383, 3.49 ] + }, + { + "time": 0.4, + "value": 2.58, + "curve": [ 0.442, 0.28, 0.523, -6.81 ] + }, + { "time": 0.6, "value": -6.81 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.011, -4.06, 0.108, 24.92 ] + }, + { + "time": 0.1333, + "value": 24.92, + "curve": [ 0.158, 24.92, 0.208, -10.62 ] + }, + { + "time": 0.2333, + "value": -10.62, + "curve": [ 0.254, -10.62, 0.312, -9.73 ] + }, + { + "time": 0.3333, + "value": -6.4, + "curve": [ 0.356, -2.95, 0.438, 24.93 ] + }, + { + "time": 0.4667, + "value": 24.93, + "curve": [ 0.492, 24.93, 0.575, -9.78 ] + }, + { + "time": 0.6, + "value": -9.78, + "curve": [ 0.617, -9.78, 0.655, -8.63 ] + }, + { "time": 0.6667, "value": -6.81 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 3.5, + "curve": [ 0.07, 3.51, 0.075, 8.69 ] + }, + { + "time": 0.1, + "value": 8.69, + "curve": [ 0.139, 8.69, 0.214, 6.9 ] + }, + { + "time": 0.2333, + "value": 6.33, + "curve": [ 0.266, 5.34, 0.285, 3.48 ] + }, + { + "time": 0.3333, + "value": 3.48, + "curve": [ 0.398, 3.48, 0.408, 8.68 ] + }, + { + "time": 0.4333, + "value": 8.68, + "curve": [ 0.458, 8.68, 0.551, 6.8 ] + }, + { + "time": 0.5667, + "value": 6.26, + "curve": [ 0.598, 5.17, 0.642, 3.49 ] + }, + { "time": 0.6667, "value": 3.5 } + ] + }, + "torso3": { + "rotate": [ + { + "value": 4.52, + "curve": [ 0.067, 4.54, 0.075, -7.27 ] + }, + { + "time": 0.1, + "value": -7.27, + "curve": [ 0.125, -7.27, 0.227, 0.84 ] + }, + { + "time": 0.2333, + "value": 1.24, + "curve": [ 0.254, 2.5, 0.301, 4.51 ] + }, + { + "time": 0.3333, + "value": 4.52, + "curve": [ 0.386, 4.54, 0.408, -7.35 ] + }, + { + "time": 0.4333, + "value": -7.35, + "curve": [ 0.458, -7.35, 0.549, -0.14 ] + }, + { + "time": 0.5667, + "value": 0.95, + "curve": [ 0.586, 2.18, 0.632, 4.54 ] + }, + { "time": 0.6667, "value": 4.52 } + ] + }, + "aim-constraint-target": { + "rotate": [ + { "value": 30.57 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": -6.5 } + ] + }, + "front-foot": { + "rotate": [ + { "value": 4.5 } + ] + }, + "head-control": { + "translate": [ + { + "y": -9.94, + "curve": [ 0.058, 0, 0.175, -15.32, 0.044, -4.19, 0.175, 5 ] + }, + { + "time": 0.2333, + "x": -15.32, + "y": 5, + "curve": [ 0.317, -15.32, 0.429, -9.74, 0.317, 5, 0.382, -31.71 ] + }, + { + "time": 0.4667, + "x": -7.81, + "y": -31.59, + "curve": [ 0.507, -5.76, 0.617, 0, 0.549, -31.47, 0.628, -13.33 ] + }, + { "time": 0.6667, "y": -9.94 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": -0.74, + "y": 11.22, + "curve": [ 0.061, -0.74, 0.144, 1.17, 0.061, 11.22, 0.143, -17.93 ] + }, + { + "time": 0.2333, + "x": 1.19, + "y": -17.9, + "curve": [ 0.54, 1.25, 0.558, -0.74, 0.545, -17.8, 0.558, 11.22 ] + }, + { "time": 0.6667, "x": -0.74, "y": 11.22 } + ] + }, + "back-shoulder": { + "translate": [ + { + "curve": [ 0.083, 0, 0.25, 0, 0.083, 0, 0.25, 8.93 ] + }, + { + "time": 0.3333, + "y": 8.93, + "curve": [ 0.417, 0, 0.583, 0, 0.417, 8.93, 0.583, 0 ] + }, + { "time": 0.6667 } + ] + } + }, + "ik": { + "front-leg-ik": [ + { "softness": 10, "bendPositive": false }, + { "time": 0.5667, "softness": 14.8, "bendPositive": false }, + { "time": 0.6, "softness": 48.2, "bendPositive": false }, + { "time": 0.6667, "softness": 10, "bendPositive": false } + ], + "rear-leg-ik": [ + { "bendPositive": false }, + { "time": 0.1667, "softness": 22.5, "bendPositive": false }, + { "time": 0.3, "softness": 61.4, "bendPositive": false }, + { "time": 0.6667, "bendPositive": false } + ] + }, + "events": [ + { "time": 0.2333, "name": "footstep" }, + { "time": 0.5667, "name": "footstep" } + ] + }, + "run-to-idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-foot-target": { + "translate": [ + { + "x": -16.5, + "y": 3.41, + "curve": [ 0.033, -16.5, 0.1, -69.06, 0.033, 3.41, 0.1, 0 ] + }, + { "time": 0.1333, "x": -69.06 } + ] + }, + "hip": { + "translate": [ + { + "x": -28.78, + "y": -72.96, + "curve": [ 0.036, -28.63, 0.2, -10.85, 0.135, -62.35, 0.2, -23.15 ] + }, + { "time": 0.2667, "x": -11.97, "y": -23.15 } + ] + }, + "rear-foot-target": { + "translate": [ + { + "x": 33.15, + "y": 31.61, + "curve": [ 0.017, 33.15, 0.05, 24.41, 0.017, 31.61, 0.041, 20.73 ] + }, + { + "time": 0.0667, + "x": 24.41, + "y": 0.19, + "curve": [ 0.117, 24.41, 0.217, 48.87, 0.117, 0.19, 0.217, 0 ] + }, + { "time": 0.2667, "x": 48.87 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -80.61, + "curve": [ 0.067, -80.61, 0.2, -60.87 ] + }, + { "time": 0.2667, "value": -60.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 8.79, + "curve": [ 0.041, 8.79, 0.115, 6.3 ] + }, + { + "time": 0.1667, + "value": 6.41, + "curve": [ 0.201, 6.48, 0.241, 42.46 ] + }, + { "time": 0.2667, "value": 42.46 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 55.3, + "curve": [ 0.067, 55.3, 0.2, 39.2 ] + }, + { "time": 0.2667, "value": 39.2 } + ] + }, + "head": { + "rotate": [ + { + "curve": [ 0.05, 0, 0.083, 2.67 ] + }, + { + "time": 0.1333, + "value": 2.67, + "curve": [ 0.15, 2.67, 0.25, -6.75 ] + }, + { "time": 0.2667, "value": -6.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": 38.26, + "curve": [ 0.041, 38.26, 0.127, -2.19 ] + }, + { + "time": 0.1667, + "value": -3, + "curve": [ 0.209, -3.84, 0.241, 0 ] + }, + { "time": 0.2667 } + ], + "scale": [ + { + "x": 0.844, + "curve": [ 0.067, 0.844, 0.2, 1, 0.067, 1, 0.2, 1 ] + }, + { "time": 0.2667 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 57.24, + "curve": [ 0.067, 57.24, 0.2, 0 ] + }, + { "time": 0.2667 } + ] + }, + "gun": { + "rotate": [ + { + "value": 2.28, + "curve": [ 0.041, 2.28, 0.105, 15.34 ] + }, + { + "time": 0.1667, + "value": 15.32, + "curve": [ 0.205, 15.31, 0.241, 0 ] + }, + { "time": 0.2667 } + ] + }, + "torso": { + "rotate": [ + { + "value": -12.98, + "curve": [ 0.033, -12.98, 0.103, -14.81 ] + }, + { + "time": 0.1333, + "value": -16.63, + "curve": [ 0.168, -18.69, 0.233, -22.88 ] + }, + { "time": 0.2667, "value": -22.88 } + ], + "scale": [ + { + "x": 0.963, + "y": 1.074, + "curve": [ 0.067, 0.963, 0.132, 1, 0.067, 1.074, 0.132, 1 ] + }, + { "time": 0.2667 } + ] + }, + "neck": { + "rotate": [ + {}, + { "time": 0.2667, "value": 3.78 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 0.88 ] + }, + { + "time": 0.1333, + "value": 0.88, + "curve": [ 0.167, 0.88, 0.233, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 15.97 ] + }, + { + "time": 0.1333, + "value": 15.97, + "curve": [ 0.167, 15.97, 0.233, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 10.76 ] + }, + { + "time": 0.1333, + "value": 10.76, + "curve": [ 0.167, 10.76, 0.233, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair2": { + "rotate": [ + { + "curve": [ 0.014, -2.28, 0.042, -7.84 ] + }, + { + "time": 0.0667, + "value": -7.82, + "curve": [ 0.108, -7.79, 0.166, 6.57 ] + }, + { + "time": 0.2, + "value": 6.67, + "curve": [ 0.222, 6.73, 0.255, 1.98 ] + }, + { "time": 0.2667 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.041, 0, 0.107, 3.03 ] + }, + { + "time": 0.1667, + "value": 3.03, + "curve": [ 0.205, 3.03, 0.241, 0 ] + }, + { "time": 0.2667 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.049, 0, 0.166, 0.66 ] + }, + { + "time": 0.2, + "value": 0.66, + "curve": [ 0.232, 0.65, 0.249, -2.15 ] + }, + { "time": 0.2667, "value": -2.15 } + ] + }, + "head-control": { + "translate": [ + { "x": -10.12, "y": 8.71 }, + { "time": 0.2667 } + ] + }, + "front-shoulder": { + "translate": [ + { "x": 4.91, "y": 11.54 }, + { "time": 0.2667 } + ] + } + } + }, + "shoot": { + "slots": { + "muzzle": { + "rgba": [ + { "time": 0.1333, "color": "ffffffff" }, + { "time": 0.2, "color": "ffffff62" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle01" }, + { "time": 0.0667, "name": "muzzle02" }, + { "time": 0.1, "name": "muzzle03" }, + { "time": 0.1333, "name": "muzzle04" }, + { "time": 0.1667, "name": "muzzle05" }, + { "time": 0.2 } + ] + }, + "muzzle-glow": { + "rgba": [ + { "color": "ff0c0c00" }, + { + "time": 0.0333, + "color": "ffc9adff", + "curve": [ 0.255, 1, 0.273, 1, 0.255, 0.76, 0.273, 0.4, 0.255, 0.65, 0.273, 0.22, 0.255, 1, 0.273, 1 ] + }, + { "time": 0.3, "color": "ff400cff" }, + { "time": 0.6333, "color": "ff0c0c00" } + ], + "attachment": [ + { "name": "muzzle-glow" } + ] + }, + "muzzle-ring": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.202, 0.85, 0.214, 0.84, 0.202, 0.73, 0.214, 0.73, 0.202, 1, 0.214, 1, 0.202, 1, 0.214, 0.21 ] + }, + { "time": 0.2333, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2333 } + ] + }, + "muzzle-ring2": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.174, 0.85, 0.184, 0.84, 0.174, 0.73, 0.184, 0.73, 0.174, 1, 0.184, 1, 0.174, 1, 0.184, 0.21 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2 } + ] + }, + "muzzle-ring3": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.174, 0.85, 0.184, 0.84, 0.174, 0.73, 0.184, 0.73, 0.174, 1, 0.184, 1, 0.174, 1, 0.184, 0.21 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2 } + ] + }, + "muzzle-ring4": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.174, 0.85, 0.184, 0.84, 0.174, 0.73, 0.184, 0.73, 0.174, 1, 0.184, 1, 0.174, 1, 0.184, 0.21 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2 } + ] + } + }, + "bones": { + "gun": { + "rotate": [ + { + "time": 0.0667, + "curve": [ 0.094, 25.89, 0.112, 45.27 ] + }, + { + "time": 0.1333, + "value": 45.35, + "curve": [ 0.192, 45.28, 0.18, -0.09 ] + }, + { "time": 0.6333 } + ] + }, + "muzzle": { + "translate": [ + { "x": -11.02, "y": 25.16 } + ] + }, + "rear-upper-arm": { + "translate": [ + { + "time": 0.0333, + "curve": [ 0.045, 0.91, 0.083, 3.46, 0.044, 0.86, 0.083, 3.32 ] + }, + { + "time": 0.1, + "x": 3.46, + "y": 3.32, + "curve": [ 0.133, 3.46, 0.176, -0.1, 0.133, 3.32, 0.169, 0 ] + }, + { "time": 0.2333 } + ] + }, + "rear-bracer": { + "translate": [ + { + "time": 0.0333, + "curve": [ 0.075, -3.78, 0.083, -4.36, 0.08, -2.7, 0.083, -2.88 ] + }, + { + "time": 0.1, + "x": -4.36, + "y": -2.88, + "curve": [ 0.133, -4.36, 0.168, 0.18, 0.133, -2.88, 0.167, 0 ] + }, + { "time": 0.2333 } + ] + }, + "gun-tip": { + "translate": [ + {}, + { "time": 0.3, "x": 3.15, "y": 0.39 } + ], + "scale": [ + { "x": 0.366, "y": 0.366 }, + { "time": 0.0333, "x": 1.453, "y": 1.453 }, + { "time": 0.3, "x": 0.366, "y": 0.366 } + ] + }, + "muzzle-ring": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2333, "x": 64.47 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2333, "x": 5.951, "y": 5.951 } + ] + }, + "muzzle-ring2": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 172.57 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 4, "y": 4 } + ] + }, + "muzzle-ring3": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 277.17 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 2, "y": 2 } + ] + }, + "muzzle-ring4": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 392.06 } + ] + } + } + }, + "walk": { + "bones": { + "rear-foot-target": { + "rotate": [ + { + "value": -32.82, + "curve": [ 0.035, -42.69, 0.057, -70.49 ] + }, + { + "time": 0.1, + "value": -70.59, + "curve": [ 0.236, -70.78, 0.335, -9.87 ] + }, + { + "time": 0.3667, + "value": -1.56, + "curve": [ 0.393, 5.5, 0.477, 13.96 ] + }, + { + "time": 0.5, + "value": 13.96, + "curve": [ 0.519, 13.96, 0.508, 0.13 ] + }, + { "time": 0.5667, "value": -0.28 }, + { + "time": 0.7333, + "value": -0.28, + "curve": [ 0.827, -0.06, 0.958, -21.07 ] + }, + { "time": 1, "value": -32.82 } + ], + "translate": [ + { + "x": -167.32, + "y": 0.58, + "curve": [ 0.022, -180.55, 0.075, -235.51, 0.045, 0.58, 0.075, 30.12 ] + }, + { + "time": 0.1, + "x": -235.51, + "y": 39.92, + "curve": [ 0.142, -235.51, 0.208, -201.73, 0.138, 54.94, 0.18, 60.78 ] + }, + { + "time": 0.2333, + "x": -176.33, + "y": 61.48, + "curve": [ 0.272, -136.61, 0.321, -45.18, 0.275, 62.02, 0.321, 56.6 ] + }, + { + "time": 0.3667, + "x": 8.44, + "y": 49.67, + "curve": [ 0.403, 51.03, 0.486, 66.86, 0.401, 44.37, 0.48, 23.11 ] + }, + { "time": 0.5, "x": 66.57, "y": 14.22 }, + { "time": 0.5333, "x": 52.58, "y": 0.6 }, + { "time": 1, "x": -167.32, "y": 0.58 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": 18.19, + "curve": [ 0.01, 11.17, 0.043, 1.37 ] + }, + { "time": 0.1, "value": 0.47 }, + { + "time": 0.2333, + "value": 0.55, + "curve": [ 0.364, 0.3, 0.515, -80.48 ] + }, + { + "time": 0.7333, + "value": -80.78, + "curve": [ 0.788, -80.38, 0.921, 17.42 ] + }, + { "time": 1, "value": 18.19 } + ], + "translate": [ + { + "x": 139.21, + "y": 22.94, + "curve": [ 0.025, 139.21, 0.069, 111.46, 0.031, 3.25, 0.075, 0.06 ] + }, + { "time": 0.1, "x": 96.69, "y": 0.06 }, + { + "time": 0.5, + "x": -94.87, + "y": -0.03, + "curve": [ 0.518, -106.82, 0.575, -152.56, 0.534, 5.42, 0.557, 38.46 ] + }, + { + "time": 0.6, + "x": -152.56, + "y": 57.05, + "curve": [ 0.633, -152.56, 0.688, -128.05, 0.643, 75.61, 0.7, 84.14 ] + }, + { + "time": 0.7333, + "x": -109.42, + "y": 84.14, + "curve": [ 0.771, -93.91, 0.832, -30.64, 0.787, 84.14, 0.799, 89.65 ] + }, + { + "time": 0.8667, + "x": 17, + "y": 75.25, + "curve": [ 0.903, 66.18, 0.967, 139.21, 0.932, 61.53, 0.967, 44.02 ] + }, + { "time": 1, "x": 139.21, "y": 22.94 } + ] + }, + "hip": { + "rotate": [ + { "value": -4.35 } + ], + "translate": [ + { + "x": -2.86, + "y": -13.86, + "curve": [ 0.025, -2.84, 0.067, -2.82, 0.028, -19.14, 0.054, -24.02 ] + }, + { + "time": 0.1, + "x": -2.61, + "y": -24.19, + "curve": [ 0.143, -2.34, 0.202, -1.79, 0.152, -23.98, 0.213, -14.81 ] + }, + { + "time": 0.2667, + "x": -1.21, + "y": -7.12, + "curve": [ 0.308, -0.86, 0.345, -0.51, 0.306, -1.63, 0.341, 3.15 ] + }, + { + "time": 0.3667, + "x": -0.33, + "y": 3.15, + "curve": [ 0.41, 0.02, 0.458, 0.26, 0.427, 3.3, 0.481, -6.75 ] + }, + { + "time": 0.5, + "x": 0.26, + "y": -10.59, + "curve": [ 0.553, 0.26, 0.559, 0.2, 0.519, -14.41, 0.548, -23.88 ] + }, + { + "time": 0.6, + "x": -0.17, + "y": -23.71, + "curve": [ 0.663, -0.72, 0.798, -2.09, 0.702, -23.36, 0.802, 3.53 ] + }, + { + "time": 0.8667, + "x": -2.46, + "y": 3.48, + "curve": [ 0.901, -2.63, 0.967, -2.87, 0.913, 3.45, 0.967, -7.64 ] + }, + { "time": 1, "x": -2.86, "y": -13.86 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": 28.96, + "curve": [ 0.056, 28.74, 0.049, 19.6 ] + }, + { "time": 0.0667, "value": 1.68 }, + { + "time": 0.5, + "value": -10, + "curve": [ 0.525, -10, 0.592, -54.69 ] + }, + { + "time": 0.6, + "value": -59.66, + "curve": [ 0.623, -74.54, 0.674, -101.78 ] + }, + { + "time": 0.7333, + "value": -101.78, + "curve": [ 0.812, -101.78, 0.855, -84.67 ] + }, + { + "time": 0.8667, + "value": -63.53, + "curve": [ 0.869, -58.38, 0.975, 28.96 ] + }, + { "time": 1, "value": 28.96 } + ] + }, + "torso": { + "rotate": [ + { + "value": -20.72, + "curve": [ 0.025, -20.57, 0.071, -20.04 ] + }, + { + "time": 0.1333, + "value": -20.04, + "curve": [ 0.187, -20.04, 0.285, -21.16 ] + }, + { + "time": 0.3667, + "value": -21.16, + "curve": [ 0.405, -21.16, 0.47, -20.9 ] + }, + { + "time": 0.5, + "value": -20.71, + "curve": [ 0.518, -20.6, 0.582, -20.03 ] + }, + { + "time": 0.6333, + "value": -20.04, + "curve": [ 0.709, -20.05, 0.815, -21.18 ] + }, + { + "time": 0.8667, + "value": -21.18, + "curve": [ 0.908, -21.18, 0.971, -20.93 ] + }, + { "time": 1, "value": -20.72 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.78, + "curve": [ 0.025, 17.93, 0.071, 18.46 ] + }, + { + "time": 0.1333, + "value": 18.46, + "curve": [ 0.187, 18.46, 0.285, 17.34 ] + }, + { + "time": 0.3667, + "value": 17.34, + "curve": [ 0.405, 17.34, 0.47, 17.6 ] + }, + { + "time": 0.5, + "value": 17.79, + "curve": [ 0.518, 17.9, 0.582, 18.47 ] + }, + { + "time": 0.6333, + "value": 18.46, + "curve": [ 0.709, 18.45, 0.815, 17.32 ] + }, + { + "time": 0.8667, + "value": 17.32, + "curve": [ 0.908, 17.32, 0.971, 17.57 ] + }, + { "time": 1, "value": 17.78 } + ] + }, + "head": { + "rotate": [ + { + "value": -12.23, + "curve": [ 0.061, -12.23, 0.191, -7.45 ] + }, + { + "time": 0.2667, + "value": -7.43, + "curve": [ 0.341, -7.42, 0.421, -12.23 ] + }, + { + "time": 0.5, + "value": -12.23, + "curve": [ 0.567, -12.26, 0.694, -7.46 ] + }, + { + "time": 0.7667, + "value": -7.47, + "curve": [ 0.853, -7.49, 0.943, -12.23 ] + }, + { "time": 1, "value": -12.23 } + ], + "scale": [ + { + "curve": [ 0.039, 1, 0.084, 0.991, 0.039, 1, 0.084, 1.019 ] + }, + { + "time": 0.1333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.205, 0.991, 0.318, 1.019, 0.205, 1.019, 0.337, 0.992 ] + }, + { + "time": 0.4, + "x": 1.019, + "y": 0.992, + "curve": [ 0.456, 1.019, 0.494, 1.001, 0.483, 0.991, 0.493, 0.999 ] + }, + { + "time": 0.5, + "curve": [ 0.508, 0.998, 0.584, 0.991, 0.51, 1.002, 0.584, 1.019 ] + }, + { + "time": 0.6333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.705, 0.991, 0.818, 1.019, 0.705, 1.019, 0.837, 0.992 ] + }, + { + "time": 0.9, + "x": 1.019, + "y": 0.992, + "curve": [ 0.956, 1.019, 0.955, 1, 0.983, 0.991, 0.955, 1 ] + }, + { "time": 1 } + ] + }, + "back-foot-tip": { + "rotate": [ + { "value": 4.09 }, + { "time": 0.0333, "value": 3.05 }, + { + "time": 0.1, + "value": -59.01, + "curve": [ 0.124, -72.97, 0.169, -100.05 ] + }, + { + "time": 0.2333, + "value": -99.71, + "curve": [ 0.326, -99.21, 0.349, -37.4 ] + }, + { + "time": 0.3667, + "value": -17.85, + "curve": [ 0.388, 4.74, 0.451, 32.35 ] + }, + { + "time": 0.5, + "value": 32.4, + "curve": [ 0.537, 32.44, 0.566, 6.43 ] + }, + { "time": 0.5667, "value": 2 }, + { "time": 1, "value": 4.09 } + ] + }, + "front-thigh": { + "translate": [ + { + "x": 17.15, + "y": -0.09, + "curve": [ 0.178, 17.14, 0.295, -4.26, 0.009, -0.09, 0.475, 0.02 ] + }, + { + "time": 0.5, + "x": -4.26, + "y": 0.02, + "curve": [ 0.705, -4.27, 0.848, 17.15, 0.525, 0.02, 0.975, -0.09 ] + }, + { "time": 1, "x": 17.15, "y": -0.09 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -17.71, + "y": -4.63, + "curve": [ 0.036, -19.81, 0.043, -20.86, 0.036, -4.63, 0.05, -7.03 ] + }, + { + "time": 0.1, + "x": -20.95, + "y": -7.06, + "curve": [ 0.162, -21.05, 0.4, 7.79, 0.2, -7.13, 0.4, -1.9 ] + }, + { + "time": 0.5, + "x": 7.79, + "y": -1.94, + "curve": [ 0.612, 7.69, 0.875, -10.49, 0.592, -1.97, 0.917, -3.25 ] + }, + { "time": 1, "x": -17.71, "y": -4.63 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 1, + "curve": [ 0.006, 1.2, 0.084, 2.88 ] + }, + { + "time": 0.1333, + "value": 2.88, + "curve": [ 0.205, 2.88, 0.284, -1.17 ] + }, + { + "time": 0.3667, + "value": -1.17, + "curve": [ 0.411, -1.17, 0.481, 0.57 ] + }, + { + "time": 0.5, + "value": 1, + "curve": [ 0.515, 1.33, 0.59, 2.83 ] + }, + { + "time": 0.6333, + "value": 2.85, + "curve": [ 0.683, 2.86, 0.796, -1.2 ] + }, + { + "time": 0.8667, + "value": -1.2, + "curve": [ 0.916, -1.2, 0.984, 0.62 ] + }, + { "time": 1, "value": 1 } + ] + }, + "torso3": { + "rotate": [ + { "value": -1.81 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -9.51, + "curve": [ 0.021, -13.32, 0.058, -19.4 ] + }, + { + "time": 0.1, + "value": -19.4, + "curve": [ 0.238, -19.69, 0.337, 7.78 ] + }, + { + "time": 0.3667, + "value": 16.2, + "curve": [ 0.399, 25.42, 0.497, 60.19 ] + }, + { + "time": 0.6, + "value": 60.26, + "curve": [ 0.719, 60.13, 0.845, 27.61 ] + }, + { + "time": 0.8667, + "value": 22.45, + "curve": [ 0.892, 16.38, 0.979, -3.27 ] + }, + { "time": 1, "value": -9.51 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 13.57, + "curve": [ 0.022, 9.71, 0.147, -3.78 ] + }, + { + "time": 0.3667, + "value": -3.69, + "curve": [ 0.457, -3.66, 0.479, 0.83 ] + }, + { + "time": 0.5, + "value": 4.05, + "curve": [ 0.513, 6.08, 0.635, 30.8 ] + }, + { + "time": 0.8, + "value": 30.92, + "curve": [ 0.974, 31, 0.98, 18.35 ] + }, + { "time": 1, "value": 13.57 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -28.72, + "curve": [ 0.024, -31.74, 0.176, -43.4 ] + }, + { + "time": 0.3667, + "value": -43.6, + "curve": [ 0.403, -43.65, 0.47, -40.15 ] + }, + { + "time": 0.5, + "value": -35.63, + "curve": [ 0.547, -28.59, 0.624, -4.57 ] + }, + { + "time": 0.7333, + "value": -4.59, + "curve": [ 0.891, -4.62, 0.954, -24.28 ] + }, + { "time": 1, "value": -28.48 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.034, 30.94, 0.068, 32.05 ] + }, + { + "time": 0.1, + "value": 31.88, + "curve": [ 0.194, 31.01, 0.336, -0.11 ] + }, + { + "time": 0.3667, + "value": -7.11, + "curve": [ 0.421, -19.73, 0.53, -46.21 ] + }, + { + "time": 0.6, + "value": -45.75, + "curve": [ 0.708, -45.03, 0.844, -13.56 ] + }, + { + "time": 0.8667, + "value": -6.48, + "curve": [ 0.909, 6.59, 0.958, 24.21 ] + }, + { "time": 1, "value": 28.28 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -2.79, + "curve": [ 0.074, -2.84, 0.121, 25.08 ] + }, + { + "time": 0.2333, + "value": 24.99, + "curve": [ 0.35, 24.89, 0.427, -2.86 ] + }, + { + "time": 0.5, + "value": -2.8, + "curve": [ 0.575, -2.73, 0.652, 24.5 ] + }, + { + "time": 0.7333, + "value": 24.55, + "curve": [ 0.828, 24.6, 0.932, -2.69 ] + }, + { "time": 1, "value": -2.79 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.01, + "curve": [ 0.106, -5.97, 0.151, 18.62 ] + }, + { + "time": 0.2333, + "value": 18.72, + "curve": [ 0.336, 18.7, 0.405, -11.37 ] + }, + { + "time": 0.5, + "value": -11.45, + "curve": [ 0.626, -11.46, 0.629, 18.94 ] + }, + { + "time": 0.7333, + "value": 18.92, + "curve": [ 0.833, 18.92, 0.913, -6.06 ] + }, + { "time": 1, "value": -6.01 } + ], + "translate": [ + { "x": 0.03, "y": 1.35 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.06, + "curve": [ 0.044, 11.16, 0.063, 11.49 ] + }, + { + "time": 0.1, + "value": 11.49, + "curve": [ 0.215, 11.49, 0.336, 2.92 ] + }, + { + "time": 0.3667, + "value": 0.84, + "curve": [ 0.416, -2.52, 0.498, -10.84 ] + }, + { + "time": 0.6, + "value": -10.83, + "curve": [ 0.762, -10.71, 0.845, -3.05 ] + }, + { + "time": 0.8667, + "value": -1.34, + "curve": [ 0.917, 2.54, 0.977, 8.81 ] + }, + { "time": 1, "value": 10.06 } + ] + }, + "gun": { + "rotate": [ + { + "value": -14.67, + "curve": [ 0.086, -14.67, 0.202, 8.31 ] + }, + { + "time": 0.2333, + "value": 12.14, + "curve": [ 0.279, 17.71, 0.391, 25.79 ] + }, + { + "time": 0.5, + "value": 25.77, + "curve": [ 0.631, 25.74, 0.694, 4.53 ] + }, + { + "time": 0.7333, + "value": -0.65, + "curve": [ 0.768, -5.21, 0.902, -14.4 ] + }, + { "time": 1, "value": -14.67 } + ] + }, + "front-leg-target": { + "translate": [ + { + "x": -2.83, + "y": -8.48, + "curve": [ 0.008, -2.83, 0.058, 0.09, 0.001, 4.97, 0.058, 6.68 ] + }, + { + "time": 0.0667, + "x": 0.09, + "y": 6.68, + "curve": [ 0.3, 0.09, 0.767, -2.83, 0.3, 6.68, 0.767, -8.48 ] + }, + { "time": 1, "x": -2.83, "y": -8.48 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.028, 1.24, 0.016, 3.46 ] + }, + { + "time": 0.1, + "value": 3.45, + "curve": [ 0.159, 3.45, 0.189, 0.23 ] + }, + { + "time": 0.2333, + "value": -2.29, + "curve": [ 0.265, -4.32, 0.305, -5.92 ] + }, + { + "time": 0.3667, + "value": -5.94, + "curve": [ 0.446, -5.96, 0.52, 3.41 ] + }, + { + "time": 0.6, + "value": 3.42, + "curve": [ 0.717, 3.42, 0.772, -5.93 ] + }, + { + "time": 0.8667, + "value": -5.97, + "curve": [ 0.933, -5.99, 0.982, -0.94 ] + }, + { "time": 1 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.067, 0, 0.159, -10.48 ] + }, + { + "time": 0.2333, + "value": -10.49, + "curve": [ 0.334, -10.5, 0.439, -0.09 ] + }, + { + "time": 0.5, + "value": -0.09, + "curve": [ 0.569, -0.09, 0.658, -10.75 ] + }, + { + "time": 0.7333, + "value": -10.7, + "curve": [ 0.833, -10.63, 0.947, 0 ] + }, + { "time": 1 } + ] + }, + "gun-tip": { + "rotate": [ + { "time": 0.2333, "value": 0.11 } + ] + }, + "muzzle-ring": { + "rotate": [ + { "time": 0.2333, "value": 0.11 } + ] + }, + "muzzle-ring2": { + "rotate": [ + { "time": 0.2667, "value": 0.11 } + ] + }, + "muzzle-ring3": { + "rotate": [ + { "time": 0.2667, "value": 0.11 } + ] + }, + "muzzle-ring4": { + "rotate": [ + { "time": 0.2667, "value": 0.11 } + ] + }, + "back-shoulder": { + "translate": [ + { + "x": -0.18, + "y": -4.49, + "curve": [ 0.133, -0.18, 0.333, 7.69, 0.133, -4.49, 0.333, 2.77 ] + }, + { + "time": 0.4667, + "x": 7.69, + "y": 2.77, + "curve": [ 0.6, 7.69, 0.858, -0.18, 0.6, 2.77, 0.858, -4.49 ] + }, + { "time": 1, "x": -0.18, "y": -4.49 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.46, + "y": 9.37, + "curve": [ 0.162, 1.41, 0.333, -1.66, 0.162, 9.37, 0.301, -7.23 ] + }, + { + "time": 0.5, + "x": -1.6, + "y": -7.27, + "curve": [ 0.735, -1.5, 0.847, 1.46, 0.723, -7.31, 0.838, 9.32 ] + }, + { "time": 1, "x": 1.46, "y": 9.37 } + ] + }, + "head-control": { + "translate": [ + { + "x": -6.46, + "y": -8.4, + "curve": [ 0.053, -5.31, 0.167, -3.64, 0.093, -8.4, 0.196, -3.81 ] + }, + { + "time": 0.2333, + "x": -3.64, + "y": -1.32, + "curve": [ 0.309, -3.64, 0.436, -5.84, 0.275, 1.43, 0.38, 10.3 ] + }, + { + "time": 0.5, + "x": -7.03, + "y": 10.29, + "curve": [ 0.538, -7.75, 0.66, -10.54, 0.598, 10.27, 0.694, 1.56 ] + }, + { + "time": 0.7333, + "x": -10.54, + "y": -1.26, + "curve": [ 0.797, -10.54, 0.933, -7.91, 0.768, -3.79, 0.875, -8.4 ] + }, + { "time": 1, "x": -6.46, "y": -8.4 } + ] + } + }, + "ik": { + "front-leg-ik": [ + { + "softness": 25.7, + "bendPositive": false, + "curve": [ 0.008, 1, 0.025, 1, 0.008, 25.7, 0.025, 9.9 ] + }, + { + "time": 0.0333, + "softness": 9.9, + "bendPositive": false, + "curve": [ 0.15, 1, 0.383, 1, 0.15, 9.9, 0.383, 43.2 ] + }, + { + "time": 0.5, + "softness": 43.2, + "bendPositive": false, + "curve": [ 0.625, 1, 0.875, 1, 0.625, 43.2, 0.846, 45.57 ] + }, + { "time": 1, "softness": 25.7, "bendPositive": false } + ], + "rear-leg-ik": [ + { "softness": 5, "bendPositive": false }, + { "time": 0.4333, "softness": 4.9, "bendPositive": false }, + { "time": 0.5, "softness": 28.81, "bendPositive": false }, + { "time": 0.6, "softness": 43.8, "bendPositive": false }, + { "time": 1, "softness": 5, "bendPositive": false } + ] + }, + "events": [ + { "name": "footstep" }, + { "time": 0.5, "name": "footstep" } + ] + } +} +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-pro.skel b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-pro.skel new file mode 100644 index 0000000..c14f304 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-pro.skel differ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-run.atlas b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-run.atlas new file mode 100644 index 0000000..e54da2e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-run.atlas @@ -0,0 +1,50 @@ +spineboy-run.png + size: 1182, 687 + filter: Linear, Linear + pma: true +spineboy-pro-run + index: 8 + bounds: 2, 371, 304, 314 + offsets: 11, 22, 316, 341 +spineboy-pro-run + index: 9 + bounds: 2, 44, 278, 325 + offsets: 30, 2, 316, 341 +spineboy-pro-run + index: 0 + bounds: 308, 439, 246, 320 + offsets: 67, 1, 316, 341 + rotate: 90 +spineboy-pro-run + index: 3 + bounds: 630, 443, 242, 320 + offsets: 12, 20, 316, 341 + rotate: 90 +spineboy-pro-run + index: 7 + bounds: 952, 389, 228, 296 + offsets: 36, 33, 316, 341 +spineboy-pro-run + index: 4 + bounds: 308, 195, 242, 320 + offsets: 2, 4, 316, 341 + rotate: 90 +spineboy-pro-run + index: 5 + bounds: 630, 200, 241, 316 + offsets: 8, 3, 316, 341 + rotate: 90 +spineboy-pro-run + index: 1 + bounds: 282, 2, 191, 318 + offsets: 70, 3, 316, 341 + rotate: 90 +spineboy-pro-run + index: 2 + bounds: 948, 81, 226, 306 + offsets: 34, 26, 316, 341 +spineboy-pro-run + index: 6 + bounds: 630, 4, 194, 316 + offsets: 68, 4, 316, 341 + rotate: 90 diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-run.png b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-run.png new file mode 100644 index 0000000..f3ac39f Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy-run.png differ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy.atlas b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy.atlas new file mode 100644 index 0000000..b07ccc3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy.atlas @@ -0,0 +1,101 @@ +spineboy.png + size: 1024, 256 + filter: Linear, Linear + scale: 0.5 +crosshair + bounds: 813, 160, 45, 45 +eye-indifferent + bounds: 569, 2, 47, 45 +eye-surprised + bounds: 643, 7, 47, 45 + rotate: 90 +front-bracer + bounds: 811, 51, 29, 40 +front-fist-closed + bounds: 807, 93, 38, 41 +front-fist-open + bounds: 815, 210, 43, 44 +front-foot + bounds: 706, 64, 63, 35 + rotate: 90 +front-shin + bounds: 80, 11, 41, 92 +front-thigh + bounds: 754, 12, 23, 56 +front-upper-arm + bounds: 618, 5, 23, 49 +goggles + bounds: 214, 20, 131, 83 +gun + bounds: 347, 14, 105, 102 + rotate: 90 +head + bounds: 80, 105, 136, 149 +hoverboard-board + bounds: 2, 8, 246, 76 + rotate: 90 +hoverboard-thruster + bounds: 478, 2, 30, 32 +hoverglow-small + bounds: 218, 117, 137, 38 + rotate: 90 +mouth-grind + bounds: 775, 80, 47, 30 + rotate: 90 +mouth-oooo + bounds: 779, 31, 47, 30 + rotate: 90 +mouth-smile + bounds: 783, 207, 47, 30 + rotate: 90 +muzzle-glow + bounds: 779, 4, 25, 25 +muzzle-ring + bounds: 451, 14, 25, 105 +muzzle01 + bounds: 664, 60, 67, 40 + rotate: 90 +muzzle02 + bounds: 580, 56, 68, 42 + rotate: 90 +muzzle03 + bounds: 478, 36, 83, 53 + rotate: 90 +muzzle04 + bounds: 533, 49, 75, 45 + rotate: 90 +muzzle05 + bounds: 624, 56, 68, 38 + rotate: 90 +neck + bounds: 806, 8, 18, 21 +portal-bg + bounds: 258, 121, 133, 133 +portal-flare1 + bounds: 690, 2, 56, 30 + rotate: 90 +portal-flare2 + bounds: 510, 3, 57, 31 +portal-flare3 + bounds: 722, 4, 58, 30 + rotate: 90 +portal-shade + bounds: 393, 121, 133, 133 +portal-streaks1 + bounds: 528, 126, 126, 128 +portal-streaks2 + bounds: 656, 129, 125, 125 +rear-bracer + bounds: 826, 13, 28, 36 +rear-foot + bounds: 743, 70, 57, 30 + rotate: 90 +rear-shin + bounds: 174, 14, 38, 89 +rear-thigh + bounds: 783, 158, 28, 47 +rear-upper-arm + bounds: 783, 136, 20, 44 + rotate: 90 +torso + bounds: 123, 13, 49, 90 diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy.png b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy.png new file mode 100644 index 0000000..074f1e3 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/export/spineboy.png differ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/license.txt b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/license.txt new file mode 100644 index 0000000..ba9fe3d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/license.txt @@ -0,0 +1,8 @@ +Copyright (c) 2013, Esoteric Software LLC + +The images in this project may be redistributed as long as they are accompanied +by this license file. The images may not be used for commercial use of any +kind. + +The project file is released into the public domain. It may be used as the basis +for derivative work. \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/spineboy-ess.spine b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/spineboy-ess.spine new file mode 100644 index 0000000..1594eac Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/spineboy-ess.spine differ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/spineboy-pro.spine b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/spineboy-pro.spine new file mode 100644 index 0000000..63190b5 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.1/examples/spineboy/spineboy-pro.spine differ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/CMakeLists.txt b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/CMakeLists.txt new file mode 100644 index 0000000..96e5a7a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/CMakeLists.txt @@ -0,0 +1,25 @@ +if(MSVC) + message("MSCV detected") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + set (CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}") +else() + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic -std=c89") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wnon-virtual-dtor -pedantic -std=c++11 -fno-exceptions -fno-rtti") +endif() + +include_directories(include) +file(GLOB INCLUDES "spine-cpp/include/**/*.h") +file(GLOB SOURCES "spine-cpp/src/**/*.cpp") + +add_library(spine-cpp STATIC ${SOURCES} ${INCLUDES}) +target_include_directories(spine-cpp PUBLIC spine-cpp/include) + +# Install target +install(TARGETS spine-cpp EXPORT spine-cpp_TARGETS DESTINATION dist/lib) +install(FILES ${INCLUDES} DESTINATION dist/include) + +# Export target +export( + EXPORT spine-cpp_TARGETS + FILE ${CMAKE_CURRENT_BINARY_DIR}/spine-cppTargets.cmake + NAMESPACE "Spine::") \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/LICENSE b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/LICENSE new file mode 100644 index 0000000..4501a61 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/LICENSE @@ -0,0 +1,26 @@ +Spine Runtimes License Agreement +Last updated May 1, 2019. Replaces all prior versions. + +Copyright (c) 2013-2019, Esoteric Software LLC + +Integration of the Spine Runtimes into software or otherwise creating +derivative works of the Spine Runtimes is permitted under the terms and +conditions of Section 2 of the Spine Editor License Agreement: +http://esotericsoftware.com/spine-editor-license + +Otherwise, it is permitted to integrate the Spine Runtimes into software +or otherwise create derivative works of the Spine Runtimes (collectively, +"Products"), provided that each user of the Products must obtain their own +Spine Editor license and redistribution of the Products in any form must +include this license and copyright notice. + +THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS +INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/README.md b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/README.md new file mode 100644 index 0000000..dba490a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/README.md @@ -0,0 +1,54 @@ +# spine-cpp + +The spine-cpp runtime provides basic functionality to load and manipulate [spine](http://esotericsoftware.com) skeletal animation data using C++. It does not perform rendering but can be extended to enable spine animations for other projects that utilize C++. + +## Licensing + +You are welcome to evaluate the Spine Runtimes and the examples we provide in this repository free of charge. + +You can integrate the Spine Runtimes into your software free of charge, but users of your software must have their own [Spine license](https://esotericsoftware.com/spine-purchase). Please make your users aware of this requirement! This option is often chosen by those making development tools, such as an SDK, game toolkit, or software library. + +In order to distribute your software containing the Spine Runtimes to others that don't have a Spine license, you need a [Spine license](https://esotericsoftware.com/spine-purchase) at the time of integration. Then you can distribute your software containing the Spine Runtimes however you like, provided others don't modify it or use it to create new software. If others want to do that, they'll need their own Spine license. + +For the official legal terms governing the Spine Runtimes, please read the [Spine Runtimes License Agreement](http://esotericsoftware.com/spine-runtimes-license) and Section 2 of the [Spine Editor License Agreement](http://esotericsoftware.com/spine-editor-license#s2). + +## Spine version + +spine-cpp works with data exported from spine 4.1.xx. + +spine-cpp supports all spine features. + +## Setup + +1. Download the spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it as a zip via the download button above. +2. Copy the contents of the `spine-cpp/spine-cpp/src` and `spine-cpp/spine-cpp/include` directories into your project. Be sure your header search is configured to find the contents of the `spine-cpp/spine-cpp/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files. + +## Usage +### [Please see the spine-cpp guide for full documentation](http://esotericsoftware.com/spine-cpp) + +## Extension + +Extending spine-cpp requires implementing both the `SpineExtension` class and the TextureLoader class: + +``` +#include +void spine::SpineExtension *spine::getDefaultExtension() { + return new spine::DefaultExtension(); +} + +class MyTextureLoader : public spine::TextureLoader +{ + virtual void load(spine::AtlasPage& page, const spine::String& path) { + void* texture = ... load the texture based on path ... + page->setRendererObject(texture); // use the texture later in your rendering code + } + + virtual void unload(void* texture) { // TODO } +}; +``` + +## Runtimes extending spine-cpp + +- [spine-sfml](../spine-sfml/cpp) +- [spine-cocos2dx](../spine-cocos2dx) +- [spine-ue4](../spine-ue4) diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp-unit-tests/CMakeLists.txt b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp-unit-tests/CMakeLists.txt new file mode 100755 index 0000000..146eb22 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp-unit-tests/CMakeLists.txt @@ -0,0 +1,32 @@ +project(spine_cpp_unit_test) + +set(SRC src/main.cpp) +add_executable(spine_cpp_unit_test ${SRC}) +target_link_libraries(spine_cpp_unit_test spine-cpp) + +######################################################### +# copy resources to build output directory +######################################################### +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/spineboy/export $/testdata/spineboy) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/raptor/export $/testdata/raptor) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/goblins/export $/testdata/goblins) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/coin/export $/testdata/coin) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/tank/export $/testdata/tank) + +add_custom_command(TARGET spine_cpp_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/stretchyman/export $/testdata/stretchyman) diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp-unit-tests/README.md b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp-unit-tests/README.md new file mode 100755 index 0000000..a7d6efb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp-unit-tests/README.md @@ -0,0 +1,67 @@ +# spine-cpp-unit-tests + +The spine-cpp-unit-tests project is to test the [spine](http://esotericsoftware.com) skeletal animation system. It does not perform rendering. It is primarily used for regression testing and leak detection. It is designed to be run from a Continuous Integration server and to passively verify changes automatically on check-in. + +## Mini CPP Unit Testing +[MiniCppUnit](https://sourceforge.net/p/minicppunit/wiki/Home/) is a minimal unit testing framework similar to JUnit. It is used here to avoid large dependancies. + +Tests are sorted into Suites, Fixtures and Cases. There is one suite, it contains many fixtures and each fixture contains test cases. To turn off a fixture, edit "TestOptions.h". To turn off specific test cases, comment out the TEST_CASE() line in the fixture's header. + +## Memory Leak Detection +This project includes a very minimal memory leak detector. It is based roughly on the leak detector in the [Popcap Framework](https://sourceforge.net/projects/popcapframework/?source=directory), but has been modified over the years. + +## Continuous Integration +The test runner includes the ability to format output messages to signal a CI server. An example interface for [Teamcity](https://www.jetbrains.com/teamcity/) is included. To implement for another server, determine the wireformat for the messages and duplicate/edit the teamcity_messages class. [Teamcity Wire Format](https://confluence.jetbrains.com/display/TCD10/Build+Script+Interaction+with+TeamCity) + +### Trigger +Your CI server should trigger on VCS check-in. + +### CMake Build Step +The first build step for the CI server should be to run CMake on the 'spine-cpp-unit-tests' folder. Follow the usage directions below. + +### Compile Build Step +This build step should not execute if the previous step did not successfully complete. +Depending on the test agent build environment, you should build the output solution or project from the cmake step. Debug is fine. + +### Test Runner Build Step +This build step should not execute if the previous step did not successfully complete. +Again, depending on the test agent build environment, you should have produced an executable. Run this executable. + + +## Usage +Make sure [CMake](https://cmake.org/download/) is installed. + +Create a 'build' directory in the 'spine-cpp-unit-tests' folder. Then switch to that folder and execute cmake: + +mkdir build +cd build +cmake .. + +### Win32 build +msbuild spine_unit_test.sln /t:spine_unit_test /p:Configuration="Debug" /p:Platform="Win32" + + +## Licensing +This spine Runtime may only be used for personal or internal use, typically to evaluate spine before purchasing. If you would like to incorporate a spine Runtime into your applications, distribute software containing a spine Runtime, or modify a spine Runtime, then you will need a valid [spine license](https://esotericsoftware.com/spine-purchase). Please see the [spine Runtimes Software License](https://github.com/EsotericSoftware/spine-runtimes/blob/master/LICENSE) for detailed information. + +The spine Runtimes are developed with the intent to be used with data exported from spine. By purchasing spine, `Section 2` of the [spine Software License](https://esotericsoftware.com/files/license.txt) grants the right to create and distribute derivative works of the spine Runtimes. + +original "walk"": 330 +second "walk": 0d0 + +queue interrupt for original walk +queue start for second walk +drain interrupt and start + +0d0 is interrupted +0d0 is ended + +"run": 0c0 + 0d0 is interrupted + second walk becomes mixingFrom of run + 0c0 is started + + queue is drained + + first walk: 6f0 + second walk: 9c0 diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp-unit-tests/src/main.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp-unit-tests/src/main.cpp new file mode 100644 index 0000000..6cb8e05 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp-unit-tests/src/main.cpp @@ -0,0 +1,116 @@ +#include +#include +#include + +#ifdef MSVC +#pragma warning(disable : 4710) +#endif + +using namespace spine; + +void loadBinary(const String &binaryFile, const String &atlasFile, Atlas *&atlas, SkeletonData *&skeletonData, + AnimationStateData *&stateData, Skeleton *&skeleton, AnimationState *&state) { + atlas = new (__FILE__, __LINE__) Atlas(atlasFile, NULL); + assert(atlas != NULL); + + SkeletonBinary binary(atlas); + skeletonData = binary.readSkeletonDataFile(binaryFile); + assert(skeletonData); + + skeleton = new (__FILE__, __LINE__) Skeleton(skeletonData); + assert(skeleton != NULL); + + stateData = new (__FILE__, __LINE__) AnimationStateData(skeletonData); + assert(stateData != NULL); + stateData->setDefaultMix(0.4f); + + state = new (__FILE__, __LINE__) AnimationState(stateData); +} + +void loadJson(const String &jsonFile, const String &atlasFile, Atlas *&atlas, SkeletonData *&skeletonData, + AnimationStateData *&stateData, Skeleton *&skeleton, AnimationState *&state) { + atlas = new (__FILE__, __LINE__) Atlas(atlasFile, NULL); + assert(atlas != NULL); + + SkeletonJson json(atlas); + skeletonData = json.readSkeletonDataFile(jsonFile); + assert(skeletonData); + + skeleton = new (__FILE__, __LINE__) Skeleton(skeletonData); + assert(skeleton != NULL); + + stateData = new (__FILE__, __LINE__) AnimationStateData(skeletonData); + assert(stateData != NULL); + stateData->setDefaultMix(0.4f); + + state = new (__FILE__, __LINE__) AnimationState(stateData); +} + +void dispose(Atlas *atlas, SkeletonData *skeletonData, AnimationStateData *stateData, Skeleton *skeleton, + AnimationState *state) { + delete skeleton; + delete state; + delete stateData; + delete skeletonData; + delete atlas; +} + +struct TestData { + TestData(const String &jsonSkeleton, const String &binarySkeleton, const String &atlas) : _jsonSkeleton( + jsonSkeleton), + _binarySkeleton( + binarySkeleton), + _atlas(atlas) {} + + String _jsonSkeleton; + String _binarySkeleton; + String _atlas; +}; + +void testLoading() { + Vector testData; + testData.add(TestData("testdata/coin/coin-pro.json", "testdata/coin/coin-pro.skel", "testdata/coin/coin.atlas")); + /*testData.add(TestData("testdata/goblins/goblins-pro.json", "testdata/goblins/goblins-pro.skel", + "testdata/goblins/goblins.atlas")); + testData.add(TestData("testdata/raptor/raptor-pro.json", "testdata/raptor/raptor-pro.skel", + "testdata/raptor/raptor.atlas")); + testData.add(TestData("testdata/spineboy/spineboy-pro.json", "testdata/spineboy/spineboy-pro.skel", + "testdata/spineboy/spineboy.atlas")); + testData.add(TestData("testdata/stretchyman/stretchyman-pro.json", "testdata/stretchyman/stretchyman-pro.skel", + "testdata/stretchyman/stretchyman.atlas")); + testData.add(TestData("testdata/tank/tank-pro.json", "testdata/tank/tank-pro.skel", "testdata/tank/tank.atlas"));*/ + + for (size_t i = 0; i < testData.size(); i++) { + TestData &data = testData[i]; + Atlas *atlas = NULL; + SkeletonData *skeletonData = NULL; + AnimationStateData *stateData = NULL; + Skeleton *skeleton = NULL; + AnimationState *state = NULL; + + printf("Loading %s\n", data._jsonSkeleton.buffer()); + loadJson(data._jsonSkeleton, data._atlas, atlas, skeletonData, stateData, skeleton, state); + dispose(atlas, skeletonData, stateData, skeleton, state); + + printf("Loading %s\n", data._binarySkeleton.buffer()); + loadBinary(data._binarySkeleton, data._atlas, atlas, skeletonData, stateData, skeleton, state); + dispose(atlas, skeletonData, stateData, skeleton, state); + } +} + +namespace spine { + SpineExtension *getDefaultExtension() { + return new DefaultSpineExtension(); + } +}// namespace spine + +int main(int argc, char **argv) { + SP_UNUSED(argc); + SP_UNUSED(argv); + DebugExtension debug(SpineExtension::getInstance()); + SpineExtension::setInstance(&debug); + + testLoading(); + + debug.reportLeaks(); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Animation.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Animation.h new file mode 100644 index 0000000..f21f88e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Animation.h @@ -0,0 +1,131 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Animation_h +#define Spine_Animation_h + +#include +#include +#include +#include +#include +#include +#include + +namespace spine { + class Timeline; + + class Skeleton; + + class Event; + + class AnimationState; + + class SP_API Animation : public SpineObject { + friend class AnimationState; + + friend class TrackEntry; + + friend class AnimationStateData; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class RotateTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + friend class TwoColorTimeline; + + public: + Animation(const String &name, Vector &timelines, float duration); + + ~Animation(); + + /// Applies all the animation's timelines to the specified skeleton. + /// See also Timeline::apply(Skeleton&, float, float, Vector, float, MixPose, MixDirection) + void apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction); + + const String &getName(); + + Vector &getTimelines(); + + bool hasTimeline(Vector &ids); + + float getDuration(); + + void setDuration(float inValue); + + /// @param target After the first and before the last entry. + static int search(Vector &values, float target); + + static int search(Vector &values, float target, int step); + private: + Vector _timelines; + HashMap _timelineIds; + float _duration; + String _name; + }; +} + +#endif /* Spine_Animation_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AnimationState.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AnimationState.h new file mode 100644 index 0000000..52cc69f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -0,0 +1,502 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AnimationState_h +#define Spine_AnimationState_h + +#include +#include +#include +#include +#include +#include +#include +#include "Slot.h" + +#ifdef SPINE_USE_STD_FUNCTION +#include +#endif + +namespace spine { + enum EventType { + EventType_Start = 0, + EventType_Interrupt, + EventType_End, + EventType_Complete, + EventType_Dispose, + EventType_Event + }; + + class AnimationState; + + class TrackEntry; + + class Animation; + + class Event; + + class AnimationStateData; + + class Skeleton; + + class RotateTimeline; + + class AttachmentTimeline; + +#ifdef SPINE_USE_STD_FUNCTION + typedef std::function AnimationStateListener; +#else + + typedef void (*AnimationStateListener)(AnimationState *state, EventType type, TrackEntry *entry, Event *event); + +#endif + + /// Abstract class to inherit from to create a callback object + class SP_API AnimationStateListenerObject { + public: + AnimationStateListenerObject() {}; + + virtual ~AnimationStateListenerObject() {}; + public: + /// The callback function to be called + virtual void callback(AnimationState *state, EventType type, TrackEntry *entry, Event *event) = 0; + }; + + /// State for the playback of an animation + class SP_API TrackEntry : public SpineObject, public HasRendererObject { + friend class EventQueue; + + friend class AnimationState; + + public: + TrackEntry(); + + virtual ~TrackEntry(); + + /// The index of the track where this entry is either current or queued. + int getTrackIndex(); + + /// The animation to apply for this track entry. + Animation *getAnimation(); + + TrackEntry *getPrevious(); + + /// If true, the animation will repeat. If false, it will not, instead its last frame is applied if played beyond its duration. + bool getLoop(); + + void setLoop(bool inValue); + + /// If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead + /// of being mixed out. + /// + /// When mixing between animations that key the same property, if a lower track also keys that property then the value will + /// briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0% + /// while the second animation mixes from 0% to 100%. Setting holdPrevious to true applies the first animation + /// at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which + /// keys the property, only when a higher track also keys the property. + /// + /// Snapping will occur if holdPrevious is true and this animation does not key all the same properties as the + /// previous animation. + bool getHoldPrevious(); + + void setHoldPrevious(bool inValue); + + bool getReverse(); + + void setReverse(bool inValue); + + bool getShortestRotation(); + + void setShortestRotation(bool inValue); + + /// Seconds to postpone playing the animation. When a track entry is the current track entry, delay postpones incrementing + /// the track time. When a track entry is queued, delay is the time from the start of the previous animation to when the + /// track entry will become the current track entry. + float getDelay(); + + void setDelay(float inValue); + + /// Current time in seconds this track entry has been the current track entry. The track time determines + /// TrackEntry.AnimationTime. The track time can be set to start the animation at a time other than 0, without affecting looping. + float getTrackTime(); + + void setTrackTime(float inValue); + + /// The track time in seconds when this animation will be removed from the track. Defaults to the animation duration for + /// non-looping animations and to int.MaxValue for looping animations. If the track end time is reached and no + /// other animations are queued for playback, and mixing from any previous animations is complete, properties keyed by the animation, + /// are set to the setup pose and the track is cleared. + /// + /// It may be desired to use AnimationState.addEmptyAnimation(int, float, float) to mix the properties back to the + /// setup pose over time, rather than have it happen instantly. + float getTrackEnd(); + + void setTrackEnd(float inValue); + + /// Seconds when this animation starts, both initially and after looping. Defaults to 0. + /// + /// When changing the animation start time, it often makes sense to set TrackEntry.AnimationLast to the same value to + /// prevent timeline keys before the start time from triggering. + float getAnimationStart(); + + void setAnimationStart(float inValue); + + /// Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will + /// loop back to TrackEntry.AnimationStart at this time. Defaults to the animation duration. + float getAnimationEnd(); + + void setAnimationEnd(float inValue); + + /// The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this + /// animation is applied, event timelines will fire all events between the animation last time (exclusive) and animation time + /// (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation is applied. + float getAnimationLast(); + + void setAnimationLast(float inValue); + + /// Uses TrackEntry.TrackTime to compute the animation time between TrackEntry.AnimationStart. and + /// TrackEntry.AnimationEnd. When the track time is 0, the animation time is equal to the animation start time. + float getAnimationTime(); + + /// Multiplier for the delta time when the animation state is updated, causing time for this animation to play slower or + /// faster. Defaults to 1. + float getTimeScale(); + + void setTimeScale(float inValue); + + /// Values less than 1 mix this animation with the last skeleton pose. Defaults to 1, which overwrites the last skeleton pose with + /// this animation. + /// + /// Typically track 0 is used to completely pose the skeleton, then alpha can be used on higher tracks. It doesn't make sense + /// to use alpha on track 0 if the skeleton pose is from the last frame render. + float getAlpha(); + + void setAlpha(float inValue); + + /// + /// When the mix percentage (mix time / mix duration) is less than the event threshold, event timelines for the animation + /// being mixed out will be applied. Defaults to 0, so event timelines are not applied for an animation being mixed out. + float getEventThreshold(); + + void setEventThreshold(float inValue); + + /// When the mix percentage (mix time / mix duration) is less than the attachment threshold, attachment timelines for the + /// animation being mixed out will be applied. Defaults to 0, so attachment timelines are not applied for an animation being + /// mixed out. + float getAttachmentThreshold(); + + void setAttachmentThreshold(float inValue); + + /// When the mix percentage (mix time / mix duration) is less than the draw order threshold, draw order timelines for the + /// animation being mixed out will be applied. Defaults to 0, so draw order timelines are not applied for an animation being + /// mixed out. + float getDrawOrderThreshold(); + + void setDrawOrderThreshold(float inValue); + + /// The animation queued to start after this animation, or NULL. + TrackEntry *getNext(); + + /// Returns true if at least one loop has been completed. + bool isComplete(); + + /// Seconds from 0 to the mix duration when mixing from the previous animation to this animation. May be slightly more than + /// TrackEntry.MixDuration when the mix is complete. + float getMixTime(); + + void setMixTime(float inValue); + + /// Seconds for mixing from the previous animation to this animation. Defaults to the value provided by + /// AnimationStateData based on the animation before this animation (if any). + /// + /// The mix duration can be set manually rather than use the value from AnimationStateData.GetMix. + /// In that case, the mixDuration must be set before AnimationState.update(float) is next called. + /// + /// When using AnimationState::addAnimation(int, Animation, bool, float) with a delay + /// less than or equal to 0, note the Delay is set using the mix duration from the AnimationStateData + float getMixDuration(); + + void setMixDuration(float inValue); + + MixBlend getMixBlend(); + + void setMixBlend(MixBlend blend); + + /// The track entry for the previous animation when mixing from the previous animation to this animation, or NULL if no + /// mixing is currently occuring. When mixing from multiple animations, MixingFrom makes up a double linked list with MixingTo. + TrackEntry *getMixingFrom(); + + /// The track entry for the next animation when mixing from this animation, or NULL if no mixing is currently occuring. + /// When mixing from multiple animations, MixingTo makes up a double linked list with MixingFrom. + TrackEntry *getMixingTo(); + + /// Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the + /// long way around when using alpha and starting animations on other tracks. + /// + /// Mixing involves finding a rotation between two others, which has two possible solutions: the short way or the long way around. + /// The two rotations likely change over time, so which direction is the short or long way also changes. + /// If the short way was always chosen, bones would flip to the other side when that direction became the long way. + /// TrackEntry chooses the short way the first time it is applied and remembers that direction. + void resetRotationDirections(); + + float getTrackComplete(); + + void setListener(AnimationStateListener listener); + + void setListener(AnimationStateListenerObject *listener); + + private: + Animation *_animation; + TrackEntry *_previous; + TrackEntry *_next; + TrackEntry *_mixingFrom; + TrackEntry *_mixingTo; + int _trackIndex; + + bool _loop, _holdPrevious, _reverse, _shortestRotation; + float _eventThreshold, _attachmentThreshold, _drawOrderThreshold; + float _animationStart, _animationEnd, _animationLast, _nextAnimationLast; + float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale; + float _alpha, _mixTime, _mixDuration, _interruptAlpha, _totalAlpha; + MixBlend _mixBlend; + Vector _timelineMode; + Vector _timelineHoldMix; + Vector _timelinesRotation; + AnimationStateListener _listener; + AnimationStateListenerObject *_listenerObject; + + void reset(); + }; + + class SP_API EventQueueEntry : public SpineObject { + friend class EventQueue; + + public: + EventType _type; + TrackEntry *_entry; + Event *_event; + + EventQueueEntry(EventType eventType, TrackEntry *trackEntry, Event *event = NULL); + }; + + class SP_API EventQueue : public SpineObject { + friend class AnimationState; + + private: + Vector _eventQueueEntries; + AnimationState &_state; + bool _drainDisabled; + + static EventQueue *newEventQueue(AnimationState &state); + + static EventQueueEntry newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event = NULL); + + EventQueue(AnimationState &state); + + ~EventQueue(); + + void start(TrackEntry *entry); + + void interrupt(TrackEntry *entry); + + void end(TrackEntry *entry); + + void dispose(TrackEntry *entry); + + void complete(TrackEntry *entry); + + void event(TrackEntry *entry, Event *event); + + /// Raises all events in the queue and drains the queue. + void drain(); + }; + + class SP_API AnimationState : public SpineObject, public HasRendererObject { + friend class TrackEntry; + + friend class EventQueue; + + public: + explicit AnimationState(AnimationStateData *data); + + ~AnimationState(); + + /// Increments the track entry times, setting queued animations as current if needed + /// @param delta delta time + void update(float delta); + + /// Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the + /// animation state can be applied to multiple skeletons to pose them identically. + bool apply(Skeleton &skeleton); + + /// Removes all animations from all tracks, leaving skeletons in their previous pose. + /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, + /// rather than leaving them in their previous pose. + void clearTracks(); + + /// Removes all animations from the tracks, leaving skeletons in their previous pose. + /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, + /// rather than leaving them in their previous pose. + void clearTrack(size_t trackIndex); + + /// Sets an animation by name. setAnimation(int, Animation, bool) + TrackEntry *setAnimation(size_t trackIndex, const String &animationName, bool loop); + + /// Sets the current animation for a track, discarding any queued animations. + /// @param loop If true, the animation will repeat. + /// If false, it will not, instead its last frame is applied if played beyond its duration. + /// In either case TrackEntry.TrackEnd determines when the track is cleared. + /// @return + /// A track entry to allow further customization of animation playback. References to the track entry must not be kept + /// after AnimationState.Dispose. + TrackEntry *setAnimation(size_t trackIndex, Animation *animation, bool loop); + + /// Queues an animation by name. + /// addAnimation(int, Animation, bool, float) + TrackEntry *addAnimation(size_t trackIndex, const String &animationName, bool loop, float delay); + + /// Adds an animation to be played delay seconds after the current or last queued animation + /// for a track. If the track is empty, it is equivalent to calling setAnimation. + /// @param delay + /// Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation + /// duration of the previous track minus any mix duration plus the negative delay. + /// + /// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + /// after AnimationState.Dispose + TrackEntry *addAnimation(size_t trackIndex, Animation *animation, bool loop, float delay); + + /// Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration. + TrackEntry *setEmptyAnimation(size_t trackIndex, float mixDuration); + + /// Adds an empty animation to be played after the current or last queued animation for a track, and mixes to it over the + /// specified mix duration. + /// @return + /// A track entry to allow further customization of animation playback. References to the track entry must not be kept after AnimationState.Dispose. + /// + /// @param trackIndex Track number. + /// @param mixDuration Mix duration. + /// @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation + /// duration of the previous track minus any mix duration plus the negative delay. + TrackEntry *addEmptyAnimation(size_t trackIndex, float mixDuration, float delay); + + /// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration. + void setEmptyAnimations(float mixDuration); + + /// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing. + TrackEntry *getCurrent(size_t trackIndex); + + AnimationStateData *getData(); + + /// A list of tracks that have animations, which may contain NULLs. + Vector &getTracks(); + + float getTimeScale(); + + void setTimeScale(float inValue); + + void setListener(AnimationStateListener listener); + + void setListener(AnimationStateListenerObject *listener); + + void disableQueue(); + + void enableQueue(); + + void setManualTrackEntryDisposal(bool inValue); + + bool getManualTrackEntryDisposal(); + + void disposeTrackEntry(TrackEntry *entry); + + private: + static const int Subsequent = 0; + static const int First = 1; + static const int HoldSubsequent = 2; + static const int HoldFirst = 3; + static const int HoldMix = 4; + + static const int Setup = 1; + static const int Current = 2; + + AnimationStateData *_data; + + Pool _trackEntryPool; + Vector _tracks; + Vector _events; + EventQueue *_queue; + + HashMap _propertyIDs; + bool _animationsChanged; + + AnimationStateListener _listener; + AnimationStateListenerObject *_listenerObject; + + int _unkeyedState; + + float _timeScale; + + bool _manualTrackEntryDisposal; + + static Animation *getEmptyAnimation(); + + static void + applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, MixBlend pose, + Vector &timelinesRotation, size_t i, bool firstFrame); + + void applyAttachmentTimeline(AttachmentTimeline *attachmentTimeline, Skeleton &skeleton, float animationTime, + MixBlend pose, bool firstFrame); + + /// Returns true when all mixing from entries are complete. + bool updateMixingFrom(TrackEntry *to, float delta); + + float applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBlend currentPose); + + void queueEvents(TrackEntry *entry, float animationTime); + + /// Sets the active TrackEntry for a given track number. + void setCurrent(size_t index, TrackEntry *current, bool interrupt); + + /// Removes the next entry and all entries after it for the specified entry. */ + void clearNext(TrackEntry *entry); + + TrackEntry *expandToIndex(size_t index); + + /// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values. + /// @param last May be NULL. + TrackEntry *newTrackEntry(size_t trackIndex, Animation *animation, bool loop, TrackEntry *last); + + void animationsChanged(); + + void computeHold(TrackEntry *entry); + + void setAttachment(Skeleton &skeleton, spine::Slot &slot, const String &attachmentName, bool attachments); + }; +} + +#endif /* Spine_AnimationState_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AnimationStateData.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AnimationStateData.h new file mode 100644 index 0000000..bdde48e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AnimationStateData.h @@ -0,0 +1,90 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AnimationStateData_h +#define Spine_AnimationStateData_h + +#include +#include +#include + +#include + +namespace spine { + class SkeletonData; + + class Animation; + + /// Stores mix (crossfade) durations to be applied when AnimationState animations are changed. + class SP_API AnimationStateData : public SpineObject { + friend class AnimationState; + + public: + explicit AnimationStateData(SkeletonData *skeletonData); + + /// The SkeletonData to look up animations when they are specified by name. + SkeletonData *getSkeletonData(); + + /// The mix duration to use when no mix duration has been specifically defined between two animations. + float getDefaultMix(); + + void setDefaultMix(float inValue); + + /// Sets a mix duration by animation names. + void setMix(const String &fromName, const String &toName, float duration); + + /// Sets a mix duration when changing from the specified animation to the other. + /// See TrackEntry.MixDuration. + void setMix(Animation *from, Animation *to, float duration); + + /// The mix duration to use when changing from the specified animation to the other, + /// or the DefaultMix if no mix duration has been set. + float getMix(Animation *from, Animation *to); + + /// Removes all mixes and sets the default mix to 0. + void clear(); + + private: + class AnimationPair : public SpineObject { + public: + Animation *_a1; + Animation *_a2; + + explicit AnimationPair(Animation *a1 = NULL, Animation *a2 = NULL); + + bool operator==(const AnimationPair &other) const; + }; + + SkeletonData *_skeletonData; + float _defaultMix; + HashMap _animationToMixTime; + }; +} + +#endif /* Spine_AnimationStateData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Atlas.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Atlas.h new file mode 100644 index 0000000..822467e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Atlas.h @@ -0,0 +1,139 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Atlas_h +#define Spine_Atlas_h + +#include +#include +#include +#include +#include +#include "TextureRegion.h" + +namespace spine { + enum Format { + Format_Alpha, + Format_Intensity, + Format_LuminanceAlpha, + Format_RGB565, + Format_RGBA4444, + Format_RGB888, + Format_RGBA8888 + }; + + // Our TextureFilter collides with UE4's TextureFilter in unity builds. We rename + // TextureFilter to SpineTextureFilter in UE4. +#ifdef SPINE_UE4 + #define TEXTURE_FILTER_ENUM SpineTextureFilter +#else + #define TEXTURE_FILTER_ENUM TextureFilter +#endif + + enum TEXTURE_FILTER_ENUM { + TextureFilter_Unknown, + TextureFilter_Nearest, + TextureFilter_Linear, + TextureFilter_MipMap, + TextureFilter_MipMapNearestNearest, + TextureFilter_MipMapLinearNearest, + TextureFilter_MipMapNearestLinear, + TextureFilter_MipMapLinearLinear + }; + + enum TextureWrap { + TextureWrap_MirroredRepeat, + TextureWrap_ClampToEdge, + TextureWrap_Repeat + }; + + class SP_API AtlasPage : public SpineObject { + public: + String name; + String texturePath; + Format format; + TEXTURE_FILTER_ENUM minFilter; + TEXTURE_FILTER_ENUM magFilter; + TextureWrap uWrap; + TextureWrap vWrap; + int width, height; + bool pma; + int index; + void *texture; + + explicit AtlasPage(const String &inName) : name(inName), format(Format_RGBA8888), + minFilter(TextureFilter_Nearest), + magFilter(TextureFilter_Nearest), uWrap(TextureWrap_ClampToEdge), + vWrap(TextureWrap_ClampToEdge), width(0), height(0), pma(false), index(0), texture(NULL) { + } + }; + + class SP_API AtlasRegion : public TextureRegion { + public: + AtlasPage *page; + String name; + int index; + int x, y; + Vector splits; + Vector pads; + Vector names; + Vector values; + }; + + class TextureLoader; + + class SP_API Atlas : public SpineObject { + public: + Atlas(const String &path, TextureLoader *textureLoader, bool createTexture = true); + + Atlas(const char *data, int length, const char *dir, TextureLoader *textureLoader, bool createTexture = true); + + ~Atlas(); + + void flipV(); + + /// Returns the first region found with the specified name. This method uses String comparison to find the region, so the result + /// should be cached rather than calling this method multiple times. + /// @return The region, or NULL. + AtlasRegion *findRegion(const String &name); + + Vector &getPages(); + + Vector &getRegions(); + + private: + Vector _pages; + Vector _regions; + TextureLoader *_textureLoader; + + void load(const char *begin, int length, const char *dir, bool createTexture); + }; +} + +#endif /* Spine_Atlas_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h new file mode 100644 index 0000000..d45ebaf --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AtlasAttachmentLoader_h +#define Spine_AtlasAttachmentLoader_h + +#include +#include +#include + + +namespace spine { + class Atlas; + + class AtlasRegion; + + /// An AttachmentLoader that configures attachments using texture regions from an Atlas. + /// See http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data about Loading Skeleton Data in the Spine Runtimes Guide. + class SP_API AtlasAttachmentLoader : public AttachmentLoader { + public: + RTTI_DECL + + explicit AtlasAttachmentLoader(Atlas *atlas); + + virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence); + + virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence); + + virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &skin, const String &name); + + virtual PathAttachment *newPathAttachment(Skin &skin, const String &name); + + virtual PointAttachment *newPointAttachment(Skin &skin, const String &name); + + virtual ClippingAttachment *newClippingAttachment(Skin &skin, const String &name); + + virtual void configureAttachment(Attachment *attachment); + + AtlasRegion *findRegion(const String &name); + + private: + Atlas *_atlas; + }; +} + +#endif /* Spine_AtlasAttachmentLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Attachment.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Attachment.h new file mode 100644 index 0000000..4187167 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Attachment.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Attachment_h +#define Spine_Attachment_h + +#include +#include +#include + +namespace spine { + class SP_API Attachment : public SpineObject { + RTTI_DECL + + public: + explicit Attachment(const String &name); + + virtual ~Attachment(); + + const String &getName() const; + + virtual Attachment *copy() = 0; + + int getRefCount(); + + void reference(); + + void dereference(); + + private: + const String _name; + int _refCount; + }; +} + +#endif /* Spine_Attachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h new file mode 100644 index 0000000..66c0e36 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h @@ -0,0 +1,84 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentLoader_h +#define Spine_AttachmentLoader_h + +#include +#include +#include + +namespace spine { + class Skin; + + class Attachment; + + class RegionAttachment; + + class MeshAttachment; + + class BoundingBoxAttachment; + + class PathAttachment; + + class PointAttachment; + + class ClippingAttachment; + + class Sequence; + + class SP_API AttachmentLoader : public SpineObject { + public: + RTTI_DECL + + AttachmentLoader(); + + virtual ~AttachmentLoader(); + + /// @return May be NULL to not load any attachment. + virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) = 0; + + /// @return May be NULL to not load any attachment. + virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) = 0; + + /// @return May be NULL to not load any attachment. + virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &skin, const String &name) = 0; + + /// @return May be NULL to not load any attachment + virtual PathAttachment *newPathAttachment(Skin &skin, const String &name) = 0; + + virtual PointAttachment *newPointAttachment(Skin &skin, const String &name) = 0; + + virtual ClippingAttachment *newClippingAttachment(Skin &skin, const String &name) = 0; + + virtual void configureAttachment(Attachment *attachment) = 0; + }; +} + +#endif /* Spine_AttachmentLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h new file mode 100644 index 0000000..6f3b984 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentTimeline_h +#define Spine_AttachmentTimeline_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + + class Skeleton; + + class Slot; + + class Event; + + class SP_API AttachmentTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit AttachmentTimeline(size_t frameCount, int slotIndex); + + virtual ~AttachmentTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, const String &attachmentName); + + Vector &getAttachmentNames(); + + int getSlotIndex() { return _slotIndex; } + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + Vector _attachmentNames; + + void setAttachment(Skeleton &skeleton, Slot &slot, String *attachmentName); + }; +} + +#endif /* Spine_AttachmentTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AttachmentType.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AttachmentType.h new file mode 100644 index 0000000..a92b607 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/AttachmentType.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentType_h +#define Spine_AttachmentType_h + +namespace spine { + enum AttachmentType { + AttachmentType_Region, + AttachmentType_Boundingbox, + AttachmentType_Mesh, + AttachmentType_Linkedmesh, + AttachmentType_Path, + AttachmentType_Point, + AttachmentType_Clipping + }; +} + +#endif /* Spine_AttachmentType_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/BlendMode.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/BlendMode.h new file mode 100644 index 0000000..989a1be --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/BlendMode.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BlendMode_h +#define Spine_BlendMode_h + +namespace spine { + enum BlendMode { + BlendMode_Normal = 0, + BlendMode_Additive, + BlendMode_Multiply, + BlendMode_Screen + }; +} + +#endif /* Spine_BlendMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Bone.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Bone.h new file mode 100644 index 0000000..e1384aa --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Bone.h @@ -0,0 +1,272 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Bone_h +#define Spine_Bone_h + +#include +#include +#include + +namespace spine { + class BoneData; + + class Skeleton; + +/// Stores a bone's current pose. +/// +/// A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a +/// local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a +/// constraint or application code modifies the world transform after it was computed from the local transform. + class SP_API Bone : public Updatable { + friend class AnimationState; + + friend class RotateTimeline; + + friend class IkConstraint; + + friend class TransformConstraint; + + friend class VertexAttachment; + + friend class PathConstraint; + + friend class Skeleton; + + friend class RegionAttachment; + + friend class PointAttachment; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class ScaleTimeline; + + friend class ScaleXTimeline; + + friend class ScaleYTimeline; + + friend class ShearTimeline; + + friend class ShearXTimeline; + + friend class ShearYTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + RTTI_DECL + + public: + static void setYDown(bool inValue); + + static bool isYDown(); + + /// @param parent May be NULL. + Bone(BoneData &data, Skeleton &skeleton, Bone *parent = NULL); + + /// Same as updateWorldTransform. This method exists for Bone to implement Spine::Updatable. + virtual void update(); + + /// Computes the world transform using the parent bone and this bone's local transform. + void updateWorldTransform(); + + /// Computes the world transform using the parent bone and the specified local transform. + void + updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY); + + /// Computes the individual applied transform values from the world transform. This can be useful to perform processing using + /// the applied transform after the world transform has been modified directly (eg, by a constraint).. + /// + /// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. + void updateAppliedTransform(); + + void setToSetupPose(); + + void worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY); + + void localToWorld(float localX, float localY, float &outWorldX, float &outWorldY); + + float worldToLocalRotation(float worldRotation); + + float localToWorldRotation(float localRotation); + + /// Rotates the world transform the specified amount and sets isAppliedValid to false. + /// @param degrees Degrees. + void rotateWorld(float degrees); + + float getWorldToLocalRotationX(); + + float getWorldToLocalRotationY(); + + BoneData &getData(); + + Skeleton &getSkeleton(); + + Bone *getParent(); + + Vector &getChildren(); + + /// The local X translation. + float getX(); + + void setX(float inValue); + + /// The local Y translation. + float getY(); + + void setY(float inValue); + + /// The local rotation. + float getRotation(); + + void setRotation(float inValue); + + /// The local scaleX. + float getScaleX(); + + void setScaleX(float inValue); + + /// The local scaleY. + float getScaleY(); + + void setScaleY(float inValue); + + /// The local shearX. + float getShearX(); + + void setShearX(float inValue); + + /// The local shearY. + float getShearY(); + + void setShearY(float inValue); + + /// The rotation, as calculated by any constraints. + float getAppliedRotation(); + + void setAppliedRotation(float inValue); + + /// The applied local x translation. + float getAX(); + + void setAX(float inValue); + + /// The applied local y translation. + float getAY(); + + void setAY(float inValue); + + /// The applied local scaleX. + float getAScaleX(); + + void setAScaleX(float inValue); + + /// The applied local scaleY. + float getAScaleY(); + + void setAScaleY(float inValue); + + /// The applied local shearX. + float getAShearX(); + + void setAShearX(float inValue); + + /// The applied local shearY. + float getAShearY(); + + void setAShearY(float inValue); + + float getA(); + + void setA(float inValue); + + float getB(); + + void setB(float inValue); + + float getC(); + + void setC(float inValue); + + float getD(); + + void setD(float inValue); + + float getWorldX(); + + void setWorldX(float inValue); + + float getWorldY(); + + void setWorldY(float inValue); + + float getWorldRotationX(); + + float getWorldRotationY(); + + /// Returns the magnitide (always positive) of the world scale X. + float getWorldScaleX(); + + /// Returns the magnitide (always positive) of the world scale Y. + float getWorldScaleY(); + + bool isActive(); + + void setActive(bool inValue); + + private: + static bool yDown; + + BoneData &_data; + Skeleton &_skeleton; + Bone *_parent; + Vector _children; + float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; + float _ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY; + float _a, _b, _worldX; + float _c, _d, _worldY; + bool _sorted; + bool _active; + }; +} + +#endif /* Spine_Bone_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/BoneData.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/BoneData.h new file mode 100644 index 0000000..51c04a6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -0,0 +1,140 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BoneData_h +#define Spine_BoneData_h + +#include +#include +#include +#include + +namespace spine { + class SP_API BoneData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + + friend class RotateTimeline; + + friend class ScaleTimeline; + + friend class ScaleXTimeline; + + friend class ScaleYTimeline; + + friend class ShearTimeline; + + friend class ShearXTimeline; + + friend class ShearYTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + public: + BoneData(int index, const String &name, BoneData *parent = NULL); + + /// The index of the bone in Skeleton.Bones + int getIndex(); + + /// The name of the bone, which is unique within the skeleton. + const String &getName(); + + /// May be NULL. + BoneData *getParent(); + + float getLength(); + + void setLength(float inValue); + + /// Local X translation. + float getX(); + + void setX(float inValue); + + /// Local Y translation. + float getY(); + + void setY(float inValue); + + /// Local rotation. + float getRotation(); + + void setRotation(float inValue); + + /// Local scaleX. + float getScaleX(); + + void setScaleX(float inValue); + + /// Local scaleY. + float getScaleY(); + + void setScaleY(float inValue); + + /// Local shearX. + float getShearX(); + + void setShearX(float inValue); + + /// Local shearY. + float getShearY(); + + void setShearY(float inValue); + + /// The transform mode for how parent world transforms affect this bone. + TransformMode getTransformMode(); + + void setTransformMode(TransformMode inValue); + + bool isSkinRequired(); + + void setSkinRequired(bool inValue); + + Color &getColor(); + + private: + const int _index; + const String _name; + BoneData *_parent; + float _length; + float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; + TransformMode _transformMode; + bool _skinRequired; + Color _color; + }; +} + +#endif /* Spine_BoneData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h new file mode 100644 index 0000000..0ea3e2a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BoundingBoxAttachment_h +#define Spine_BoundingBoxAttachment_h + +#include +#include +#include + +namespace spine { + /// Attachment that has a polygon for bounds checking. + class SP_API BoundingBoxAttachment : public VertexAttachment { + RTTI_DECL + + public: + explicit BoundingBoxAttachment(const String &name); + + Color &getColor(); + + virtual Attachment *copy(); + + private: + Color _color; + }; +} + +#endif /* Spine_BoundingBoxAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h new file mode 100644 index 0000000..ce7675e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ClippingAttachment_h +#define Spine_ClippingAttachment_h + +#include +#include + +namespace spine { + class SlotData; + + class SP_API ClippingAttachment : public VertexAttachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class SkeletonClipping; + + RTTI_DECL + + public: + explicit ClippingAttachment(const String &name); + + SlotData *getEndSlot(); + + void setEndSlot(SlotData *inValue); + + Color &getColor(); + + virtual Attachment *copy(); + + private: + SlotData *_endSlot; + Color _color; + }; +} + +#endif /* Spine_ClippingAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Color.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Color.h new file mode 100644 index 0000000..676f2cd --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Color.h @@ -0,0 +1,110 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_COLOR_H +#define SPINE_COLOR_H + +#include + +namespace spine { + class SP_API Color : public SpineObject { + public: + Color() : r(0), g(0), b(0), a(0) { + } + + Color(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) { + clamp(); + } + + inline Color &set(float _r, float _g, float _b, float _a) { + this->r = _r; + this->g = _g; + this->b = _b; + this->a = _a; + clamp(); + return *this; + } + + inline Color &set(float _r, float _g, float _b) { + this->r = _r; + this->g = _g; + this->b = _b; + clamp(); + return *this; + } + + inline Color &set(const Color &other) { + r = other.r; + g = other.g; + b = other.b; + a = other.a; + clamp(); + return *this; + } + + inline Color &add(float _r, float _g, float _b, float _a) { + this->r += _r; + this->g += _g; + this->b += _b; + this->a += _a; + clamp(); + return *this; + } + + inline Color &add(float _r, float _g, float _b) { + this->r += _r; + this->g += _g; + this->b += _b; + clamp(); + return *this; + } + + inline Color &add(const Color &other) { + r += other.r; + g += other.g; + b += other.b; + a += other.a; + clamp(); + return *this; + } + + inline Color &clamp() { + r = MathUtil::clamp(this->r, 0, 1); + g = MathUtil::clamp(this->g, 0, 1); + b = MathUtil::clamp(this->b, 0, 1); + a = MathUtil::clamp(this->a, 0, 1); + return *this; + } + + float r, g, b, a; + }; +} + + +#endif //SPINE_COLOR_H diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ColorTimeline.h new file mode 100644 index 0000000..e2528f1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -0,0 +1,197 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ColorTimeline_h +#define Spine_ColorTimeline_h + +#include + +namespace spine { + class SP_API RGBATimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGBATimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, float r, float g, float b, float a); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + static const int ENTRIES = 5; + static const int R = 1; + static const int G = 2; + static const int B = 3; + static const int A = 4; + }; + + class SP_API RGBTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGBTimeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGBTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, float r, float g, float b); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + static const int ENTRIES = 4; + static const int R = 1; + static const int G = 2; + static const int B = 3; + }; + + class SP_API AlphaTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit AlphaTimeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~AlphaTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + }; + + class SP_API RGBA2Timeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGBA2Timeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGBA2Timeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + static const int ENTRIES = 8; + static const int R = 1; + static const int G = 2; + static const int B = 3; + static const int A = 4; + static const int R2 = 5; + static const int G2 = 6; + static const int B2 = 7; + }; + + class SP_API RGB2Timeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGB2Timeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGB2Timeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + static const int ENTRIES = 7; + static const int R = 1; + static const int G = 2; + static const int B = 3; + static const int R2 = 4; + static const int G2 = 5; + static const int B2 = 6; + }; +} + +#endif /* Spine_ColorTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ConstraintData.h new file mode 100644 index 0000000..c35a7e6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ConstraintData.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Constraint_h +#define Spine_Constraint_h + +#include +#include + +namespace spine { + /// The interface for all constraints. + class SP_API ConstraintData : public SpineObject { + + RTTI_DECL + + public: + ConstraintData(const String &name); + + virtual ~ConstraintData(); + + /// The IK constraint's name, which is unique within the skeleton. + const String &getName(); + + /// The ordinal for the order a skeleton's constraints will be applied. + size_t getOrder(); + + void setOrder(size_t inValue); + + /// Whether the constraint is only active for a specific skin. + bool isSkinRequired(); + + void setSkinRequired(bool inValue); + + private: + const String _name; + size_t _order; + bool _skinRequired; + }; +} + +#endif /* Spine_Constraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ContainerUtil.h new file mode 100644 index 0000000..3e22128 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ContainerUtil_h +#define Spine_ContainerUtil_h + +#include +#include +#include +#include +#include + +#include + +namespace spine { + class SP_API ContainerUtil : public SpineObject { + public: + /// Finds an item by comparing each item's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + template + static T *findWithName(Vector &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0; i < items.size(); ++i) { + T *item = items[i]; + if (item->getName() == name) { + return item; + } + } + + return NULL; + } + + /// @return -1 if the item was not found. + template + static int findIndexWithName(Vector &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0, len = items.size(); i < len; ++i) { + T *item = items[i]; + if (item->getName() == name) { + return static_cast(i); + } + } + + return -1; + } + + /// Finds an item by comparing each item's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + template + static T *findWithDataName(Vector &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0; i < items.size(); ++i) { + T *item = items[i]; + if (item->getData().getName() == name) { + return item; + } + } + + return NULL; + } + + /// @return -1 if the item was not found. + template + static int findIndexWithDataName(Vector &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0, len = items.size(); i < len; ++i) { + T *item = items[i]; + if (item->getData().getName() == name) { + return static_cast(i); + } + } + + return -1; + } + + template + static void cleanUpVectorOfPointers(Vector &items) { + for (int i = (int) items.size() - 1; i >= 0; i--) { + T *item = items[i]; + + delete item; + + items.removeAt(i); + } + } + + private: + // ctor, copy ctor, and assignment should be private in a Singleton + ContainerUtil(); + + ContainerUtil(const ContainerUtil &); + + ContainerUtil &operator=(const ContainerUtil &); + }; +} + +#endif /* Spine_ContainerUtil_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/CurveTimeline.h new file mode 100644 index 0000000..43e741b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -0,0 +1,103 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_CurveTimeline_h +#define Spine_CurveTimeline_h + +#include +#include + +namespace spine { + /// Base class for frames that use an interpolation bezier curve. + class SP_API CurveTimeline : public Timeline { + RTTI_DECL + + public: + explicit CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount); + + virtual ~CurveTimeline(); + + void setLinear(size_t frame); + + void setStepped(size_t frame); + + virtual void + setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, + float cy2, float time2, float value2); + + float getBezierValue(float time, size_t frame, size_t valueOffset, size_t i); + + Vector &getCurves(); + + protected: + static const int LINEAR = 0; + static const int STEPPED = 1; + static const int BEZIER = 2; + static const int BEZIER_SIZE = 18; + + Vector _curves; // type, x, y, ... + }; + + class SP_API CurveTimeline1 : public CurveTimeline { + RTTI_DECL + + public: + explicit CurveTimeline1(size_t frameCount, size_t bezierCount); + + virtual ~CurveTimeline1(); + + void setFrame(size_t frame, float time, float value); + + float getCurveValue(float time); + + protected: + static const int ENTRIES = 2; + static const int VALUE = 1; + }; + + class SP_API CurveTimeline2 : public CurveTimeline { + RTTI_DECL + + public: + explicit CurveTimeline2(size_t frameCount, size_t bezierCount); + + virtual ~CurveTimeline2(); + + void setFrame(size_t frame, float time, float value1, float value2); + + float getCurveValue(float time); + + protected: + static const int ENTRIES = 3; + static const int VALUE1 = 1; + static const int VALUE2 = 2; + }; +} + +#endif /* Spine_CurveTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Debug.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Debug.h new file mode 100644 index 0000000..9b8443d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Debug.h @@ -0,0 +1,131 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_LOG_H +#define SPINE_LOG_H + +#include +#include + +#include + +namespace spine { + + class SP_API DebugExtension : public SpineExtension { + struct Allocation { + void *address; + size_t size; + const char *fileName; + int line; + + Allocation() : address(NULL), size(0), fileName(NULL), line(0) { + } + + Allocation(void *a, size_t s, const char *f, int l) : address(a), size(s), fileName(f), line(l) { + } + }; + + public: + DebugExtension(SpineExtension *extension) : _extension(extension), _allocations(0), _reallocations(0), + _frees(0) { + } + + void reportLeaks() { + for (std::map::iterator it = _allocated.begin(); it != _allocated.end(); it++) { + printf("\"%s:%i (%zu bytes at %p)\n", it->second.fileName, it->second.line, it->second.size, + it->second.address); + } + printf("allocations: %zu, reallocations: %zu, frees: %zu\n", _allocations, _reallocations, _frees); + if (_allocated.empty()) printf("No leaks detected\n"); + } + + void clearAllocations() { + _allocated.clear(); + _usedMemory = 0; + } + + virtual void *_alloc(size_t size, const char *file, int line) { + void *result = _extension->_alloc(size, file, line); + _allocated[result] = Allocation(result, size, file, line); + _allocations++; + _usedMemory += size; + return result; + } + + virtual void *_calloc(size_t size, const char *file, int line) { + void *result = _extension->_calloc(size, file, line); + _allocated[result] = Allocation(result, size, file, line); + _allocations++; + _usedMemory += size; + return result; + } + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) { + if (_allocated.count(ptr)) _usedMemory -= _allocated[ptr].size; + _allocated.erase(ptr); + void *result = _extension->_realloc(ptr, size, file, line); + _reallocations++; + _allocated[result] = Allocation(result, size, file, line); + _usedMemory += size; + return result; + } + + virtual void _free(void *mem, const char *file, int line) { + if (_allocated.count(mem)) { + _extension->_free(mem, file, line); + _frees++; + _usedMemory -= _allocated[mem].size; + _allocated.erase(mem); + return; + } + + printf("%s:%i (address %p): Double free or not allocated through SpineExtension\n", file, line, mem); + _extension->_free(mem, file, line); + } + + virtual char *_readFile(const String &path, int *length) { + return _extension->_readFile(path, length); + } + + size_t getUsedMemory() { + return _usedMemory; + } + + private: + SpineExtension *_extension; + std::map _allocated; + size_t _allocations; + size_t _reallocations; + size_t _frees; + size_t _usedMemory; + }; +} + + +#endif //SPINE_LOG_H diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/DeformTimeline.h new file mode 100644 index 0000000..6b8555d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -0,0 +1,80 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DeformTimeline_h +#define Spine_DeformTimeline_h + +#include + +namespace spine { + class VertexAttachment; + + class SP_API DeformTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit DeformTimeline(size_t frameCount, size_t bezierCount, int slotIndex, VertexAttachment *attachment); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, Vector &vertices); + + Vector > &getVertices(); + + VertexAttachment *getAttachment(); + + void setAttachment(VertexAttachment *inValue); + + virtual void + setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, + float cy2, float time2, float value2); + + float getCurvePercent(float time, int frame); + + int getSlotIndex() { return _slotIndex; } + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + Vector > _vertices; + + VertexAttachment *_attachment; + }; +} + +#endif /* Spine_DeformTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h new file mode 100644 index 0000000..873fe75 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DrawOrderTimeline_h +#define Spine_DrawOrderTimeline_h + +#include + +namespace spine { + class SP_API DrawOrderTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit DrawOrderTimeline(size_t frameCount); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + /// @param drawOrder May be NULL to use bind pose draw order + void setFrame(size_t frame, float time, Vector &drawOrder); + + Vector > &getDrawOrders(); + + private: + Vector > _drawOrders; + }; +} + +#endif /* Spine_DrawOrderTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Event.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Event.h new file mode 100644 index 0000000..ac0b122 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Event.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Event_h +#define Spine_Event_h + +#include +#include + +namespace spine { + class EventData; + +/// Stores the current pose values for an Event. + class SP_API Event : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + + public: + Event(float time, const EventData &data); + + const EventData &getData(); + + /// The animation time this event was keyed. + float getTime(); + + int getIntValue(); + + void setIntValue(int inValue); + + float getFloatValue(); + + void setFloatValue(float inValue); + + const String &getStringValue(); + + void setStringValue(const String &inValue); + + float getVolume(); + + void setVolume(float inValue); + + float getBalance(); + + void setBalance(float inValue); + + private: + const EventData &_data; + const float _time; + int _intValue; + float _floatValue; + String _stringValue; + float _volume; + float _balance; + }; +} + +#endif /* Spine_Event_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/EventData.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/EventData.h new file mode 100644 index 0000000..5099c56 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/EventData.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_EventData_h +#define Spine_EventData_h + +#include +#include + +namespace spine { +/// Stores the setup pose values for an Event. + class SP_API EventData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class Event; + + public: + explicit EventData(const String &name); + + /// The name of the event, which is unique within the skeleton. + const String &getName() const; + + int getIntValue() const; + + void setIntValue(int inValue); + + float getFloatValue() const; + + void setFloatValue(float inValue); + + const String &getStringValue() const; + + void setStringValue(const String &inValue); + + const String &getAudioPath() const; + + void setAudioPath(const String &inValue); + + float getVolume() const; + + void setVolume(float inValue); + + float getBalance() const; + + void setBalance(float inValue); + + private: + const String _name; + int _intValue; + float _floatValue; + String _stringValue; + String _audioPath; + float _volume; + float _balance; + }; +} + +#endif /* Spine_EventData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/EventTimeline.h new file mode 100644 index 0000000..e9a89be --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_EventTimeline_h +#define Spine_EventTimeline_h + +#include + +namespace spine { + class SP_API EventTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit EventTimeline(size_t frameCount); + + ~EventTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(size_t frame, Event *event); + + Vector &getEvents(); + + private: + Vector _events; + }; +} + +#endif /* Spine_EventTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Extension.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Extension.h new file mode 100644 index 0000000..9757ea7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Extension.h @@ -0,0 +1,125 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Extension_h +#define Spine_Extension_h + + +#include +#include + +#define SP_UNUSED(x) (void)(x) + +namespace spine { + class String; + + class SP_API SpineExtension { + public: + template + static T *alloc(size_t num, const char *file, int line) { + return (T *) getInstance()->_alloc(sizeof(T) * num, file, line); + } + + template + static T *calloc(size_t num, const char *file, int line) { + return (T *) getInstance()->_calloc(sizeof(T) * num, file, line); + } + + template + static T *realloc(T *ptr, size_t num, const char *file, int line) { + return (T *) getInstance()->_realloc(ptr, sizeof(T) * num, file, line); + } + + template + static void free(T *ptr, const char *file, int line) { + getInstance()->_free((void *) ptr, file, line); + } + + template + static void beforeFree(T *ptr) { + getInstance()->_beforeFree((void *) ptr); + } + + static char *readFile(const String &path, int *length) { + return getInstance()->_readFile(path, length); + } + + static void setInstance(SpineExtension *inSpineExtension); + + static SpineExtension *getInstance(); + + virtual ~SpineExtension(); + + /// Implement this function to use your own memory allocator + virtual void *_alloc(size_t size, const char *file, int line) = 0; + + virtual void *_calloc(size_t size, const char *file, int line) = 0; + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) = 0; + + /// If you provide a spineAllocFunc, you should also provide a spineFreeFunc + virtual void _free(void *mem, const char *file, int line) = 0; + + virtual char *_readFile(const String &path, int *length) = 0; + + virtual void _beforeFree(void *ptr) { SP_UNUSED(ptr); } + + protected: + SpineExtension(); + + private: + static SpineExtension *_instance; + }; + + class SP_API DefaultSpineExtension : public SpineExtension { + public: + DefaultSpineExtension(); + + virtual ~DefaultSpineExtension(); + + protected: + virtual void *_alloc(size_t size, const char *file, int line) override; + + virtual void *_calloc(size_t size, const char *file, int line) override; + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) override; + + virtual void _free(void *mem, const char *file, int line) override; + + virtual char *_readFile(const String &path, int *length) override; + }; + +// This function is to be implemented by engine specific runtimes to provide +// the default extension for that engine. It is called the first time +// SpineExtension::getInstance() is called, when no instance has been set +// yet. + extern SpineExtension *getDefaultExtension(); +} + +#endif /* Spine_Extension_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/HasRendererObject.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/HasRendererObject.h new file mode 100644 index 0000000..5792939 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/HasRendererObject.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_HasRendererObject_h +#define Spine_HasRendererObject_h + +#include + +namespace spine { + + typedef void (*DisposeRendererObject)(void *rendererObject); + + class SP_API HasRendererObject { + public: + explicit HasRendererObject() : _rendererObject(0), _dispose(0) {}; + + virtual ~HasRendererObject() { + if (_dispose && _rendererObject) + _dispose(_rendererObject); + } + + void *getRendererObject() { return _rendererObject; } + + void setRendererObject(void *rendererObject, DisposeRendererObject dispose = 0) { + if (_dispose && _rendererObject && _rendererObject != rendererObject) + _dispose(_rendererObject); + + _rendererObject = rendererObject; + _dispose = dispose; + } + + private: + void *_rendererObject; + DisposeRendererObject _dispose; + }; + +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/HashMap.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/HashMap.h new file mode 100755 index 0000000..741425c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -0,0 +1,200 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_HashMap_h +#define Spine_HashMap_h + +#include +#include + +// Required for new with line number and file name in MSVC +#ifdef _MSC_VER +#pragma warning(disable:4291) + +#pragma warning(disable:4251) + +#endif + +namespace spine { + template + class SP_API HashMap : public SpineObject { + private: + class Entry; + + public: + class SP_API Pair { + public: + explicit Pair(K &k, V &v) : key(k), value(v) {} + + K &key; + V &value; + }; + + class SP_API Entries { + public: + friend class HashMap; + + explicit Entries(Entry *entry) : _entry(NULL), _hasChecked(false) { + _start.next = entry; + _entry = &_start; + } + + Pair next() { + assert(_entry); + assert(_hasChecked); + _entry = _entry->next; + Pair pair(_entry->_key, _entry->_value); + _hasChecked = false; + return pair; + } + + bool hasNext() { + _hasChecked = true; + return _entry->next; + } + + private: + bool _hasChecked; + Entry _start; + Entry *_entry; + }; + + HashMap() : + _head(NULL), + _size(0) { + } + + ~HashMap() { + clear(); + } + + void clear() { + for (Entry *entry = _head; entry != NULL;) { + Entry *next = entry->next; + delete entry; + entry = next; + } + _head = NULL; + _size = 0; + } + + size_t size() { + return _size; + } + + void put(const K &key, const V &value) { + Entry *entry = find(key); + if (entry) { + entry->_key = key; + entry->_value = value; + } else { + entry = new(__FILE__, __LINE__) Entry(); + entry->_key = key; + entry->_value = value; + + Entry *oldHead = _head; + + if (oldHead) { + _head = entry; + oldHead->prev = entry; + entry->next = oldHead; + } else { + _head = entry; + } + _size++; + } + } + + bool addAll(Vector &keys, const V &value) { + size_t oldSize = _size; + for (size_t i = 0; i < keys.size(); i++) { + put(keys[i], value); + } + return _size != oldSize; + } + + bool containsKey(const K &key) { + return find(key) != NULL; + } + + bool remove(const K &key) { + Entry *entry = find(key); + if (!entry) return false; + + Entry *prev = entry->prev; + Entry *next = entry->next; + + if (prev) prev->next = next; + else _head = next; + if (next) next->prev = entry->prev; + + delete entry; + _size--; + + return true; + } + + V operator[](const K &key) { + Entry *entry = find(key); + if (entry) return entry->_value; + else { + assert(false); + return 0; + } + } + + Entries getEntries() const { + return Entries(_head); + } + + private: + Entry *find(const K &key) { + for (Entry *entry = _head; entry != NULL; entry = entry->next) { + if (entry->_key == key) + return entry; + } + return NULL; + } + + class SP_API Entry : public SpineObject { + public: + K _key; + V _value; + Entry *next; + Entry *prev; + + Entry() : next(NULL), prev(NULL) {} + }; + + Entry *_head; + size_t _size; + }; +} + +#endif /* Spine_HashMap_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/IkConstraint.h new file mode 100644 index 0000000..02d7629 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -0,0 +1,116 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraint_h +#define Spine_IkConstraint_h + +#include + +#include + +namespace spine { + class IkConstraintData; + + class Skeleton; + + class Bone; + + class SP_API IkConstraint : public Updatable { + friend class Skeleton; + + friend class IkConstraintTimeline; + + RTTI_DECL + + public: + /// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified + /// in the world coordinate system. + static void + apply(Bone &bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha); + + /// Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as + /// possible. The target is specified in the world coordinate system. + /// @param child A direct descendant of the parent bone. + static void + apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, bool uniform, + float softness, + float alpha); + + IkConstraint(IkConstraintData &data, Skeleton &skeleton); + + virtual void update(); + + virtual int getOrder(); + + IkConstraintData &getData(); + + Vector &getBones(); + + Bone *getTarget(); + + void setTarget(Bone *inValue); + + int getBendDirection(); + + void setBendDirection(int inValue); + + bool getCompress(); + + void setCompress(bool inValue); + + bool getStretch(); + + void setStretch(bool inValue); + + float getMix(); + + void setMix(float inValue); + + float getSoftness(); + + void setSoftness(float inValue); + + bool isActive(); + + void setActive(bool inValue); + + private: + IkConstraintData &_data; + Vector _bones; + int _bendDirection; + bool _compress; + bool _stretch; + float _mix; + float _softness; + Bone *_target; + bool _active; + }; +} + +#endif /* Spine_IkConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/IkConstraintData.h new file mode 100644 index 0000000..96f5913 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraintData_h +#define Spine_IkConstraintData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SP_API IkConstraintData : public ConstraintData { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class IkConstraint; + + friend class Skeleton; + + friend class IkConstraintTimeline; + + public: + RTTI_DECL + + explicit IkConstraintData(const String &name); + + /// The bones that are constrained by this IK Constraint. + Vector &getBones(); + + /// The bone that is the IK target. + BoneData *getTarget(); + + void setTarget(BoneData *inValue); + + /// Controls the bend direction of the IK bones, either 1 or -1. + int getBendDirection(); + + void setBendDirection(int inValue); + + bool getCompress(); + + void setCompress(bool inValue); + + bool getStretch(); + + void setStretch(bool inValue); + + bool getUniform(); + + void setUniform(bool inValue); + + float getMix(); + + void setMix(float inValue); + + float getSoftness(); + + void setSoftness(float inValue); + + private: + Vector _bones; + BoneData *_target; + int _bendDirection; + bool _compress; + bool _stretch; + bool _uniform; + float _mix; + float _softness; + }; +} + +#endif /* Spine_IkConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h new file mode 100644 index 0000000..54c2d5a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraintTimeline_h +#define Spine_IkConstraintTimeline_h + +#include + +namespace spine { + + class SP_API IkConstraintTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit IkConstraintTimeline(size_t frameCount, size_t bezierCount, int ikConstraintIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time, mix and bend direction of the specified keyframe. + void setFrame(int frame, float time, float mix, float softness, int bendDirection, bool compress, bool stretch); + + int getIkConstraintIndex() { return _ikConstraintIndex; } + + void setIkConstraintIndex(int inValue) { _ikConstraintIndex = inValue; } + + private: + int _ikConstraintIndex; + + static const int ENTRIES = 6; + static const int MIX = 1; + static const int SOFTNESS = 2; + static const int BEND_DIRECTION = 3; + static const int COMPRESS = 4; + static const int STRETCH = 5; + }; +} + +#endif /* Spine_IkConstraintTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Json.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Json.h new file mode 100644 index 0000000..8c275e4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Json.h @@ -0,0 +1,116 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Json_h +#define Spine_Json_h + +#include + +#ifndef SPINE_JSON_HAVE_PREV +/* spine doesn't use the "prev" link in the Json sibling lists. */ +#define SPINE_JSON_HAVE_PREV 0 +#endif + +namespace spine { + class SP_API Json : public SpineObject { + friend class SkeletonJson; + + public: + /* Json Types: */ + static const int JSON_FALSE; + static const int JSON_TRUE; + static const int JSON_NULL; + static const int JSON_NUMBER; + static const int JSON_STRING; + static const int JSON_ARRAY; + static const int JSON_OBJECT; + + /* Get item "string" from object. Case insensitive. */ + static Json *getItem(Json *object, const char *string); + + static Json *getItem(Json *object, int childIndex); + + static const char *getString(Json *object, const char *name, const char *defaultValue); + + static float getFloat(Json *object, const char *name, float defaultValue); + + static int getInt(Json *object, const char *name, int defaultValue); + + static bool getBoolean(Json *object, const char *name, bool defaultValue); + + /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when Json_create() returns 0. 0 when Json_create() succeeds. */ + static const char *getError(); + + /* Supply a block of JSON, and this returns a Json object you can interrogate. Call Json_dispose when finished. */ + explicit Json(const char *value); + + ~Json(); + + + private: + static const char *_error; + + Json *_next; +#if SPINE_JSON_HAVE_PREV + Json* _prev; /* next/prev allow you to walk array/object chains. Alternatively, use getSize/getItem */ +#endif + Json *_child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int _type; /* The type of the item, as above. */ + int _size; /* The number of children. */ + + const char *_valueString; /* The item's string, if type==JSON_STRING */ + int _valueInt; /* The item's number, if type==JSON_NUMBER */ + float _valueFloat; /* The item's number, if type==JSON_NUMBER */ + + const char *_name; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + + /* Utility to jump whitespace and cr/lf */ + static const char *skip(const char *inValue); + + /* Parser core - when encountering text, process appropriately. */ + static const char *parseValue(Json *item, const char *value); + + /* Parse the input text into an unescaped cstring, and populate item. */ + static const char *parseString(Json *item, const char *str); + + /* Parse the input text to generate a number, and populate the result into item. */ + static const char *parseNumber(Json *item, const char *num); + + /* Build an array from input text. */ + static const char *parseArray(Json *item, const char *value); + + /* Build an object from the text. */ + static const char *parseObject(Json *item, const char *value); + + static int json_strcasecmp(const char *s1, const char *s2); + }; +} + +#endif /* Spine_Json_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/LinkedMesh.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/LinkedMesh.h new file mode 100644 index 0000000..053aa90 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/LinkedMesh.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_LinkedMesh_h +#define Spine_LinkedMesh_h + +#include +#include + +namespace spine { + class MeshAttachment; + + class SP_API LinkedMesh : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + public: + LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, + bool inheritTimeline); + + private: + MeshAttachment *_mesh; + String _skin; + size_t _slotIndex; + String _parent; + bool _inheritTimeline; + }; +} + +#endif /* Spine_LinkedMesh_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Log.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Log.h new file mode 100644 index 0000000..3d4fc65 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Log.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_DEBUG_LOG_H +#define SPINE_DEBUG_LOG_H + +#include + +namespace spine { + SP_API void spDebug_printSkeletonData(SkeletonData *skeletonData); + + SP_API void spDebug_printAnimation(Animation *animation); + + SP_API void spDebug_printTimeline(Timeline *timeline); + + SP_API void spDebug_printBoneDatas(Vector &boneDatas); + + SP_API void spDebug_printBoneData(BoneData *boneData); + + SP_API void spDebug_printSkeleton(Skeleton *skeleton); + + SP_API void spDebug_printBones(Vector &bones); + + SP_API void spDebug_printBone(Bone *bone); + + SP_API void spDebug_printFloats(float *values, int numFloats); + + SP_API void spDebug_printFloats(Vector &values); +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/MathUtil.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/MathUtil.h new file mode 100644 index 0000000..38691e7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -0,0 +1,132 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MathUtil_h +#define Spine_MathUtil_h + +#include + +#include +// Needed for older MSVC versions +#undef min +#undef max + +namespace spine { + + class SP_API MathUtil : public SpineObject { + private: + MathUtil(); + + public: + static const float Pi; + static const float Pi_2; + static const float Deg_Rad; + static const float Rad_Deg; + + template + static inline T min(T a, T b) { return a < b ? a : b; } + + template + static inline T max(T a, T b) { return a > b ? a : b; } + + static float sign(float val); + + static float clamp(float x, float lower, float upper); + + static float abs(float v); + + /// Returns the sine in radians from a lookup table. + static float sin(float radians); + + /// Returns the cosine in radians from a lookup table. + static float cos(float radians); + + /// Returns the sine in radians from a lookup table. + static float sinDeg(float degrees); + + /// Returns the cosine in radians from a lookup table. + static float cosDeg(float degrees); + + /// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 + /// degrees), largest error of 0.00488 radians (0.2796 degrees). + static float atan2(float y, float x); + + static float acos(float v); + + static float sqrt(float v); + + static float fmod(float a, float b); + + static bool isNan(float v); + + static float random(); + + static float randomTriangular(float min, float max); + + static float randomTriangular(float min, float max, float mode); + + static float pow(float a, float b); + }; + + struct SP_API Interpolation { + virtual float apply(float a) = 0; + + virtual float interpolate(float start, float end, float a) { + return start + (end - start) * apply(a); + } + + virtual ~Interpolation() {}; + }; + + struct SP_API PowInterpolation : public Interpolation { + PowInterpolation(int power) : power(power) { + } + + float apply(float a) { + if (a <= 0.5f) return MathUtil::pow(a * 2.0f, (float) power) / 2.0f; + return MathUtil::pow((a - 1.0f) * 2.0f, (float) power) / (power % 2 == 0 ? -2.0f : 2.0f) + 1.0f; + } + + int power; + }; + + struct SP_API PowOutInterpolation : public Interpolation { + PowOutInterpolation(int power) : power(power) { + } + + float apply(float a) { + return MathUtil::pow(a - 1, (float) power) * (power % 2 == 0 ? -1.0f : 1.0f) + 1.0f; + } + + int power; + }; + +} + +#endif /* Spine_MathUtil_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/MeshAttachment.h new file mode 100644 index 0000000..df8ed3a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MeshAttachment_h +#define Spine_MeshAttachment_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + /// Attachment that displays a texture region using a mesh. + class SP_API MeshAttachment : public VertexAttachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AtlasAttachmentLoader; + + RTTI_DECL + + public: + explicit MeshAttachment(const String &name); + + virtual ~MeshAttachment(); + + using VertexAttachment::computeWorldVertices; + + virtual void computeWorldVertices(Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride = 2); + + void updateRegion(); + + int getHullLength(); + + void setHullLength(int inValue); + + Vector &getRegionUVs(); + + /// The UV pair for each vertex, normalized within the entire texture. See also MeshAttachment::updateRegion + Vector &getUVs(); + + Vector &getTriangles(); + + Color &getColor(); + + const String &getPath(); + + void setPath(const String &inValue); + + TextureRegion *getRegion(); + + void setRegion(TextureRegion *region); + + Sequence *getSequence(); + + void setSequence(Sequence *sequence); + + MeshAttachment *getParentMesh(); + + void setParentMesh(MeshAttachment *inValue); + + // Nonessential. + Vector &getEdges(); + + float getWidth(); + + void setWidth(float inValue); + + float getHeight(); + + void setHeight(float inValue); + + virtual Attachment *copy(); + + MeshAttachment *newLinkedMesh(); + + private: + MeshAttachment *_parentMesh; + Vector _uvs; + Vector _regionUVs; + Vector _triangles; + Vector _edges; + String _path; + Color _color; + int _hullLength; + int _width, _height; + TextureRegion *_region; + Sequence *_sequence; + }; +} + +#endif /* Spine_MeshAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/MixBlend.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/MixBlend.h new file mode 100644 index 0000000..4d0bd52 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/MixBlend.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MixPose_h +#define Spine_MixPose_h + +namespace spine { + +/// Controls how a timeline is mixed with the setup or current pose. +/// See also Timeline::apply(Skeleton&, float, float, Vector&, float, Blend, MixDirection) + enum MixBlend { + MixBlend_Setup = 0, + MixBlend_First, + MixBlend_Replace, + MixBlend_Add + }; +} + +#endif /* Spine_MixPose_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/MixDirection.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/MixDirection.h new file mode 100644 index 0000000..80b3e99 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/MixDirection.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MixDirection_h +#define Spine_MixDirection_h + +namespace spine { + +/// Indicates whether a timeline's alpha is mixing out over time toward 0 (the setup or current pose) or mixing in toward 1 (the timeline's pose). +/// See also Timeline::apply(Skeleton&, float, float, Vector&, float, MixPose, MixDirection) + enum MixDirection { + MixDirection_In = 0, + MixDirection_Out + }; + +} + +#endif /* Spine_MixDirection_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathAttachment.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathAttachment.h new file mode 100644 index 0000000..9e92624 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathAttachment.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathAttachment_h +#define Spine_PathAttachment_h + +#include +#include + +namespace spine { + class SP_API PathAttachment : public VertexAttachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathAttachment(const String &name); + + /// The length in the setup pose from the start of the path to the end of each curve. + Vector &getLengths(); + + bool isClosed(); + + void setClosed(bool inValue); + + bool isConstantSpeed(); + + void setConstantSpeed(bool inValue); + + Color &getColor(); + + virtual Attachment *copy(); + + private: + Vector _lengths; + bool _closed; + bool _constantSpeed; + Color _color; + }; +} + +#endif /* Spine_PathAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraint.h new file mode 100644 index 0000000..870c1ef --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -0,0 +1,131 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraint_h +#define Spine_PathConstraint_h + +#include + +#include + +namespace spine { + class PathConstraintData; + + class Skeleton; + + class PathAttachment; + + class Bone; + + class Slot; + + class SP_API PathConstraint : public Updatable { + friend class Skeleton; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + RTTI_DECL + + public: + PathConstraint(PathConstraintData &data, Skeleton &skeleton); + + virtual void update(); + + virtual int getOrder(); + + PathConstraintData &getData(); + + Vector &getBones(); + + Slot *getTarget(); + + void setTarget(Slot *inValue); + + float getPosition(); + + void setPosition(float inValue); + + float getSpacing(); + + void setSpacing(float inValue); + + float getMixRotate(); + + void setMixRotate(float inValue); + + float getMixX(); + + void setMixX(float inValue); + + float getMixY(); + + void setMixY(float inValue); + + bool isActive(); + + void setActive(bool inValue); + + private: + static const float EPSILON; + static const int NONE; + static const int BEFORE; + static const int AFTER; + + PathConstraintData &_data; + Vector _bones; + Slot *_target; + float _position, _spacing; + float _mixRotate, _mixX, _mixY; + + Vector _spaces; + Vector _positions; + Vector _world; + Vector _curves; + Vector _lengths; + Vector _segments; + + bool _active; + + Vector &computeWorldPositions(PathAttachment &path, int spacesCount, bool tangents); + + static void addBeforePosition(float p, Vector &temp, int i, Vector &output, int o); + + static void addAfterPosition(float p, Vector &temp, int i, Vector &output, int o); + + static void + addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, + Vector &output, int o, bool tangents); + }; +} + +#endif /* Spine_PathConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraintData.h new file mode 100644 index 0000000..0354470 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -0,0 +1,119 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintData_h +#define Spine_PathConstraintData_h + +#include +#include +#include +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SlotData; + + class SP_API PathConstraintData : public ConstraintData { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class PathConstraint; + + friend class Skeleton; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + public: + RTTI_DECL + + explicit PathConstraintData(const String &name); + + Vector &getBones(); + + SlotData *getTarget(); + + void setTarget(SlotData *inValue); + + PositionMode getPositionMode(); + + void setPositionMode(PositionMode inValue); + + SpacingMode getSpacingMode(); + + void setSpacingMode(SpacingMode inValue); + + RotateMode getRotateMode(); + + void setRotateMode(RotateMode inValue); + + float getOffsetRotation(); + + void setOffsetRotation(float inValue); + + float getPosition(); + + void setPosition(float inValue); + + float getSpacing(); + + void setSpacing(float inValue); + + float getMixRotate(); + + void setMixRotate(float inValue); + + float getMixX(); + + void setMixX(float inValue); + + float getMixY(); + + void setMixY(float inValue); + + private: + Vector _bones; + SlotData *_target; + PositionMode _positionMode; + SpacingMode _spacingMode; + RotateMode _rotateMode; + float _offsetRotation; + float _position, _spacing; + float _mixRotate, _mixX, _mixY; + }; +} + +#endif /* Spine_PathConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h new file mode 100644 index 0000000..5c245b2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -0,0 +1,69 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintMixTimeline_h +#define Spine_PathConstraintMixTimeline_h + +#include + +namespace spine { +#define SP_PATHCONSTRAINTMIXTIMELINE_ENTRIES 5 + + class SP_API PathConstraintMixTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathConstraintMixTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and mixes of the specified keyframe. + void setFrame(int frameIndex, float time, float mixRotate, float mixX, float mixY); + + int getPathConstraintIndex() { return _pathConstraintIndex; } + + void setPathConstraintIndex(int inValue) { _pathConstraintIndex = inValue; } + + private: + int _pathConstraintIndex; + + static const int ENTRIES = 4; + static const int ROTATE = 1; + static const int X = 2; + static const int Y = 2; + }; +} + +#endif /* Spine_PathConstraintMixTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h new file mode 100644 index 0000000..38dcffb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintPositionTimeline_h +#define Spine_PathConstraintPositionTimeline_h + +#include + +namespace spine { + + class SP_API PathConstraintPositionTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + static const int ENTRIES; + + explicit PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex); + + virtual ~PathConstraintPositionTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getPathConstraintIndex() { return _pathConstraintIndex; } + + void setPathConstraintIndex(int inValue) { _pathConstraintIndex = inValue; } + + protected: + int _pathConstraintIndex; + }; +} + +#endif /* Spine_PathConstraintPositionTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h new file mode 100644 index 0000000..506f0eb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintSpacingTimeline_h +#define Spine_PathConstraintSpacingTimeline_h + +#include + +namespace spine { + class SP_API PathConstraintSpacingTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathConstraintSpacingTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getPathConstraintIndex() { return _pathConstraintIndex; } + + void setPathConstraintIndex(int inValue) { _pathConstraintIndex = inValue; } + + protected: + int _pathConstraintIndex; + }; +} + +#endif /* Spine_PathConstraintSpacingTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PointAttachment.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PointAttachment.h new file mode 100644 index 0000000..672f342 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PointAttachment.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PointAttachment_h +#define Spine_PointAttachment_h + +#include +#include + +namespace spine { + class Bone; + + /// An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be + /// used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a + /// skin. + /// + /// See http://esotericsoftware.com/spine-point-attachments for Point Attachments in the Spine User Guide. + /// + class SP_API PointAttachment : public Attachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PointAttachment(const String &name); + + void computeWorldPosition(Bone &bone, float &ox, float &oy); + + float computeWorldRotation(Bone &bone); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getRotation(); + + void setRotation(float inValue); + + Color &getColor(); + + virtual Attachment *copy(); + + private: + float _x, _y, _rotation; + Color _color; + }; +} + +#endif /* Spine_PointAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Pool.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Pool.h new file mode 100644 index 0000000..ed8e611 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Pool.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Pool_h +#define Spine_Pool_h + +#include +#include +#include +#include + +namespace spine { + template + class SP_API Pool : public SpineObject { + public: + Pool() { + } + + ~Pool() { + ContainerUtil::cleanUpVectorOfPointers(_objects); + } + + T *obtain() { + if (_objects.size() > 0) { + T **object = &_objects[_objects.size() - 1]; + T *ret = *object; + _objects.removeAt(_objects.size() - 1); + + return ret; + } else { + T *ret = new(__FILE__, __LINE__) T(); + + return ret; + } + } + + void free(T *object) { + if (!_objects.contains(object)) { + _objects.add(object); + } + } + + private: + Vector _objects; + }; +} + +#endif /* Spine_Pool_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PositionMode.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PositionMode.h new file mode 100644 index 0000000..3aea759 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/PositionMode.h @@ -0,0 +1,40 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PositionMode_h +#define Spine_PositionMode_h + +namespace spine { + enum PositionMode { + PositionMode_Fixed = 0, + PositionMode_Percent + }; +} + +#endif /* Spine_PositionMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Property.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Property.h new file mode 100644 index 0000000..d19a876 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Property.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Property_h +#define Spine_Property_h + +namespace spine { + typedef long long PropertyId; + enum Property { + Property_Rotate = 1 << 0, + Property_X = 1 << 1, + Property_Y = 1 << 2, + Property_ScaleX = 1 << 3, + Property_ScaleY = 1 << 4, + Property_ShearX = 1 << 5, + Property_ShearY = 1 << 6, + Property_Rgb = 1 << 7, + Property_Alpha = 1 << 8, + Property_Rgb2 = 1 << 9, + Property_Attachment = 1 << 10, + Property_Deform = 1 << 11, + Property_Event = 1 << 12, + Property_DrawOrder = 1 << 13, + Property_IkConstraint = 1 << 14, + Property_TransformConstraint = 1 << 15, + Property_PathConstraintPosition = 1 << 16, + Property_PathConstraintSpacing = 1 << 17, + Property_PathConstraintMix = 1 << 18, + Property_Sequence = 1 << 19 + }; +} + +#endif /* Spine_Property_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/RTTI.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/RTTI.h new file mode 100644 index 0000000..6b0027b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/RTTI.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RTTI_h +#define Spine_RTTI_h + +#include + +namespace spine { + class SP_API RTTI { + public: + explicit RTTI(const char *className); + + RTTI(const char *className, const RTTI &baseRTTI); + + const char *getClassName() const; + + bool isExactly(const RTTI &rtti) const; + + bool instanceOf(const RTTI &rtti) const; + + private: + // Prevent copying + RTTI(const RTTI &obj); + + RTTI &operator=(const RTTI &obj); + + const char *_className; + const RTTI *_pBaseRTTI; + }; +} + +#define RTTI_DECL \ +public: \ +static const spine::RTTI rtti; \ +virtual const spine::RTTI& getRTTI() const; + +#define RTTI_IMPL_NOPARENT(name) \ +const spine::RTTI name::rtti(#name); \ +const spine::RTTI& name::getRTTI() const { return rtti; } + +#define RTTI_IMPL(name, parent) \ +const spine::RTTI name::rtti(#name, parent::rtti); \ +const spine::RTTI& name::getRTTI() const { return rtti; } + +#endif /* Spine_RTTI_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/RegionAttachment.h new file mode 100644 index 0000000..376ba81 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -0,0 +1,140 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RegionAttachment_h +#define Spine_RegionAttachment_h + +#include +#include +#include +#include +#include + +#include + +#define NUM_UVS 8 + +namespace spine { + class Bone; + + /// Attachment that displays a texture region. + class SP_API RegionAttachment : public Attachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AtlasAttachmentLoader; + + RTTI_DECL + + public: + explicit RegionAttachment(const String &name); + + virtual ~RegionAttachment(); + + void updateRegion(); + + /// Transforms the attachment's four vertices to world coordinates. + /// @param slot The parent slot. + /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8. + /// @param offset The worldVertices index to begin writing values. + /// @param stride The number of worldVertices entries between the value pairs written. + void computeWorldVertices(Slot &slot, float *worldVertices, size_t offset, size_t stride = 2); + + void computeWorldVertices(Slot &slot, Vector &worldVertices, size_t offset, size_t stride = 2); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getRotation(); + + void setRotation(float inValue); + + float getScaleX(); + + void setScaleX(float inValue); + + float getScaleY(); + + void setScaleY(float inValue); + + float getWidth(); + + void setWidth(float inValue); + + float getHeight(); + + void setHeight(float inValue); + + Color &getColor(); + + const String &getPath(); + + void setPath(const String &inValue); + + TextureRegion *getRegion(); + + void setRegion(TextureRegion *region); + + Sequence *getSequence(); + + void setSequence(Sequence *sequence); + + Vector &getOffset(); + + Vector &getUVs(); + + virtual Attachment *copy(); + + private: + static const int BLX; + static const int BLY; + static const int ULX; + static const int ULY; + static const int URX; + static const int URY; + static const int BRX; + static const int BRY; + + float _x, _y, _rotation, _scaleX, _scaleY, _width, _height; + Vector _vertexOffset; + Vector _uvs; + String _path; + Color _color; + TextureRegion *_region; + Sequence *_sequence; + }; +} + +#endif /* Spine_RegionAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/RotateMode.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/RotateMode.h new file mode 100644 index 0000000..f34ce78 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/RotateMode.h @@ -0,0 +1,41 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RotateMode_h +#define Spine_RotateMode_h + +namespace spine { + enum RotateMode { + RotateMode_Tangent = 0, + RotateMode_Chain, + RotateMode_ChainScale + }; +} + +#endif /* Spine_RotateMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/RotateTimeline.h new file mode 100644 index 0000000..29ace74 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RotateTimeline_h +#define Spine_RotateTimeline_h + +#include + +namespace spine { + class SP_API RotateTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + + RTTI_DECL + + public: + explicit RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; +} + +#endif /* Spine_RotateTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h new file mode 100644 index 0000000..447824d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -0,0 +1,109 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ScaleTimeline_h +#define Spine_ScaleTimeline_h + +#include + +namespace spine { + class SP_API ScaleTimeline : public CurveTimeline2 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ScaleTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API ScaleXTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ScaleXTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API ScaleYTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ScaleYTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; +} + +#endif /* Spine_ScaleTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Sequence.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Sequence.h new file mode 100644 index 0000000..bbf631a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Sequence.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Sequence_h +#define Spine_Sequence_h + +#include +#include +#include + +namespace spine { + class Slot; + + class Attachment; + + class SkeletonBinary; + class SkeletonJson; + + class SP_API Sequence : public SpineObject { + friend class SkeletonBinary; + friend class SkeletonJson; + public: + Sequence(int count); + + ~Sequence(); + + Sequence *copy(); + + void apply(Slot *slot, Attachment *attachment); + + String getPath(const String &basePath, int index); + + int getId() { return _id; } + + void setId(int id) { _id = id; } + + int getStart() { return _start; } + + void setStart(int start) { _start = start; } + + int getDigits() { return _digits; } + + void setDigits(int digits) { _digits = digits; } + + int getSetupIndex() { return _setupIndex; } + + void setSetupIndex(int setupIndex) { _setupIndex = setupIndex; } + + Vector &getRegions() { return _regions; } + + private: + int _id; + Vector _regions; + int _start; + int _digits; + int _setupIndex; + + int getNextID(); + }; + + enum SequenceMode { + hold = 0, + once = 1, + loop = 2, + pingpong = 3, + onceReverse = 4, + loopReverse = 5, + pingpongReverse = 6 + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SequenceTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SequenceTimeline.h new file mode 100644 index 0000000..2f1ab20 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SequenceTimeline.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SequenceTimeline_h +#define Spine_SequenceTimeline_h + +#include +#include + +namespace spine { + class Attachment; + + class SP_API SequenceTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit SequenceTimeline(size_t frameCount, int slotIndex, spine::Attachment *attachment); + + virtual ~SequenceTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + void setFrame(int frame, float time, SequenceMode mode, int index, float delay); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + Attachment *getAttachment() { return _attachment; } + + protected: + int _slotIndex; + Attachment *_attachment; + + static const int ENTRIES = 3; + static const int MODE = 1; + static const int DELAY = 2; + }; +} + +#endif /* Spine_SequenceTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ShearTimeline.h new file mode 100644 index 0000000..8a72133 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -0,0 +1,109 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ShearTimeline_h +#define Spine_ShearTimeline_h + +#include + +namespace spine { + class SP_API ShearTimeline : public CurveTimeline2 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ShearTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API ShearXTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ShearXTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API ShearYTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ShearYTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; +} + +#endif /* Spine_ShearTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Skeleton.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Skeleton.h new file mode 100644 index 0000000..5dc0c27 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -0,0 +1,253 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Skeleton_h +#define Spine_Skeleton_h + +#include +#include +#include +#include +#include + +namespace spine { + class SkeletonData; + + class Bone; + + class Updatable; + + class Slot; + + class IkConstraint; + + class PathConstraint; + + class TransformConstraint; + + class Skin; + + class Attachment; + + class SP_API Skeleton : public SpineObject { + friend class AnimationState; + + friend class SkeletonBounds; + + friend class SkeletonClipping; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class ScaleTimeline; + + friend class ScaleXTimeline; + + friend class ScaleYTimeline; + + friend class ShearTimeline; + + friend class ShearXTimeline; + + friend class ShearYTimeline; + + friend class TransformConstraintTimeline; + + friend class RotateTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + friend class TwoColorTimeline; + + public: + explicit Skeleton(SkeletonData *skeletonData); + + ~Skeleton(); + + /// Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added + /// or removed. + void updateCache(); + + void printUpdateCache(); + + /// Updates the world transform for each bone and applies constraints. + void updateWorldTransform(); + + void updateWorldTransform(Bone *parent); + + /// Sets the bones, constraints, and slots to their setup pose values. + void setToSetupPose(); + + /// Sets the bones and constraints to their setup pose values. + void setBonesToSetupPose(); + + void setSlotsToSetupPose(); + + /// @return May be NULL. + Bone *findBone(const String &boneName); + + /// @return May be NULL. + Slot *findSlot(const String &slotName); + + /// Sets a skin by name (see setSkin). + void setSkin(const String &skinName); + + /// Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. + /// If there was no old skin, each slot's setup mode attachment is attached from the new skin. + /// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling + /// See Skeleton::setSlotsToSetupPose() + /// Also, often AnimationState::apply(Skeleton&) is called before the next time the + /// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. + /// @param newSkin May be NULL. + void setSkin(Skin *newSkin); + + /// @return May be NULL. + Attachment *getAttachment(const String &slotName, const String &attachmentName); + + /// @return May be NULL. + Attachment *getAttachment(int slotIndex, const String &attachmentName); + + /// @param attachmentName May be empty. + void setAttachment(const String &slotName, const String &attachmentName); + + /// @return May be NULL. + IkConstraint *findIkConstraint(const String &constraintName); + + /// @return May be NULL. + TransformConstraint *findTransformConstraint(const String &constraintName); + + /// @return May be NULL. + PathConstraint *findPathConstraint(const String &constraintName); + + /// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. + /// @param outX The horizontal distance between the skeleton origin and the left side of the AABB. + /// @param outY The vertical distance between the skeleton origin and the bottom side of the AABB. + /// @param outWidth The width of the AABB + /// @param outHeight The height of the AABB. + /// @param outVertexBuffer Reference to hold a Vector of floats. This method will assign it with new floats as needed. + void getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector &outVertexBuffer); + + Bone *getRootBone(); + + SkeletonData *getData(); + + Vector &getBones(); + + Vector &getUpdateCacheList(); + + Vector &getSlots(); + + Vector &getDrawOrder(); + + Vector &getIkConstraints(); + + Vector &getPathConstraints(); + + Vector &getTransformConstraints(); + + Skin *getSkin(); + + Color &getColor(); + + void setPosition(float x, float y); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getScaleX(); + + void setScaleX(float inValue); + + float getScaleY(); + + void setScaleY(float inValue); + + private: + SkeletonData *_data; + Vector _bones; + Vector _slots; + Vector _drawOrder; + Vector _ikConstraints; + Vector _transformConstraints; + Vector _pathConstraints; + Vector _updateCache; + Skin *_skin; + Color _color; + float _scaleX, _scaleY; + float _x, _y; + + void sortIkConstraint(IkConstraint *constraint); + + void sortPathConstraint(PathConstraint *constraint); + + void sortTransformConstraint(TransformConstraint *constraint); + + void sortPathConstraintAttachment(Skin *skin, size_t slotIndex, Bone &slotBone); + + void sortPathConstraintAttachment(Attachment *attachment, Bone &slotBone); + + void sortBone(Bone *bone); + + static void sortReset(Vector &bones); + }; +} + +#endif /* Spine_Skeleton_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h new file mode 100644 index 0000000..a1ade7d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -0,0 +1,168 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonBinary_h +#define Spine_SkeletonBinary_h + +#include +#include +#include +#include +#include + +namespace spine { + class SkeletonData; + + class Atlas; + + class AttachmentLoader; + + class LinkedMesh; + + class Skin; + + class Attachment; + + class VertexAttachment; + + class Animation; + + class Timeline; + + class CurveTimeline; + + class CurveTimeline1; + + class CurveTimeline2; + + class Sequence; + + class SP_API SkeletonBinary : public SpineObject { + public: + static const int BONE_ROTATE = 0; + static const int BONE_TRANSLATE = 1; + static const int BONE_TRANSLATEX = 2; + static const int BONE_TRANSLATEY = 3; + static const int BONE_SCALE = 4; + static const int BONE_SCALEX = 5; + static const int BONE_SCALEY = 6; + static const int BONE_SHEAR = 7; + static const int BONE_SHEARX = 8; + static const int BONE_SHEARY = 9; + + static const int SLOT_ATTACHMENT = 0; + static const int SLOT_RGBA = 1; + static const int SLOT_RGB = 2; + static const int SLOT_RGBA2 = 3; + static const int SLOT_RGB2 = 4; + static const int SLOT_ALPHA = 5; + + static const int ATTACHMENT_DEFORM = 0; + static const int ATTACHMENT_SEQUENCE = 1; + + static const int PATH_POSITION = 0; + static const int PATH_SPACING = 1; + static const int PATH_MIX = 2; + + static const int CURVE_LINEAR = 0; + static const int CURVE_STEPPED = 1; + static const int CURVE_BEZIER = 2; + + explicit SkeletonBinary(Atlas *atlasArray); + + explicit SkeletonBinary(AttachmentLoader *attachmentLoader, bool ownsLoader = false); + + ~SkeletonBinary(); + + SkeletonData *readSkeletonData(const unsigned char *binary, int length); + + SkeletonData *readSkeletonDataFile(const String &path); + + void setScale(float scale) { _scale = scale; } + + String &getError() { return _error; } + + private: + struct DataInput : public SpineObject { + const unsigned char *cursor; + const unsigned char *end; + }; + + AttachmentLoader *_attachmentLoader; + Vector _linkedMeshes; + String _error; + float _scale; + const bool _ownsLoader; + + void setError(const char *value1, const char *value2); + + char *readString(DataInput *input); + + char *readStringRef(DataInput *input, SkeletonData *skeletonData); + + float readFloat(DataInput *input); + + unsigned char readByte(DataInput *input); + + signed char readSByte(DataInput *input); + + bool readBoolean(DataInput *input); + + int readInt(DataInput *input); + + void readColor(DataInput *input, Color &color); + + int readVarint(DataInput *input, bool optimizePositive); + + Skin *readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential); + + Sequence *readSequence(DataInput *input); + + Attachment *readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName, + SkeletonData *skeletonData, bool nonessential); + + void readVertices(DataInput *input, Vector &vertices, Vector &bones, int vertexCount); + + void readFloatArray(DataInput *input, int n, float scale, Vector &array); + + void readShortArray(DataInput *input, Vector &array); + + Animation *readAnimation(const String &name, DataInput *input, SkeletonData *skeletonData); + + void + setBezier(DataInput *input, CurveTimeline *timeline, int bezier, int frame, int value, float time1, float time2, + float value1, float value2, float scale); + + Timeline *readTimeline(DataInput *input, CurveTimeline1 *timeline, float scale); + + Timeline *readTimeline2(DataInput *input, CurveTimeline2 *timeline, float scale); + }; +} + +#endif /* Spine_SkeletonBinary_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h new file mode 100644 index 0000000..8dc4cab --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonBounds_h +#define Spine_SkeletonBounds_h + +#include +#include +#include + +namespace spine { + class Skeleton; + + class BoundingBoxAttachment; + + class Polygon; + + /// Collects each BoundingBoxAttachment that is visible and computes the world vertices for its polygon. + /// The polygon vertices are provided along with convenience methods for doing hit detection. + class SP_API SkeletonBounds : public SpineObject { + public: + SkeletonBounds(); + + ~SkeletonBounds(); + + /// Clears any previous polygons, finds all visible bounding box attachments, + /// and computes the world vertices for each bounding box's polygon. + /// @param skeleton The skeleton. + /// @param updateAabb + /// If true, the axis aligned bounding box containing all the polygons is computed. + /// If false, the SkeletonBounds AABB methods will always return true. + /// + void update(Skeleton &skeleton, bool updateAabb); + + /// Returns true if the axis aligned bounding box contains the point. + bool aabbcontainsPoint(float x, float y); + + /// Returns true if the axis aligned bounding box intersects the line segment. + bool aabbintersectsSegment(float x1, float y1, float x2, float y2); + + /// Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. + bool aabbIntersectsSkeleton(SkeletonBounds bounds); + + /// Returns true if the polygon contains the point. + bool containsPoint(Polygon *polygon, float x, float y); + + /// Returns the first bounding box attachment that contains the point, or NULL. When doing many checks, it is usually more + /// efficient to only call this method if {@link #aabbcontainsPoint(float, float)} returns true. + BoundingBoxAttachment *containsPoint(float x, float y); + + /// Returns the first bounding box attachment that contains the line segment, or NULL. When doing many checks, it is usually + /// more efficient to only call this method if {@link #aabbintersectsSegment(float, float, float, float)} returns true. + BoundingBoxAttachment *intersectsSegment(float x1, float y1, float x2, float y2); + + /// Returns true if the polygon contains the line segment. + bool intersectsSegment(Polygon *polygon, float x1, float y1, float x2, float y2); + + /// Returns the polygon for the given bounding box attachment or null if no + /// polygon can be found for the attachment. Requires a call to update() first. + Polygon *getPolygon(BoundingBoxAttachment *attachment); + + /// Returns the bounding box for the given polygon or null. Requires a call to update() first. + BoundingBoxAttachment * getBoundingBox(Polygon *polygon); + + /// Returns all polygons or an empty vector. Requires a call to update() first. + Vector &getPolygons(); + + /// Returns all bounding boxes. Requires a call to update() first. + Vector &getBoundingBoxes(); + + float getWidth(); + + float getHeight(); + + private: + Pool _polygonPool; + Vector _boundingBoxes; + Vector _polygons; + float _minX, _minY, _maxX, _maxY; + + void aabbCompute(); + }; + + class Polygon : public SpineObject { + public: + Vector _vertices; + int _count; + + Polygon() : _count(0) { + _vertices.ensureCapacity(16); + } + }; +} + +#endif /* Spine_SkeletonBounds_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h new file mode 100644 index 0000000..a5fbdc7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h @@ -0,0 +1,85 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonClipping_h +#define Spine_SkeletonClipping_h + +#include +#include + +namespace spine { + class Slot; + + class ClippingAttachment; + + class SP_API SkeletonClipping : public SpineObject { + public: + SkeletonClipping(); + + size_t clipStart(Slot &slot, ClippingAttachment *clip); + + void clipEnd(Slot &slot); + + void clipEnd(); + + void + clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength, float *uvs, size_t stride); + + void + clipTriangles(Vector &vertices, Vector &triangles, Vector &uvs, size_t stride); + + bool isClipping(); + + Vector &getClippedVertices(); + + Vector &getClippedTriangles(); + + Vector &getClippedUVs(); + + private: + Triangulator _triangulator; + Vector _clippingPolygon; + Vector _clipOutput; + Vector _clippedVertices; + Vector _clippedTriangles; + Vector _clippedUVs; + Vector _scratch; + ClippingAttachment *_clipAttachment; + Vector *> *_clippingPolygons; + + /** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping + * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */ + bool clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector *clippingArea, + Vector *output); + + static void makeClockwise(Vector &polygon); + }; +} + +#endif /* Spine_SkeletonClipping_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonData.h new file mode 100644 index 0000000..14a7c66 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonData.h @@ -0,0 +1,182 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonData_h +#define Spine_SkeletonData_h + +#include +#include + +namespace spine { + class BoneData; + + class SlotData; + + class Skin; + + class EventData; + + class Animation; + + class IkConstraintData; + + class TransformConstraintData; + + class PathConstraintData; + +/// Stores the setup pose and all of the stateless data for a skeleton. + class SP_API SkeletonData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class Skeleton; + + public: + SkeletonData(); + + ~SkeletonData(); + + /// Finds a bone by comparing each bone's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + BoneData *findBone(const String &boneName); + + /// @return May be NULL. + SlotData *findSlot(const String &slotName); + + /// @return May be NULL. + Skin *findSkin(const String &skinName); + + /// @return May be NULL. + spine::EventData *findEvent(const String &eventDataName); + + /// @return May be NULL. + Animation *findAnimation(const String &animationName); + + /// @return May be NULL. + IkConstraintData *findIkConstraint(const String &constraintName); + + /// @return May be NULL. + TransformConstraintData *findTransformConstraint(const String &constraintName); + + /// @return May be NULL. + PathConstraintData *findPathConstraint(const String &constraintName); + + const String &getName(); + + void setName(const String &inValue); + + /// The skeleton's bones, sorted parent first. The root bone is always the first bone. + Vector &getBones(); + + Vector &getSlots(); + + /// All skins, including the default skin. + Vector &getSkins(); + + /// The skeleton's default skin. + /// By default this skin contains all attachments that were not in a skin in Spine. + /// @return May be NULL. + Skin *getDefaultSkin(); + + void setDefaultSkin(Skin *inValue); + + Vector &getEvents(); + + Vector &getAnimations(); + + Vector &getIkConstraints(); + + Vector &getTransformConstraints(); + + Vector &getPathConstraints(); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getWidth(); + + void setWidth(float inValue); + + float getHeight(); + + void setHeight(float inValue); + + /// The Spine version used to export this data, or NULL. + const String &getVersion(); + + void setVersion(const String &inValue); + + const String &getHash(); + + void setHash(const String &inValue); + + const String &getImagesPath(); + + void setImagesPath(const String &inValue); + + const String &getAudioPath(); + + void setAudioPath(const String &inValue); + + /// The dopesheet FPS in Spine. Available only when nonessential data was exported. + float getFps(); + + void setFps(float inValue); + + private: + String _name; + Vector _bones; // Ordered parents first + Vector _slots; // Setup pose draw order. + Vector _skins; + Skin *_defaultSkin; + Vector _events; + Vector _animations; + Vector _ikConstraints; + Vector _transformConstraints; + Vector _pathConstraints; + float _x, _y, _width, _height; + String _version; + String _hash; + Vector _strings; + + // Nonessential. + float _fps; + String _imagesPath; + String _audioPath; + }; +} + +#endif /* Spine_SkeletonData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonJson.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonJson.h new file mode 100644 index 0000000..754d7de --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SkeletonJson.h @@ -0,0 +1,114 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonJson_h +#define Spine_SkeletonJson_h + +#include +#include +#include + +namespace spine { + class Timeline; + + class CurveTimeline; + + class CurveTimeline1; + + class CurveTimeline2; + + class VertexAttachment; + + class Animation; + + class Json; + + class SkeletonData; + + class Atlas; + + class AttachmentLoader; + + class LinkedMesh; + + class String; + + class Sequence; + + class SP_API SkeletonJson : public SpineObject { + public: + explicit SkeletonJson(Atlas *atlas); + + explicit SkeletonJson(AttachmentLoader *attachmentLoader, bool ownsLoader = false); + + ~SkeletonJson(); + + SkeletonData *readSkeletonDataFile(const String &path); + + SkeletonData *readSkeletonData(const char *json); + + void setScale(float scale) { _scale = scale; } + + String &getError() { return _error; } + + private: + AttachmentLoader *_attachmentLoader; + Vector _linkedMeshes; + float _scale; + const bool _ownsLoader; + String _error; + + static Sequence *readSequence(Json *sequence); + + static void + setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1, + float cy1, + float cx2, float cy2, float time2, float value2); + + static int + readCurve(Json *curve, CurveTimeline *timeline, int bezier, int frame, int value, float time1, float time2, + float value1, float value2, float scale); + + static Timeline *readTimeline(Json *keyMap, CurveTimeline1 *timeline, float defaultValue, float scale); + + static Timeline * + readTimeline(Json *keyMap, CurveTimeline2 *timeline, const char *name1, const char *name2, float defaultValue, + float scale); + + Animation *readAnimation(Json *root, SkeletonData *skeletonData); + + void readVertices(Json *attachmentMap, VertexAttachment *attachment, size_t verticesLength); + + void setError(Json *root, const String &value1, const String &value2); + + int findSlotIndex(SkeletonData *skeletonData, const String &slotName, Vector timelines); + }; +} + +#endif /* Spine_SkeletonJson_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Skin.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Skin.h new file mode 100644 index 0000000..ea6542e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Skin.h @@ -0,0 +1,167 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Skin_h +#define Spine_Skin_h + +#include +#include + +namespace spine { + class Attachment; + + class Skeleton; + + class BoneData; + + class ConstraintData; + +/// Stores attachments by slot index and attachment name. +/// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and +/// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide. + class SP_API Skin : public SpineObject { + friend class Skeleton; + + public: + class SP_API AttachmentMap : public SpineObject { + friend class Skin; + + public: + struct SP_API Entry { + size_t _slotIndex; + String _name; + Attachment *_attachment; + + Entry(size_t slotIndex, const String &name, Attachment *attachment) : + _slotIndex(slotIndex), + _name(name), + _attachment(attachment) { + } + }; + + class SP_API Entries { + friend class AttachmentMap; + + public: + bool hasNext() { + while (true) { + if (_slotIndex >= _buckets.size()) return false; + if (_bucketIndex >= _buckets[_slotIndex].size()) { + _bucketIndex = 0; + ++_slotIndex; + continue; + }; + return true; + } + } + + Entry &next() { + Entry &result = _buckets[_slotIndex][_bucketIndex]; + ++_bucketIndex; + return result; + } + + protected: + Entries(Vector > &buckets) : _buckets(buckets), _slotIndex(0), _bucketIndex(0) { + } + + private: + Vector > &_buckets; + size_t _slotIndex; + size_t _bucketIndex; + }; + + void put(size_t slotIndex, const String &attachmentName, Attachment *attachment); + + Attachment *get(size_t slotIndex, const String &attachmentName); + + void remove(size_t slotIndex, const String &attachmentName); + + Entries getEntries(); + + protected: + AttachmentMap(); + + private: + + int findInBucket(Vector &, const String &attachmentName); + + Vector > _buckets; + }; + + explicit Skin(const String &name); + + ~Skin(); + + /// Adds an attachment to the skin for the specified slot index and name. + /// If the name already exists for the slot, the previous value is replaced. + void setAttachment(size_t slotIndex, const String &name, Attachment *attachment); + + /// Returns the attachment for the specified slot index and name, or NULL. + Attachment *getAttachment(size_t slotIndex, const String &name); + + // Removes the attachment from the skin. + void removeAttachment(size_t slotIndex, const String &name); + + /// Finds the skin keys for a given slot. The results are added to the passed array of names. + /// @param slotIndex The target slotIndex. To find the slot index, use SkeletonData::findSlot and SlotData::getIndex. + /// @param names Found skin key names will be added to this array. + void findNamesForSlot(size_t slotIndex, Vector &names); + + /// Finds the attachments for a given slot. The results are added to the passed array of Attachments. + /// @param slotIndex The target slotIndex. To find the slot index, use SkeletonData::findSlot and SlotData::getIndex. + /// @param attachments Found Attachments will be added to this array. + void findAttachmentsForSlot(size_t slotIndex, Vector &attachments); + + const String &getName(); + + /// Adds all attachments, bones, and constraints from the specified skin to this skin. + void addSkin(Skin *other); + + /// Adds all attachments, bones, and constraints from the specified skin to this skin. Attachments are deep copied. + void copySkin(Skin *other); + + AttachmentMap::Entries getAttachments(); + + Vector &getBones(); + + Vector &getConstraints(); + + private: + const String _name; + AttachmentMap _attachments; + Vector _bones; + Vector _constraints; + + /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. + void attachAll(Skeleton &skeleton, Skin &oldSkin); + }; +} + +#endif /* Spine_Skin_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Slot.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Slot.h new file mode 100644 index 0000000..d9a073a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Slot.h @@ -0,0 +1,137 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Slot_h +#define Spine_Slot_h + +#include +#include +#include + +namespace spine { + class SlotData; + + class Bone; + + class Skeleton; + + class Attachment; + + class SP_API Slot : public SpineObject { + friend class VertexAttachment; + + friend class Skeleton; + + friend class SkeletonBounds; + + friend class SkeletonClipping; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TwoColorTimeline; + + public: + Slot(SlotData &data, Bone &bone); + + void setToSetupPose(); + + SlotData &getData(); + + Bone &getBone(); + + Skeleton &getSkeleton(); + + Color &getColor(); + + Color &getDarkColor(); + + bool hasDarkColor(); + + /// May be NULL. + Attachment *getAttachment(); + + void setAttachment(Attachment *inValue); + + int getAttachmentState(); + + void setAttachmentState(int state); + + Vector &getDeform(); + + int getSequenceIndex(); + + void setSequenceIndex(int index); + + private: + SlotData &_data; + Bone &_bone; + Skeleton &_skeleton; + Color _color; + Color _darkColor; + bool _hasDarkColor; + Attachment *_attachment; + int _attachmentState; + int _sequenceIndex; + Vector _deform; + }; +} + +#endif /* Spine_Slot_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SlotData.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SlotData.h new file mode 100644 index 0000000..3733aea --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SlotData_h +#define Spine_SlotData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SP_API SlotData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TwoColorTimeline; + + public: + SlotData(int index, const String &name, BoneData &boneData); + + int getIndex(); + + const String &getName(); + + BoneData &getBoneData(); + + Color &getColor(); + + Color &getDarkColor(); + + bool hasDarkColor(); + + void setHasDarkColor(bool inValue); + + /// May be empty. + const String &getAttachmentName(); + + void setAttachmentName(const String &inValue); + + BlendMode getBlendMode(); + + void setBlendMode(BlendMode inValue); + + private: + const int _index; + String _name; + BoneData &_boneData; + Color _color; + Color _darkColor; + + bool _hasDarkColor; + String _attachmentName; + BlendMode _blendMode; + }; +} + +#endif /* Spine_SlotData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SpacingMode.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SpacingMode.h new file mode 100644 index 0000000..2e7bdb6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SpacingMode.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SpacingMode_h +#define Spine_SpacingMode_h + +namespace spine { + enum SpacingMode { + SpacingMode_Length = 0, + SpacingMode_Fixed, + SpacingMode_Percent, + SpacingMode_Proportional + }; +} + +#endif /* Spine_SpacingMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SpineObject.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SpineObject.h new file mode 100644 index 0000000..c79cf3b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SpineObject.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Object_h +#define Spine_Object_h + +#include +#include + +#include + +namespace spine { + class String; + + class SP_API SpineObject { + public: + void *operator new(size_t sz); + + void *operator new(size_t sz, const char *file, int line); + + void *operator new(size_t sz, void *ptr); + + void operator delete(void *p, const char *file, int line); + + void operator delete(void *p, void *mem); + + void operator delete(void *p); + + virtual ~SpineObject(); + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SpineString.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SpineString.h new file mode 100644 index 0000000..7bba40d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/SpineString.h @@ -0,0 +1,218 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_STRING_H +#define SPINE_STRING_H + +#include +#include + +#include +#include + +namespace spine { + class SP_API String : public SpineObject { + public: + String() : _length(0), _buffer(NULL), _tempowner(true) { + } + + String(const char *chars, bool own = false, bool tofree = true) { + _tempowner = tofree; + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + if (!own) { + _buffer = SpineExtension::calloc(_length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, chars, _length + 1); + } else { + _buffer = (char *) chars; + } + } + } + + String(const String &other) { + _tempowner = true; + if (!other._buffer) { + _length = 0; + _buffer = NULL; + } else { + _length = other._length; + _buffer = SpineExtension::calloc(other._length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, other._buffer, other._length + 1); + } + } + + size_t length() const { + return _length; + } + + bool isEmpty() const { + return _length == 0; + } + + const char *buffer() const { + return _buffer; + } + + void own(const String &other) { + if (this == &other) return; + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + _length = other._length; + _buffer = other._buffer; + other._length = 0; + other._buffer = NULL; + } + + void own(const char *chars) { + if (_buffer == chars) return; + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + _buffer = (char *) chars; + } + } + + void unown() { + _length = 0; + _buffer = NULL; + } + + String &operator=(const String &other) { + if (this == &other) return *this; + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + if (!other._buffer) { + _length = 0; + _buffer = NULL; + } else { + _length = other._length; + _buffer = SpineExtension::calloc(other._length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, other._buffer, other._length + 1); + } + return *this; + } + + String &operator=(const char *chars) { + if (_buffer == chars) return *this; + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + _buffer = SpineExtension::calloc(_length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, chars, _length + 1); + } + return *this; + } + + String &append(const char *chars) { + size_t len = strlen(chars); + size_t thisLen = _length; + _length = _length + len; + bool same = chars == _buffer; + _buffer = SpineExtension::realloc(_buffer, _length + 1, __FILE__, __LINE__); + memcpy((void *) (_buffer + thisLen), (void *) (same ? _buffer : chars), len + 1); + return *this; + } + + String &append(const String &other) { + size_t len = other.length(); + size_t thisLen = _length; + _length = _length + len; + bool same = other._buffer == _buffer; + _buffer = SpineExtension::realloc(_buffer, _length + 1, __FILE__, __LINE__); + memcpy((void *) (_buffer + thisLen), (void *) (same ? _buffer : other._buffer), len + 1); + return *this; + } + + String &append(int other) { + char str[100]; + snprintf(str, 100, "%i", other); + append(str); + return *this; + } + + String &append(float other) { + char str[100]; + snprintf(str, 100, "%f", other); + append(str); + return *this; + } + + bool startsWith(const String &needle) { + if (needle.length() > length()) return false; + for (int i = 0; i < (int)needle.length(); i++) { + if (buffer()[i] != needle.buffer()[i]) return false; + } + return true; + } + + friend bool operator==(const String &a, const String &b) { + if (a._buffer == b._buffer) return true; + if (a._length != b._length) return false; + if (a._buffer && b._buffer) { + return strcmp(a._buffer, b._buffer) == 0; + } else { + return false; + } + } + + friend bool operator!=(const String &a, const String &b) { + return !(a == b); + } + + ~String() { + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + } + + private: + mutable size_t _length; + mutable char *_buffer; + mutable bool _tempowner; + }; +} + + +#endif //SPINE_STRING_H diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TextureLoader.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TextureLoader.h new file mode 100644 index 0000000..fc61541 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TextureLoader.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TextureLoader_h +#define Spine_TextureLoader_h + +#include +#include + +namespace spine { + class AtlasPage; + + class SP_API TextureLoader : public SpineObject { + public: + TextureLoader(); + + virtual ~TextureLoader(); + + virtual void load(AtlasPage &page, const String &path) = 0; + + virtual void unload(void *texture) = 0; + }; +} + +#endif /* Spine_TextureLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TextureRegion.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TextureRegion.h new file mode 100644 index 0000000..8766197 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TextureRegion.h @@ -0,0 +1,50 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TextureRegion_h +#define Spine_TextureRegion_h + +#include + +namespace spine { + class SP_API TextureRegion : public SpineObject { + public: + void *rendererObject; + float u, v, u2, v2; + int degrees; + float offsetX, offsetY; + int width, height; + int originalWidth, originalHeight; + + TextureRegion(): rendererObject(NULL), u(0), v(0), u2(0), v2(0), degrees(0), offsetX(0), offsetY(0), width(0), height(0), originalWidth(0), originalHeight(0) {}; + ~TextureRegion() {}; + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Timeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Timeline.h new file mode 100644 index 0000000..f097f9a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Timeline_h +#define Spine_Timeline_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + class Skeleton; + + class Event; + + class SP_API Timeline : public SpineObject { + RTTI_DECL + + public: + Timeline(size_t frameCount, size_t frameEntries); + + virtual ~Timeline(); + + /// Sets the value(s) for the specified time. + /// @param skeleton The skeleton the timeline is being applied to. This provides access to the bones, slots, and other skeleton components the timeline may change. + /// @param lastTime lastTime The time this timeline was last applied. Timelines such as EventTimeline trigger only at specific times rather than every frame. In that case, the timeline triggers everything between lastTime (exclusive) and time (inclusive). + /// @param time The time within the animation. Most timelines find the key before and the key after this time so they can interpolate between the keys. + /// @param pEvents If any events are fired, they are added to this array. Can be NULL to ignore firing events or if the timeline does not fire events. May be NULL. + /// @param alpha alpha 0 applies the current or setup pose value (depending on pose parameter). 1 applies the timeline + /// value. Between 0 and 1 applies a value between the current or setup pose and the timeline value. By adjusting alpha over + /// time, an animation can be mixed in or out. alpha can also be useful to apply animations on top of each other (layered). + /// @param blend Controls how mixing is applied when alpha is than 1. + /// @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions such as DrawOrderTimeline and AttachmentTimeline. + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction) = 0; + + size_t getFrameEntries(); + + size_t getFrameCount(); + + Vector &getFrames(); + + float getDuration(); + + virtual Vector &getPropertyIds(); + + protected: + void setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount); + + Vector _propertyIds; + Vector _frames; + size_t _frameEntries; + }; +} + +#endif /* Spine_Timeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TransformConstraint.h new file mode 100644 index 0000000..93dc472 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraint_h +#define Spine_TransformConstraint_h + +#include + +#include + +namespace spine { + class TransformConstraintData; + + class Skeleton; + + class Bone; + + class SP_API TransformConstraint : public Updatable { + friend class Skeleton; + + friend class TransformConstraintTimeline; + + RTTI_DECL + + public: + TransformConstraint(TransformConstraintData &data, Skeleton &skeleton); + + virtual void update(); + + virtual int getOrder(); + + TransformConstraintData &getData(); + + Vector &getBones(); + + Bone *getTarget(); + + void setTarget(Bone *inValue); + + float getMixRotate(); + + void setMixRotate(float inValue); + + float getMixX(); + + void setMixX(float inValue); + + float getMixY(); + + void setMixY(float inValue); + + float getMixScaleX(); + + void setMixScaleX(float inValue); + + float getMixScaleY(); + + void setMixScaleY(float inValue); + + float getMixShearY(); + + void setMixShearY(float inValue); + + bool isActive(); + + void setActive(bool inValue); + + private: + TransformConstraintData &_data; + Vector _bones; + Bone *_target; + float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY; + bool _active; + + void applyAbsoluteWorld(); + + void applyRelativeWorld(); + + void applyAbsoluteLocal(); + + void applyRelativeLocal(); + }; +} + +#endif /* Spine_TransformConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h new file mode 100644 index 0000000..ad7ce64 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -0,0 +1,128 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraintData_h +#define Spine_TransformConstraintData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SP_API TransformConstraintData : public ConstraintData { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class TransformConstraint; + + friend class Skeleton; + + friend class TransformConstraintTimeline; + + public: + RTTI_DECL + + explicit TransformConstraintData(const String &name); + + Vector &getBones(); + + BoneData *getTarget(); + + void setTarget(BoneData *target); + + float getMixRotate(); + + void setMixRotate(float mixRotate); + + float getMixX(); + + void setMixX(float mixX); + + float getMixY(); + + void setMixY(float mixY); + + float getMixScaleX(); + + void setMixScaleX(float mixScaleX); + + float getMixScaleY(); + + void setMixScaleY(float mixScaleY); + + float getMixShearY(); + + void setMixShearY(float mixShearY); + + float getOffsetRotation(); + + void setOffsetRotation(float offsetRotation); + + float getOffsetX(); + + void setOffsetX(float offsetX); + + float getOffsetY(); + + void setOffsetY(float offsetY); + + float getOffsetScaleX(); + + void setOffsetScaleX(float offsetScaleX); + + float getOffsetScaleY(); + + void setOffsetScaleY(float offsetScaleY); + + float getOffsetShearY(); + + void setOffsetShearY(float offsetShearY); + + bool isRelative(); + + void setRelative(bool isRelative); + + bool isLocal(); + + void setLocal(bool isLocal); + + private: + Vector _bones; + BoneData *_target; + float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY; + float _offsetRotation, _offsetX, _offsetY, _offsetScaleX, _offsetScaleY, _offsetShearY; + bool _relative, _local; + }; +} + +#endif /* Spine_TransformConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h new file mode 100644 index 0000000..18cf9c2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraintTimeline_h +#define Spine_TransformConstraintTimeline_h + +#include + +namespace spine { + + class SP_API TransformConstraintTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TransformConstraintTimeline(size_t frameCount, size_t bezierCount, int transformConstraintIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + void setFrame(size_t frameIndex, float time, float mixRotate, float mixX, float mixY, float mixScaleX, + float mixScaleY, float mixShearY); + + int getTransformConstraintIndex() { return _transformConstraintIndex; } + + void setTransformConstraintIndex(int inValue) { _transformConstraintIndex = inValue; } + + private: + int _transformConstraintIndex; + + static const int ENTRIES = 7; + static const int ROTATE = 1; + static const int X = 2; + static const int Y = 3; + static const int SCALEX = 4; + static const int SCALEY = 5; + static const int SHEARY = 6; + }; +} + +#endif /* Spine_TransformConstraintTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TransformMode.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TransformMode.h new file mode 100644 index 0000000..9b75ccf --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TransformMode.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformMode_h +#define Spine_TransformMode_h + +namespace spine { + enum TransformMode { + TransformMode_Normal = 0, + TransformMode_OnlyTranslation, + TransformMode_NoRotationOrReflection, + TransformMode_NoScale, + TransformMode_NoScaleOrReflection + }; +} + +#endif /* Spine_TransformMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h new file mode 100644 index 0000000..efa9cde --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TranslateTimeline_h +#define Spine_TranslateTimeline_h + +#include + +#include +#include + +namespace spine { + + class SP_API TranslateTimeline : public CurveTimeline2 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~TranslateTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API TranslateXTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~TranslateXTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API TranslateYTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~TranslateYTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; +} + +#endif /* Spine_TranslateTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Triangulator.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Triangulator.h new file mode 100644 index 0000000..d10efd0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Triangulator.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Triangulator_h +#define Spine_Triangulator_h + +#include +#include + +namespace spine { + class SP_API Triangulator : public SpineObject { + public: + ~Triangulator(); + + Vector &triangulate(Vector &vertices); + + Vector* > & + decompose(Vector + &vertices, + Vector &triangles + ); + + private: + Vector* > + _convexPolygons; + Vector* > + _convexPolygonsIndices; + + Vector _indices; + Vector _isConcaveArray; + Vector _triangles; + + Pool > _polygonPool; + Pool > _polygonIndicesPool; + + static bool isConcave(int index, int vertexCount, Vector &vertices, Vector &indices); + + static bool positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y); + + static int winding(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y); + }; +} + +#endif /* Spine_Triangulator_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Updatable.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Updatable.h new file mode 100644 index 0000000..481cac5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Updatable.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Updatable_h +#define Spine_Updatable_h + +#include +#include + +namespace spine { + class SP_API Updatable : public SpineObject { + RTTI_DECL + + public: + Updatable(); + + virtual ~Updatable(); + + virtual void update() = 0; + + virtual bool isActive() = 0; + + virtual void setActive(bool inValue) = 0; + }; +} + +#endif /* Spine_Updatable_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Vector.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Vector.h new file mode 100644 index 0000000..771b597 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Vector.h @@ -0,0 +1,222 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Vector_h +#define Spine_Vector_h + +#include +#include +#include +#include + +namespace spine { + template + class SP_API Vector : public SpineObject { + public: + Vector() : _size(0), _capacity(0), _buffer(NULL) { + } + + Vector(const Vector &inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL) { + if (_capacity > 0) { + _buffer = allocate(_capacity); + for (size_t i = 0; i < _size; ++i) { + construct(_buffer + i, inVector._buffer[i]); + } + } + } + + ~Vector() { + clear(); + deallocate(_buffer); + } + + inline void clear() { + for (size_t i = 0; i < _size; ++i) { + destroy(_buffer + (_size - 1 - i)); + } + + _size = 0; + } + + inline size_t getCapacity() const { + return _capacity; + } + + inline size_t size() const { + return _size; + } + + inline void setSize(size_t newSize, const T &defaultValue) { + assert(newSize >= 0); + size_t oldSize = _size; + _size = newSize; + if (_capacity < newSize) { + _capacity = (int) (_size * 1.75f); + if (_capacity < 8) _capacity = 8; + _buffer = spine::SpineExtension::realloc(_buffer, _capacity, __FILE__, __LINE__); + } + if (oldSize < _size) { + for (size_t i = oldSize; i < _size; i++) { + construct(_buffer + i, defaultValue); + } + } + } + + inline void ensureCapacity(size_t newCapacity = 0) { + if (_capacity >= newCapacity) return; + _capacity = newCapacity; + _buffer = SpineExtension::realloc(_buffer, newCapacity, __FILE__, __LINE__); + } + + inline void add(const T &inValue) { + if (_size == _capacity) { + // inValue might reference an element in this buffer + // When we reallocate, the reference becomes invalid. + // We thus need to create a defensive copy before + // reallocating. + T valueCopy = inValue; + _capacity = (int) (_size * 1.75f); + if (_capacity < 8) _capacity = 8; + _buffer = spine::SpineExtension::realloc(_buffer, _capacity, __FILE__, __LINE__); + construct(_buffer + _size++, valueCopy); + } else { + construct(_buffer + _size++, inValue); + } + } + + inline void addAll(Vector &inValue) { + ensureCapacity(this->size() + inValue.size()); + for (size_t i = 0; i < inValue.size(); i++) { + add(inValue[i]); + } + } + + inline void clearAndAddAll(Vector &inValue) { + this->clear(); + this->addAll(inValue); + } + + inline void removeAt(size_t inIndex) { + assert(inIndex < _size); + + --_size; + + if (inIndex != _size) { + for (size_t i = inIndex; i < _size; ++i) { + T tmp(_buffer[i]); + _buffer[i] = _buffer[i + 1]; + _buffer[i + 1] = tmp; + } + } + + destroy(_buffer + _size); + } + + inline bool contains(const T &inValue) { + for (size_t i = 0; i < _size; ++i) { + if (_buffer[i] == inValue) { + return true; + } + } + + return false; + } + + inline int indexOf(const T &inValue) { + for (size_t i = 0; i < _size; ++i) { + if (_buffer[i] == inValue) { + return (int) i; + } + } + + return -1; + } + + inline T &operator[](size_t inIndex) { + assert(inIndex < _size); + + return _buffer[inIndex]; + } + + inline friend bool operator==(Vector &lhs, Vector &rhs) { + if (lhs.size() != rhs.size()) { + return false; + } + + for (size_t i = 0, n = lhs.size(); i < n; ++i) { + if (lhs[i] != rhs[i]) { + return false; + } + } + + return true; + } + + inline friend bool operator!=(Vector &lhs, Vector &rhs) { + return !(lhs == rhs); + } + + inline T *buffer() { + return _buffer; + } + + private: + size_t _size; + size_t _capacity; + T *_buffer; + + inline T *allocate(size_t n) { + assert(n > 0); + + T *ptr = SpineExtension::calloc(n, __FILE__, __LINE__); + + assert(ptr); + + return ptr; + } + + inline void deallocate(T *buffer) { + if (_buffer) { + SpineExtension::free(buffer, __FILE__, __LINE__); + } + } + + inline void construct(T *buffer, const T &val) { + new(buffer) T(val); + } + + inline void destroy(T *buffer) { + buffer->~T(); + } + + // Vector &operator=(const Vector &inVector) {}; + }; +} + +#endif /* Spine_Vector_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Version.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Version.h new file mode 100644 index 0000000..0bd8729 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Version.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_VERTEXEFFECT_H_ +#define SPINE_VERTEXEFFECT_H_ + +#define SPINE_MAJOR_VERSION 4 +#define SPINE_MINOR_VERSION 1 +#define SPINE_VERSION_STRING "4.1" + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/VertexAttachment.h new file mode 100644 index 0000000..23853cd --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_VertexAttachment_h +#define Spine_VertexAttachment_h + +#include + +#include + +namespace spine { + class Slot; + + /// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices. + class SP_API VertexAttachment : public Attachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class DeformTimeline; + + RTTI_DECL + + public: + explicit VertexAttachment(const String &name); + + virtual ~VertexAttachment(); + + void computeWorldVertices(Slot &slot, float *worldVertices); + + void computeWorldVertices(Slot &slot, Vector &worldVertices); + + /// Transforms local vertices to world coordinates. + /// @param start The index of the first Vertices value to transform. Each vertex has 2 values, x and y. + /// @param count The number of world vertex values to output. Must be less than or equal to WorldVerticesLength - start. + /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + count. + /// @param offset The worldVertices index to begin writing values. + /// @param stride The number of worldVertices entries between the value pairs written. + virtual void computeWorldVertices(Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride = 2); + + virtual void computeWorldVertices(Slot &slot, size_t start, size_t count, Vector &worldVertices, size_t offset, + size_t stride = 2); + + /// Gets a unique ID for this attachment. + int getId(); + + Vector &getBones(); + + Vector &getVertices(); + + size_t getWorldVerticesLength(); + + void setWorldVerticesLength(size_t inValue); + + Attachment * getTimelineAttachment(); + + void setTimelineAttachment(Attachment *attachment); + + void copyTo(VertexAttachment *other); + + protected: + Vector _bones; + Vector _vertices; + size_t _worldVerticesLength; + Attachment *_timelineAttachment; + + private: + const int _id; + + static int getNextID(); + }; +} + +#endif /* Spine_VertexAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Vertices.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Vertices.h new file mode 100644 index 0000000..f182011 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/Vertices.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Vertices_h +#define Spine_Vertices_h + +#include + +namespace spine { + class SP_API Vertices : public SpineObject { + public: + Vector _bones; + Vector _vertices; + }; +} + +#endif /* Spine_Vertices_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/dll.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/dll.h new file mode 100644 index 0000000..09dff90 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/dll.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SHAREDLIB_H +#define SPINE_SHAREDLIB_H + +#ifdef _WIN32 +#define DLLIMPORT __declspec(dllimport) +#define DLLEXPORT __declspec(dllexport) +#else +#ifndef DLLIMPORT +#define DLLIMPORT +#endif +#ifndef DLLEXPORT +#define DLLEXPORT +#endif +#endif + +#ifdef SPINEPLUGIN_API +#define SP_API SPINEPLUGIN_API +#else +#define SP_API +#endif + +#endif /* SPINE_SHAREDLIB_H */ diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/spine.h b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/spine.h new file mode 100644 index 0000000..cc48e5b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/include/spine/spine.h @@ -0,0 +1,110 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SPINE_H_ +#define SPINE_SPINE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Animation.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Animation.cpp new file mode 100644 index 0000000..ba2c704 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Animation.cpp @@ -0,0 +1,107 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include + +#include + +#include + +using namespace spine; + +Animation::Animation(const String &name, Vector &timelines, float duration) : _timelines(timelines), + _timelineIds(), + _duration(duration), + _name(name) { + assert(_name.length() > 0); + for (size_t i = 0; i < timelines.size(); i++) { + Vector propertyIds = timelines[i]->getPropertyIds(); + for (size_t ii = 0; ii < propertyIds.size(); ii++) + _timelineIds.put(propertyIds[ii], true); + } +} + +bool Animation::hasTimeline(Vector &ids) { + for (size_t i = 0; i < ids.size(); i++) { + if (_timelineIds.containsKey(ids[i])) return true; + } + return false; +} + +Animation::~Animation() { + ContainerUtil::cleanUpVectorOfPointers(_timelines); +} + +void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + if (loop && _duration != 0) { + time = MathUtil::fmod(time, _duration); + if (lastTime > 0) { + lastTime = MathUtil::fmod(lastTime, _duration); + } + } + + for (size_t i = 0, n = _timelines.size(); i < n; ++i) { + _timelines[i]->apply(skeleton, lastTime, time, pEvents, alpha, blend, direction); + } +} + +const String &Animation::getName() { + return _name; +} + +Vector &Animation::getTimelines() { + return _timelines; +} + +float Animation::getDuration() { + return _duration; +} + +void Animation::setDuration(float inValue) { + _duration = inValue; +} + +int Animation::search(Vector &frames, float target) { + size_t n = (int) frames.size(); + for (size_t i = 1; i < n; i++) { + if (frames[i] > target) return (int) (i - 1); + } + return (int) (n - 1); +} + +int Animation::search(Vector &frames, float target, int step) { + size_t n = frames.size(); + for (size_t i = step; i < n; i += step) + if (frames[i] > target) return (int) (i - step); + return (int) (n - step); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AnimationState.cpp new file mode 100644 index 0000000..e04afa8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -0,0 +1,1072 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +void dummyOnAnimationEventFunc(AnimationState *state, spine::EventType type, TrackEntry *entry, Event *event = NULL) { + SP_UNUSED(state); + SP_UNUSED(type); + SP_UNUSED(entry); + SP_UNUSED(event); +} + +TrackEntry::TrackEntry() : _animation(NULL), _previous(NULL), _next(NULL), _mixingFrom(NULL), _mixingTo(0), + _trackIndex(0), _loop(false), _holdPrevious(false), _reverse(false), + _shortestRotation(false), + _eventThreshold(0), _attachmentThreshold(0), _drawOrderThreshold(0), _animationStart(0), + _animationEnd(0), _animationLast(0), _nextAnimationLast(0), _delay(0), _trackTime(0), + _trackLast(0), _nextTrackLast(0), _trackEnd(0), _timeScale(1.0f), _alpha(0), _mixTime(0), + _mixDuration(0), _interruptAlpha(0), _totalAlpha(0), _mixBlend(MixBlend_Replace), + _listener(dummyOnAnimationEventFunc), _listenerObject(NULL) { +} + +TrackEntry::~TrackEntry() {} + +int TrackEntry::getTrackIndex() { return _trackIndex; } + +Animation *TrackEntry::getAnimation() { return _animation; } + +TrackEntry *TrackEntry::getPrevious() { return _previous; } + +bool TrackEntry::getLoop() { return _loop; } + +void TrackEntry::setLoop(bool inValue) { _loop = inValue; } + +bool TrackEntry::getHoldPrevious() { return _holdPrevious; } + +void TrackEntry::setHoldPrevious(bool inValue) { _holdPrevious = inValue; } + +bool TrackEntry::getReverse() { return _reverse; } + +void TrackEntry::setReverse(bool inValue) { _reverse = inValue; } + +bool TrackEntry::getShortestRotation() { return _shortestRotation; } + +void TrackEntry::setShortestRotation(bool inValue) { _shortestRotation = inValue; } + +float TrackEntry::getDelay() { return _delay; } + +void TrackEntry::setDelay(float inValue) { _delay = inValue; } + +float TrackEntry::getTrackTime() { return _trackTime; } + +void TrackEntry::setTrackTime(float inValue) { _trackTime = inValue; } + +float TrackEntry::getTrackEnd() { return _trackEnd; } + +void TrackEntry::setTrackEnd(float inValue) { _trackEnd = inValue; } + +float TrackEntry::getAnimationStart() { return _animationStart; } + +void TrackEntry::setAnimationStart(float inValue) { _animationStart = inValue; } + +float TrackEntry::getAnimationEnd() { return _animationEnd; } + +void TrackEntry::setAnimationEnd(float inValue) { _animationEnd = inValue; } + +float TrackEntry::getAnimationLast() { return _animationLast; } + +void TrackEntry::setAnimationLast(float inValue) { + _animationLast = inValue; + _nextAnimationLast = inValue; +} + +float TrackEntry::getAnimationTime() { + if (_loop) { + float duration = _animationEnd - _animationStart; + if (duration == 0) return _animationStart; + return MathUtil::fmod(_trackTime, duration) + _animationStart; + } + + return MathUtil::min(_trackTime + _animationStart, _animationEnd); +} + +float TrackEntry::getTimeScale() { return _timeScale; } + +void TrackEntry::setTimeScale(float inValue) { _timeScale = inValue; } + +float TrackEntry::getAlpha() { return _alpha; } + +void TrackEntry::setAlpha(float inValue) { _alpha = inValue; } + +float TrackEntry::getEventThreshold() { return _eventThreshold; } + +void TrackEntry::setEventThreshold(float inValue) { _eventThreshold = inValue; } + +float TrackEntry::getAttachmentThreshold() { return _attachmentThreshold; } + +void TrackEntry::setAttachmentThreshold(float inValue) { _attachmentThreshold = inValue; } + +float TrackEntry::getDrawOrderThreshold() { return _drawOrderThreshold; } + +void TrackEntry::setDrawOrderThreshold(float inValue) { _drawOrderThreshold = inValue; } + +TrackEntry *TrackEntry::getNext() { return _next; } + +bool TrackEntry::isComplete() { + return _trackTime >= _animationEnd - _animationStart; +} + +float TrackEntry::getMixTime() { return _mixTime; } + +void TrackEntry::setMixTime(float inValue) { _mixTime = inValue; } + +float TrackEntry::getMixDuration() { return _mixDuration; } + +void TrackEntry::setMixDuration(float inValue) { _mixDuration = inValue; } + +TrackEntry *TrackEntry::getMixingFrom() { return _mixingFrom; } + +TrackEntry *TrackEntry::getMixingTo() { return _mixingTo; } + +void TrackEntry::setMixBlend(MixBlend blend) { _mixBlend = blend; } + +MixBlend TrackEntry::getMixBlend() { return _mixBlend; } + +void TrackEntry::resetRotationDirections() { + _timelinesRotation.clear(); +} + +void TrackEntry::setListener(AnimationStateListener inValue) { + _listener = inValue; + _listenerObject = NULL; +} + +void TrackEntry::setListener(AnimationStateListenerObject *inValue) { + _listener = dummyOnAnimationEventFunc; + _listenerObject = inValue; +} + +void TrackEntry::reset() { + _animation = NULL; + _previous = NULL; + _next = NULL; + _mixingFrom = NULL; + _mixingTo = NULL; + + setRendererObject(NULL); + + _timelineMode.clear(); + _timelineHoldMix.clear(); + _timelinesRotation.clear(); + + _listener = dummyOnAnimationEventFunc; + _listenerObject = NULL; +} + +float TrackEntry::getTrackComplete() { + float duration = _animationEnd - _animationStart; + if (duration != 0) { + if (_loop) return duration * (1 + (int) (_trackTime / duration));// Completion of next loop. + if (_trackTime < duration) return duration; // Before duration. + } + return _trackTime;// Next update. +} + +EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry *trackEntry, Event *event) : _type(eventType), + _entry(trackEntry), + _event(event) { +} + +EventQueue *EventQueue::newEventQueue(AnimationState &state) { + return new (__FILE__, __LINE__) EventQueue(state); +} + +EventQueueEntry EventQueue::newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event) { + return EventQueueEntry(eventType, entry, event); +} + +EventQueue::EventQueue(AnimationState &state) : _state(state), + _drainDisabled(false) { +} + +EventQueue::~EventQueue() { +} + +void EventQueue::start(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Start, entry)); + _state._animationsChanged = true; +} + +void EventQueue::interrupt(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Interrupt, entry)); +} + +void EventQueue::end(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_End, entry)); + _state._animationsChanged = true; +} + +void EventQueue::dispose(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Dispose, entry)); +} + +void EventQueue::complete(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Complete, entry)); +} + +void EventQueue::event(TrackEntry *entry, Event *event) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Event, entry, event)); +} + +/// Raises all events in the queue and drains the queue. +void EventQueue::drain() { + if (_drainDisabled) { + return; + } + + _drainDisabled = true; + + AnimationState &state = _state; + + // Don't cache _eventQueueEntries.size() so callbacks can queue their own events (eg, call setAnimation in AnimationState_Complete). + for (size_t i = 0; i < _eventQueueEntries.size(); ++i) { + EventQueueEntry queueEntry = _eventQueueEntries[i]; + TrackEntry *trackEntry = queueEntry._entry; + + switch (queueEntry._type) { + case EventType_Start: + case EventType_Interrupt: + case EventType_Complete: + if (!trackEntry->_listenerObject) trackEntry->_listener(&state, queueEntry._type, trackEntry, NULL); + else + trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + if (!state._listenerObject) state._listener(&state, queueEntry._type, trackEntry, NULL); + else + state._listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + break; + case EventType_End: + if (!trackEntry->_listenerObject) trackEntry->_listener(&state, queueEntry._type, trackEntry, NULL); + else + trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + if (!state._listenerObject) state._listener(&state, queueEntry._type, trackEntry, NULL); + else + state._listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + /* Fall through. */ + case EventType_Dispose: + if (!trackEntry->_listenerObject) trackEntry->_listener(&state, EventType_Dispose, trackEntry, NULL); + else + trackEntry->_listenerObject->callback(&state, EventType_Dispose, trackEntry, NULL); + if (!state._listenerObject) state._listener(&state, EventType_Dispose, trackEntry, NULL); + else + state._listenerObject->callback(&state, EventType_Dispose, trackEntry, NULL); + + if (!_state.getManualTrackEntryDisposal()) _state.disposeTrackEntry(trackEntry); + break; + case EventType_Event: + if (!trackEntry->_listenerObject) + trackEntry->_listener(&state, queueEntry._type, trackEntry, queueEntry._event); + else + trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, queueEntry._event); + if (!state._listenerObject) state._listener(&state, queueEntry._type, trackEntry, queueEntry._event); + else + state._listenerObject->callback(&state, queueEntry._type, trackEntry, queueEntry._event); + break; + } + } + _eventQueueEntries.clear(); + + _drainDisabled = false; +} + +AnimationState::AnimationState(AnimationStateData *data) : _data(data), + _queue(EventQueue::newEventQueue(*this)), + _animationsChanged(false), + _listener(dummyOnAnimationEventFunc), + _listenerObject(NULL), + _unkeyedState(0), + _timeScale(1), + _manualTrackEntryDisposal(false) { +} + +AnimationState::~AnimationState() { + for (size_t i = 0; i < _tracks.size(); i++) { + TrackEntry *entry = _tracks[i]; + if (entry) { + TrackEntry *from = entry->_mixingFrom; + while (from) { + TrackEntry *curr = from; + from = curr->_mixingFrom; + delete curr; + } + TrackEntry *next = entry->_next; + while (next) { + TrackEntry *curr = next; + next = curr->_next; + delete curr; + } + delete entry; + } + } + delete _queue; +} + +void AnimationState::update(float delta) { + delta *= _timeScale; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *currentP = _tracks[i]; + if (currentP == NULL) { + continue; + } + + TrackEntry ¤t = *currentP; + + current._animationLast = current._nextAnimationLast; + current._trackLast = current._nextTrackLast; + + float currentDelta = delta * current._timeScale; + + if (current._delay > 0) { + current._delay -= currentDelta; + if (current._delay > 0) { + continue; + } + currentDelta = -current._delay; + current._delay = 0; + } + + TrackEntry *next = current._next; + if (next != NULL) { + // When the next entry's delay is passed, change to the next entry, preserving leftover time. + float nextTime = current._trackLast - next->_delay; + if (nextTime >= 0) { + next->_delay = 0; + next->_trackTime += + current._timeScale == 0 ? 0 : (nextTime / current._timeScale + delta) * next->_timeScale; + current._trackTime += currentDelta; + setCurrent(i, next, true); + while (next->_mixingFrom != NULL) { + next->_mixTime += delta; + next = next->_mixingFrom; + } + continue; + } + } else if (current._trackLast >= current._trackEnd && current._mixingFrom == NULL) { + // clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. + _tracks[i] = NULL; + + _queue->end(currentP); + clearNext(currentP); + continue; + } + + if (current._mixingFrom != NULL && updateMixingFrom(currentP, delta)) { + // End mixing from entries once all have completed. + TrackEntry *from = current._mixingFrom; + current._mixingFrom = NULL; + if (from != NULL) from->_mixingTo = NULL; + while (from != NULL) { + _queue->end(from); + from = from->_mixingFrom; + } + } + + current._trackTime += currentDelta; + } + + _queue->drain(); +} + +bool AnimationState::apply(Skeleton &skeleton) { + if (_animationsChanged) { + animationsChanged(); + } + + bool applied = false; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *currentP = _tracks[i]; + if (currentP == NULL || currentP->_delay > 0) { + continue; + } + + TrackEntry ¤t = *currentP; + + applied = true; + MixBlend blend = i == 0 ? MixBlend_First : current._mixBlend; + + // apply mixing from entries first. + float mix = current._alpha; + if (current._mixingFrom != NULL) { + mix *= applyMixingFrom(currentP, skeleton, blend); + } else if (current._trackTime >= current._trackEnd && current._next == NULL) { + mix = 0;// Set to setup pose the last time the entry will be applied. + } + + // apply current entry. + float animationLast = current._animationLast, animationTime = current.getAnimationTime(); + float applyTime = animationTime; + Vector *applyEvents = &_events; + if (current._reverse) { + applyTime = current._animation->getDuration() - applyTime; + applyEvents = NULL; + } + size_t timelineCount = current._animation->_timelines.size(); + Vector &timelines = current._animation->_timelines; + if ((i == 0 && mix == 1) || blend == MixBlend_Add) { + for (size_t ii = 0; ii < timelineCount; ++ii) { + Timeline *timeline = timelines[ii]; + if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) + applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, blend, + true); + else + timeline->apply(skeleton, animationLast, applyTime, applyEvents, mix, blend, MixDirection_In); + } + } else { + Vector &timelineMode = current._timelineMode; + + bool shortestRotation = current._shortestRotation; + bool firstFrame = !shortestRotation && current._timelinesRotation.size() != timelines.size() << 1; + if (firstFrame) current._timelinesRotation.setSize(timelines.size() << 1, 0); + Vector &timelinesRotation = current._timelinesRotation; + + for (size_t ii = 0; ii < timelineCount; ++ii) { + Timeline *timeline = timelines[ii]; + assert(timeline); + + MixBlend timelineBlend = timelineMode[ii] == Subsequent ? blend : MixBlend_Setup; + + if (!shortestRotation && timeline->getRTTI().isExactly(RotateTimeline::rtti)) + applyRotateTimeline(static_cast(timeline), skeleton, applyTime, mix, + timelineBlend, timelinesRotation, ii << 1, firstFrame); + else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) + applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, + timelineBlend, true); + else + timeline->apply(skeleton, animationLast, applyTime, applyEvents, mix, timelineBlend, + MixDirection_In); + } + } + + queueEvents(currentP, animationTime); + _events.clear(); + current._nextAnimationLast = animationTime; + current._nextTrackLast = current._trackTime; + } + + int setupState = _unkeyedState + Setup; + Vector &slots = skeleton.getSlots(); + for (int i = 0, n = (int) slots.size(); i < n; i++) { + Slot *slot = slots[i]; + if (slot->getAttachmentState() == setupState) { + const String &attachmentName = slot->getData().getAttachmentName(); + slot->setAttachment(attachmentName.isEmpty() ? NULL : skeleton.getAttachment(slot->getData().getIndex(), attachmentName)); + } + } + _unkeyedState += 2; + + _queue->drain(); + return applied; +} + +void AnimationState::clearTracks() { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) + clearTrack(i); + _tracks.clear(); + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); +} + +void AnimationState::clearTrack(size_t trackIndex) { + if (trackIndex >= _tracks.size()) return; + + TrackEntry *current = _tracks[trackIndex]; + if (current == NULL) return; + + _queue->end(current); + + clearNext(current); + + TrackEntry *entry = current; + while (true) { + TrackEntry *from = entry->_mixingFrom; + if (from == NULL) break; + + _queue->end(from); + entry->_mixingFrom = NULL; + entry->_mixingTo = NULL; + entry = from; + } + + _tracks[current->_trackIndex] = NULL; + + _queue->drain(); +} + +TrackEntry *AnimationState::setAnimation(size_t trackIndex, const String &animationName, bool loop) { + Animation *animation = _data->_skeletonData->findAnimation(animationName); + assert(animation != NULL); + return setAnimation(trackIndex, animation, loop); +} + +TrackEntry *AnimationState::setAnimation(size_t trackIndex, Animation *animation, bool loop) { + assert(animation != NULL); + + bool interrupt = true; + TrackEntry *current = expandToIndex(trackIndex); + if (current != NULL) { + if (current->_nextTrackLast == -1) { + // Don't mix from an entry that was never applied. + _tracks[trackIndex] = current->_mixingFrom; + _queue->interrupt(current); + _queue->end(current); + clearNext(current); + current = current->_mixingFrom; + interrupt = false; + } else { + clearNext(current); + } + } + + TrackEntry *entry = newTrackEntry(trackIndex, animation, loop, current); + setCurrent(trackIndex, entry, interrupt); + _queue->drain(); + + return entry; +} + +TrackEntry *AnimationState::addAnimation(size_t trackIndex, const String &animationName, bool loop, float delay) { + Animation *animation = _data->_skeletonData->findAnimation(animationName); + assert(animation != NULL); + return addAnimation(trackIndex, animation, loop, delay); +} + +TrackEntry *AnimationState::addAnimation(size_t trackIndex, Animation *animation, bool loop, float delay) { + assert(animation != NULL); + + TrackEntry *last = expandToIndex(trackIndex); + if (last != NULL) { + while (last->_next != NULL) + last = last->_next; + } + + TrackEntry *entry = newTrackEntry(trackIndex, animation, loop, last); + + if (last == NULL) { + setCurrent(trackIndex, entry, true); + _queue->drain(); + } else { + last->_next = entry; + entry->_previous = last; + if (delay <= 0) delay += last->getTrackComplete() - entry->_mixDuration; + } + + entry->_delay = delay; + return entry; +} + +TrackEntry *AnimationState::setEmptyAnimation(size_t trackIndex, float mixDuration) { + TrackEntry *entry = setAnimation(trackIndex, AnimationState::getEmptyAnimation(), false); + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; +} + +TrackEntry *AnimationState::addEmptyAnimation(size_t trackIndex, float mixDuration, float delay) { + TrackEntry *entry = addAnimation(trackIndex, AnimationState::getEmptyAnimation(), false, delay); + if (delay <= 0) entry->_delay += entry->_mixDuration - mixDuration; + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; +} + +void AnimationState::setEmptyAnimations(float mixDuration) { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *current = _tracks[i]; + if (current != NULL) { + setEmptyAnimation(i, mixDuration); + } + } + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); +} + +TrackEntry *AnimationState::getCurrent(size_t trackIndex) { + return trackIndex >= _tracks.size() ? NULL : _tracks[trackIndex]; +} + +AnimationStateData *AnimationState::getData() { + return _data; +} + +Vector &AnimationState::getTracks() { + return _tracks; +} + +float AnimationState::getTimeScale() { + return _timeScale; +} + +void AnimationState::setTimeScale(float inValue) { + _timeScale = inValue; +} + +void AnimationState::setListener(AnimationStateListener inValue) { + _listener = inValue; + _listenerObject = NULL; +} + +void AnimationState::setListener(AnimationStateListenerObject *inValue) { + _listener = dummyOnAnimationEventFunc; + _listenerObject = inValue; +} + +void AnimationState::disableQueue() { + _queue->_drainDisabled = true; +} + +void AnimationState::enableQueue() { + _queue->_drainDisabled = false; +} + +void AnimationState::setManualTrackEntryDisposal(bool inValue) { + _manualTrackEntryDisposal = inValue; +} + +bool AnimationState::getManualTrackEntryDisposal() { + return _manualTrackEntryDisposal; +} + +void AnimationState::disposeTrackEntry(TrackEntry *entry) { + entry->reset(); + _trackEntryPool.free(entry); +} + +Animation *AnimationState::getEmptyAnimation() { + static Vector timelines; + static Animation ret(String(""), timelines, 0); + return &ret; +} + +void AnimationState::applyAttachmentTimeline(AttachmentTimeline *attachmentTimeline, Skeleton &skeleton, float time, + MixBlend blend, bool attachments) { + Slot *slot = skeleton.getSlots()[attachmentTimeline->getSlotIndex()]; + if (!slot->getBone().isActive()) return; + + Vector &frames = attachmentTimeline->getFrames(); + if (time < frames[0]) { + if (blend == MixBlend_Setup || blend == MixBlend_First) + setAttachment(skeleton, *slot, slot->getData().getAttachmentName(), attachments); + } else { + setAttachment(skeleton, *slot, attachmentTimeline->getAttachmentNames()[Animation::search(frames, time)], + attachments); + } + + /* If an attachment wasn't set (ie before the first frame or attachments is false), set the setup attachment later.*/ + if (slot->getAttachmentState() <= _unkeyedState) slot->setAttachmentState(_unkeyedState + Setup); +} + + +void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, + MixBlend blend, Vector &timelinesRotation, size_t i, bool firstFrame) { + if (firstFrame) timelinesRotation[i] = 0; + + if (alpha == 1) { + rotateTimeline->apply(skeleton, 0, time, NULL, 1, blend, MixDirection_In); + return; + } + + Bone *bone = skeleton._bones[rotateTimeline->_boneIndex]; + if (!bone->isActive()) return; + Vector &frames = rotateTimeline->_frames; + float r1, r2; + if (time < frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_rotation = bone->_data._rotation; + default: + return; + case MixBlend_First: + r1 = bone->_rotation; + r2 = bone->_data._rotation; + } + } else { + r1 = blend == MixBlend_Setup ? bone->_data._rotation : bone->_rotation; + r2 = bone->_data._rotation + rotateTimeline->getCurveValue(time); + } + + // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. + float total, diff = r2 - r1; + diff -= (16384 - (int) (16384.499999999996 - diff / 360)) * 360; + if (diff == 0) { + total = timelinesRotation[i]; + } else { + float lastTotal, lastDiff; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } else { + lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops. + lastDiff = timelinesRotation[i + 1];// Difference between bones. + } + + bool current = diff > 0, dir = lastTotal >= 0; + // Detect cross at 0 (not 180). + if (MathUtil::sign(lastDiff) != MathUtil::sign(diff) && MathUtil::abs(lastDiff) <= 90) { + // A cross after a 360 rotation is a loop. + if (MathUtil::abs(lastTotal) > 180) lastTotal += 360 * MathUtil::sign(lastTotal); + dir = current; + } + + total = diff + lastTotal - MathUtil::fmod(lastTotal, 360);// Store loops as part of lastTotal. + if (dir != current) { + total += 360 * MathUtil::sign(lastTotal); + } + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + bone->_rotation = r1 + total * alpha; +} + +bool AnimationState::updateMixingFrom(TrackEntry *to, float delta) { + TrackEntry *from = to->_mixingFrom; + if (from == NULL) { + return true; + } + + bool finished = updateMixingFrom(from, delta); + + from->_animationLast = from->_nextAnimationLast; + from->_trackLast = from->_nextTrackLast; + + // Require mixTime > 0 to ensure the mixing from entry was applied at least once. + if (to->_mixTime > 0 && to->_mixTime >= to->_mixDuration) { + // Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). + if (from->_totalAlpha == 0 || to->_mixDuration == 0) { + to->_mixingFrom = from->_mixingFrom; + if (from->_mixingFrom != NULL) from->_mixingFrom->_mixingTo = to; + to->_interruptAlpha = from->_interruptAlpha; + _queue->end(from); + } + return finished; + } + + from->_trackTime += delta * from->_timeScale; + to->_mixTime += delta; + + return false; +} + +float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBlend blend) { + TrackEntry *from = to->_mixingFrom; + if (from->_mixingFrom != NULL) applyMixingFrom(from, skeleton, blend); + + float mix; + if (to->_mixDuration == 0) { + // Single frame mix to undo mixingFrom changes. + mix = 1; + if (blend == MixBlend_First) blend = MixBlend_Setup; + } else { + mix = to->_mixTime / to->_mixDuration; + if (mix > 1) { + mix = 1; + } + if (blend != MixBlend_First) blend = from->_mixBlend; + } + + bool attachments = mix < from->_attachmentThreshold, drawOrder = mix < from->_drawOrderThreshold; + Vector &timelines = from->_animation->_timelines; + size_t timelineCount = timelines.size(); + float alphaHold = from->_alpha * to->_interruptAlpha, alphaMix = alphaHold * (1 - mix); + float animationLast = from->_animationLast, animationTime = from->getAnimationTime(); + float applyTime = animationTime; + Vector *events = NULL; + if (from->_reverse) { + applyTime = from->_animation->_duration - applyTime; + } else { + if (mix < from->_eventThreshold) events = &_events; + } + + if (blend == MixBlend_Add) { + for (size_t i = 0; i < timelineCount; i++) + timelines[i]->apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection_Out); + } else { + Vector &timelineMode = from->_timelineMode; + Vector &timelineHoldMix = from->_timelineHoldMix; + + bool shortestRotation = from->_shortestRotation; + bool firstFrame = !shortestRotation && from->_timelinesRotation.size() != timelines.size() << 1; + if (firstFrame) from->_timelinesRotation.setSize(timelines.size() << 1, 0); + + Vector &timelinesRotation = from->_timelinesRotation; + + from->_totalAlpha = 0; + for (size_t i = 0; i < timelineCount; i++) { + Timeline *timeline = timelines[i]; + MixDirection direction = MixDirection_Out; + MixBlend timelineBlend; + float alpha; + switch (timelineMode[i]) { + case Subsequent: + if (!drawOrder && (timeline->getRTTI().isExactly(DrawOrderTimeline::rtti))) continue; + timelineBlend = blend; + alpha = alphaMix; + break; + case First: + timelineBlend = MixBlend_Setup; + alpha = alphaMix; + break; + case HoldSubsequent: + timelineBlend = blend; + alpha = alphaHold; + break; + case HoldFirst: + timelineBlend = MixBlend_Setup; + alpha = alphaHold; + break; + default: + timelineBlend = MixBlend_Setup; + TrackEntry *holdMix = timelineHoldMix[i]; + alpha = alphaHold * MathUtil::max(0.0f, 1.0f - holdMix->_mixTime / holdMix->_mixDuration); + break; + } + from->_totalAlpha += alpha; + if (!shortestRotation && (timeline->getRTTI().isExactly(RotateTimeline::rtti))) { + applyRotateTimeline((RotateTimeline *) timeline, skeleton, applyTime, alpha, timelineBlend, + timelinesRotation, i << 1, firstFrame); + } else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) { + applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, timelineBlend, + attachments); + } else { + if (drawOrder && timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) && + timelineBlend == MixBlend_Setup) + direction = MixDirection_In; + timeline->apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction); + } + } + } + + if (to->_mixDuration > 0) { + queueEvents(from, animationTime); + } + + _events.clear(); + from->_nextAnimationLast = animationTime; + from->_nextTrackLast = from->_trackTime; + + return mix; +} + +void AnimationState::setAttachment(Skeleton &skeleton, Slot &slot, const String &attachmentName, bool attachments) { + slot.setAttachment( + attachmentName.isEmpty() ? NULL : skeleton.getAttachment(slot.getData().getIndex(), attachmentName)); + if (attachments) slot.setAttachmentState(_unkeyedState + Current); +} + +void AnimationState::queueEvents(TrackEntry *entry, float animationTime) { + float animationStart = entry->_animationStart, animationEnd = entry->_animationEnd; + float duration = animationEnd - animationStart; + float trackLastWrapped = MathUtil::fmod(entry->_trackLast, duration); + + // Queue events before complete. + size_t i = 0, n = _events.size(); + for (; i < n; ++i) { + Event *e = _events[i]; + if (e->_time < trackLastWrapped) break; + if (e->_time > animationEnd) continue;// Discard events outside animation start/end. + _queue->event(entry, e); + } + + // Queue complete if completed a loop iteration or the animation. + bool complete = false; + if (entry->_loop) + complete = duration == 0 || (trackLastWrapped > MathUtil::fmod(entry->_trackTime, duration)); + else + complete = animationTime >= animationEnd && entry->_animationLast < animationEnd; + if (complete) _queue->complete(entry); + + // Queue events after complete. + for (; i < n; ++i) { + Event *e = _events[i]; + if (e->_time < animationStart) continue;// Discard events outside animation start/end. + _queue->event(entry, e); + } +} + +void AnimationState::setCurrent(size_t index, TrackEntry *current, bool interrupt) { + TrackEntry *from = expandToIndex(index); + _tracks[index] = current; + current->_previous = NULL; + + if (from != NULL) { + if (interrupt) _queue->interrupt(from); + + current->_mixingFrom = from; + from->_mixingTo = current; + current->_mixTime = 0; + + // Store interrupted mix percentage. + if (from->_mixingFrom != NULL && from->_mixDuration > 0) { + current->_interruptAlpha *= MathUtil::min(1.0f, from->_mixTime / from->_mixDuration); + } + + from->_timelinesRotation.clear();// Reset rotation for mixing out, in case entry was mixed in. + } + + _queue->start(current);// triggers animationsChanged +} + +TrackEntry *AnimationState::expandToIndex(size_t index) { + if (index < _tracks.size()) return _tracks[index]; + while (index >= _tracks.size()) + _tracks.add(NULL); + return NULL; +} + +TrackEntry *AnimationState::newTrackEntry(size_t trackIndex, Animation *animation, bool loop, TrackEntry *last) { + TrackEntry *entryP = _trackEntryPool.obtain();// Pooling + TrackEntry &entry = *entryP; + + entry._trackIndex = (int) trackIndex; + entry._animation = animation; + entry._loop = loop; + entry._holdPrevious = 0; + + entry._reverse = false; + entry._shortestRotation = false; + + entry._eventThreshold = 0; + entry._attachmentThreshold = 0; + entry._drawOrderThreshold = 0; + + entry._animationStart = 0; + entry._animationEnd = animation->getDuration(); + entry._animationLast = -1; + entry._nextAnimationLast = -1; + + entry._delay = 0; + entry._trackTime = 0; + entry._trackLast = -1; + entry._nextTrackLast = -1;// nextTrackLast == -1 signifies a TrackEntry that wasn't applied yet. + entry._trackEnd = FLT_MAX;// loop ? float.MaxValue : animation.Duration; + entry._timeScale = 1; + + entry._alpha = 1; + entry._mixTime = 0; + entry._mixDuration = (last == NULL) ? 0 : _data->getMix(last->_animation, animation); + entry._interruptAlpha = 1; + entry._totalAlpha = 0; + entry._mixBlend = MixBlend_Replace; + + return entryP; +} + +void AnimationState::clearNext(TrackEntry *entry) { + TrackEntry *next = entry->_next; + while (next != NULL) { + _queue->dispose(next); + next = next->_next; + } + entry->_next = NULL; +} + +void AnimationState::animationsChanged() { + _animationsChanged = false; + + _propertyIDs.clear(); + + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *entry = _tracks[i]; + if (!entry) continue; + + while (entry->_mixingFrom != NULL) + entry = entry->_mixingFrom; + + do { + if (entry->_mixingTo == NULL || entry->_mixBlend != MixBlend_Add) computeHold(entry); + entry = entry->_mixingTo; + } while (entry != NULL); + } +} + +void AnimationState::computeHold(TrackEntry *entry) { + TrackEntry *to = entry->_mixingTo; + Vector &timelines = entry->_animation->_timelines; + size_t timelinesCount = timelines.size(); + Vector &timelineMode = entry->_timelineMode; + timelineMode.setSize(timelinesCount, 0); + Vector &timelineHoldMix = entry->_timelineHoldMix; + timelineHoldMix.setSize(timelinesCount, 0); + + if (to != NULL && to->_holdPrevious) { + for (size_t i = 0; i < timelinesCount; i++) { + timelineMode[i] = _propertyIDs.addAll(timelines[i]->getPropertyIds(), true) ? HoldFirst : HoldSubsequent; + } + return; + } + + // outer: + size_t i = 0; +continue_outer: + for (; i < timelinesCount; ++i) { + Timeline *timeline = timelines[i]; + Vector &ids = timeline->getPropertyIds(); + if (!_propertyIDs.addAll(ids, true)) { + timelineMode[i] = Subsequent; + } else { + if (to == NULL || timeline->getRTTI().isExactly(AttachmentTimeline::rtti) || + timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) || + timeline->getRTTI().isExactly(EventTimeline::rtti) || !to->_animation->hasTimeline(ids)) { + timelineMode[i] = First; + } else { + for (TrackEntry *next = to->_mixingTo; next != NULL; next = next->_mixingTo) { + if (next->_animation->hasTimeline(ids)) continue; + if (next->_mixDuration > 0) { + timelineMode[i] = HoldMix; + timelineHoldMix[i] = next; + i++; + goto continue_outer;// continue outer; + } + break; + } + timelineMode[i] = HoldFirst; + } + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp new file mode 100644 index 0000000..65719a3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +using namespace spine; + +AnimationStateData::AnimationStateData(SkeletonData *skeletonData) : _skeletonData(skeletonData), _defaultMix(0) { +} + +void AnimationStateData::setMix(const String &fromName, const String &toName, float duration) { + Animation *from = _skeletonData->findAnimation(fromName); + Animation *to = _skeletonData->findAnimation(toName); + + setMix(from, to, duration); +} + +void AnimationStateData::setMix(Animation *from, Animation *to, float duration) { + assert(from != NULL); + assert(to != NULL); + + AnimationPair key(from, to); + _animationToMixTime.put(key, duration); +} + +float AnimationStateData::getMix(Animation *from, Animation *to) { + assert(from != NULL); + assert(to != NULL); + + AnimationPair key(from, to); + + if (_animationToMixTime.containsKey(key)) return _animationToMixTime[key]; + return _defaultMix; +} + +SkeletonData *AnimationStateData::getSkeletonData() { + return _skeletonData; +} + +float AnimationStateData::getDefaultMix() { + return _defaultMix; +} + +void AnimationStateData::setDefaultMix(float inValue) { + _defaultMix = inValue; +} + +void AnimationStateData::clear() { + _defaultMix = 0; + _animationToMixTime.clear(); +} + +AnimationStateData::AnimationPair::AnimationPair(Animation *a1, Animation *a2) : _a1(a1), _a2(a2) { +} + +bool AnimationStateData::AnimationPair::operator==(const AnimationPair &other) const { + return _a1->_name == other._a1->_name && _a2->_name == other._a2->_name; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Atlas.cpp new file mode 100644 index 0000000..e1714e2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -0,0 +1,354 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +#include + +using namespace spine; + +Atlas::Atlas(const String &path, TextureLoader *textureLoader, bool createTexture) : _textureLoader(textureLoader) { + int dirLength; + char *dir; + int length; + const char *data; + + /* Get directory from atlas path. */ + const char *lastForwardSlash = strrchr(path.buffer(), '/'); + const char *lastBackwardSlash = strrchr(path.buffer(), '\\'); + const char *lastSlash = lastForwardSlash > lastBackwardSlash ? lastForwardSlash : lastBackwardSlash; + if (lastSlash == path) lastSlash++; /* Never drop starting slash. */ + dirLength = (int) (lastSlash ? lastSlash - path.buffer() : 0); + dir = SpineExtension::calloc(dirLength + 1, __FILE__, __LINE__); + memcpy(dir, path.buffer(), dirLength); + dir[dirLength] = '\0'; + + data = SpineExtension::readFile(path, &length); + if (data) { + load(data, length, dir, createTexture); + } + + SpineExtension::free(data, __FILE__, __LINE__); + SpineExtension::free(dir, __FILE__, __LINE__); +} + +Atlas::Atlas(const char *data, int length, const char *dir, TextureLoader *textureLoader, bool createTexture) + : _textureLoader( + textureLoader) { + load(data, length, dir, createTexture); +} + +Atlas::~Atlas() { + if (_textureLoader) { + for (size_t i = 0, n = _pages.size(); i < n; ++i) { + _textureLoader->unload(_pages[i]->texture); + } + } + ContainerUtil::cleanUpVectorOfPointers(_pages); + ContainerUtil::cleanUpVectorOfPointers(_regions); +} + +void Atlas::flipV() { + for (size_t i = 0, n = _regions.size(); i < n; ++i) { + AtlasRegion *regionP = _regions[i]; + AtlasRegion ®ion = *regionP; + region.v = 1 - region.v; + region.v2 = 1 - region.v2; + } +} + +AtlasRegion *Atlas::findRegion(const String &name) { + for (size_t i = 0, n = _regions.size(); i < n; ++i) + if (_regions[i]->name == name) return _regions[i]; + return NULL; +} + +Vector &Atlas::getPages() { + return _pages; +} + +Vector &Atlas::getRegions() { + return _regions; +} + +struct SimpleString { + char *start; + char *end; + int length; + + SimpleString trim() { + while (isspace((unsigned char) *start) && start < end) + start++; + if (start == end) { + length = (int) (end - start); + return *this; + } + end--; + while (((unsigned char) *end == '\r') && end >= start) + end--; + end++; + length = (int) (end - start); + return *this; + } + + int indexOf(char needle) { + char *c = start; + while (c < end) { + if (*c == needle) return (int) (c - start); + c++; + } + return -1; + } + + int indexOf(char needle, int at) { + char *c = start + at; + while (c < end) { + if (*c == needle) return (int) (c - start); + c++; + } + return -1; + } + + SimpleString substr(int s, int e) { + e = s + e; + SimpleString result; + result.start = start + s; + result.end = start + e; + result.length = e - s; + return result; + } + + SimpleString substr(int s) { + SimpleString result; + result.start = start + s; + result.end = end; + result.length = (int) (result.end - result.start); + return result; + } + + bool equals(const char *str) { + int otherLen = (int) strlen(str); + if (length != otherLen) return false; + for (int i = 0; i < length; i++) { + if (start[i] != str[i]) return false; + } + return true; + } + + char *copy() { + char *string = SpineExtension::calloc(length + 1, __FILE__, __LINE__); + memcpy(string, start, length); + string[length] = '\0'; + return string; + } + + int toInt() { + return (int) strtol(start, &end, 10); + } +}; + +struct AtlasInput { + const char *start; + const char *end; + char *index; + int length; + SimpleString line; + + AtlasInput(const char *data, int length) : start(data), end(data + length), index((char *) data), length(length) {} + + SimpleString *readLine() { + if (index >= end) return 0; + line.start = index; + while (index < end && *index != '\n') + index++; + line.end = index; + if (index != end) index++; + line = line.trim(); + line.length = end - start; + return &line; + } + + static int readEntry(SimpleString entry[5], SimpleString *line) { + if (line == NULL) return 0; + line->trim(); + if (line->length == 0) return 0; + + int colon = line->indexOf(':'); + if (colon == -1) return 0; + entry[0] = line->substr(0, colon).trim(); + for (int i = 1, lastMatch = colon + 1;; i++) { + int comma = line->indexOf(',', lastMatch); + if (comma == -1) { + entry[i] = line->substr(lastMatch).trim(); + return i; + } + entry[i] = line->substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + if (i == 4) return 4; + } + } +}; + +int indexOf(const char **array, int count, SimpleString *str) { + for (int i = 0; i < count; i++) + if (str->equals(array[i])) return i; + return 0; +} + +void Atlas::load(const char *begin, int length, const char *dir, bool createTexture) { + static const char *formatNames[] = {"", "Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888", + "RGBA8888"}; + static const char *textureFilterNames[] = {"", "Nearest", "Linear", "MipMap", "MipMapNearestNearest", + "MipMapLinearNearest", + "MipMapNearestLinear", "MipMapLinearLinear"}; + + int dirLength = (int) strlen(dir); + int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\'; + AtlasInput reader(begin, length); + SimpleString entry[5]; + AtlasPage *page = NULL; + + SimpleString *line = reader.readLine(); + while (line != NULL && line->length == 0) + line = reader.readLine(); + + while (true) { + if (line == NULL || line->length == 0) break; + if (reader.readEntry(entry, line) == 0) break; + line = reader.readLine(); + } + + while (true) { + if (line == NULL) break; + if (line->trim().length == 0) { + page = NULL; + line = reader.readLine(); + } else if (page == NULL) { + char *name = line->copy(); + char *path = SpineExtension::calloc(dirLength + needsSlash + strlen(name) + 1, __FILE__, __LINE__); + memcpy(path, dir, dirLength); + if (needsSlash) path[dirLength] = '/'; + strcpy(path + dirLength + needsSlash, name); + page = new (__FILE__, __LINE__) AtlasPage(String(name, true)); + + while (true) { + line = reader.readLine(); + if (reader.readEntry(entry, line) == 0) break; + if (entry[0].equals("size")) { + page->width = entry[1].toInt(); + page->height = entry[2].toInt(); + } else if (entry[0].equals("format")) { + page->format = (Format) indexOf(formatNames, 8, &entry[1]); + } else if (entry[0].equals("filter")) { + page->minFilter = (TEXTURE_FILTER_ENUM) indexOf(textureFilterNames, 8, &entry[1]); + page->magFilter = (TEXTURE_FILTER_ENUM) indexOf(textureFilterNames, 8, &entry[2]); + } else if (entry[0].equals("repeat")) { + page->uWrap = TextureWrap_ClampToEdge; + page->vWrap = TextureWrap_ClampToEdge; + if (entry[1].indexOf('x') != -1) page->uWrap = TextureWrap_Repeat; + if (entry[1].indexOf('y') != -1) page->vWrap = TextureWrap_Repeat; + } else if (entry[0].equals("pma")) { + page->pma = entry[1].equals("true"); + } + } + + if (createTexture) { + if (_textureLoader) _textureLoader->load(*page, String(path)); + SpineExtension::free(path, __FILE__, __LINE__); + } else { + page->texturePath = String(path, true); + } + page->index = (int) _pages.size(); + _pages.add(page); + } else { + AtlasRegion *region = new (__FILE__, __LINE__) AtlasRegion(); + region->page = page; + region->rendererObject = page->texture; + region->name = String(line->copy(), true); + while (true) { + line = reader.readLine(); + int count = reader.readEntry(entry, line); + if (count == 0) break; + if (entry[0].equals("xy")) { + region->x = entry[1].toInt(); + region->y = entry[2].toInt(); + } else if (entry[0].equals("size")) { + region->width = entry[1].toInt(); + region->height = entry[2].toInt(); + } else if (entry[0].equals("bounds")) { + region->x = entry[1].toInt(); + region->y = entry[2].toInt(); + region->width = entry[3].toInt(); + region->height = entry[4].toInt(); + } else if (entry[0].equals("offset")) { + region->offsetX = entry[1].toInt(); + region->offsetY = entry[2].toInt(); + } else if (entry[0].equals("orig")) { + region->originalWidth = entry[1].toInt(); + region->originalHeight = entry[2].toInt(); + } else if (entry[0].equals("offsets")) { + region->offsetX = entry[1].toInt(); + region->offsetY = entry[2].toInt(); + region->originalWidth = entry[3].toInt(); + region->originalHeight = entry[4].toInt(); + } else if (entry[0].equals("rotate")) { + if (entry[1].equals("true")) { + region->degrees = 90; + } else if (!entry[1].equals("false")) { + region->degrees = entry[1].toInt(); + } + } else if (entry[0].equals("index")) { + region->index = entry[1].toInt(); + } else { + region->names.add(String(entry[0].copy())); + for (int i = 0; i < count; i++) { + region->values.add(entry[i + 1].toInt()); + } + } + } + if (region->originalWidth == 0 && region->originalHeight == 0) { + region->originalWidth = region->width; + region->originalHeight = region->height; + } + + region->u = (float) region->x / page->width; + region->v = (float) region->y / page->height; + if (region->degrees == 90) { + region->u2 = (float) (region->x + region->height) / page->width; + region->v2 = (float) (region->y + region->width) / page->height; + } else { + region->u2 = (float) (region->x + region->width) / page->width; + region->v2 = (float) (region->y + region->height) / page->height; + } + _regions.add(region); + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp new file mode 100644 index 0000000..16cde69 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp @@ -0,0 +1,113 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace spine { + RTTI_IMPL(AtlasAttachmentLoader, AttachmentLoader) + + AtlasAttachmentLoader::AtlasAttachmentLoader(Atlas *atlas) : AttachmentLoader(), _atlas(atlas) { + } + + bool loadSequence(Atlas *atlas, const String &basePath, Sequence *sequence) { + Vector ®ions = sequence->getRegions(); + for (int i = 0, n = (int) regions.size(); i < n; i++) { + String path = sequence->getPath(basePath, i); + regions[i] = atlas->findRegion(path); + if (!regions[i]) return false; + regions[i]->rendererObject = regions[i]; + } + return true; + } + + RegionAttachment *AtlasAttachmentLoader::newRegionAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) { + SP_UNUSED(skin); + RegionAttachment *attachment = new (__FILE__, __LINE__) RegionAttachment(name); + if (sequence) { + if (!loadSequence(_atlas, path, sequence)) return NULL; + } else { + AtlasRegion *region = findRegion(path); + if (!region) return NULL; + attachment->setRegion(region); + } + return attachment; + } + + MeshAttachment *AtlasAttachmentLoader::newMeshAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) { + SP_UNUSED(skin); + MeshAttachment *attachment = new (__FILE__, __LINE__) MeshAttachment(name); + + if (sequence) { + if (!loadSequence(_atlas, path, sequence)) return NULL; + } else { + AtlasRegion *region = findRegion(path); + if (!region) return NULL; + attachment->setRegion(region); + } + return attachment; + } + + BoundingBoxAttachment *AtlasAttachmentLoader::newBoundingBoxAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new (__FILE__, __LINE__) BoundingBoxAttachment(name); + } + + PathAttachment *AtlasAttachmentLoader::newPathAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new (__FILE__, __LINE__) PathAttachment(name); + } + + PointAttachment *AtlasAttachmentLoader::newPointAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new (__FILE__, __LINE__) PointAttachment(name); + } + + ClippingAttachment *AtlasAttachmentLoader::newClippingAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new (__FILE__, __LINE__) ClippingAttachment(name); + } + + void AtlasAttachmentLoader::configureAttachment(Attachment *attachment) { + SP_UNUSED(attachment); + } + + AtlasRegion *AtlasAttachmentLoader::findRegion(const String &name) { + return _atlas->findRegion(name); + } + +}// namespace spine diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Attachment.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Attachment.cpp new file mode 100644 index 0000000..9c2fe3e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Attachment.cpp @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(Attachment) + +Attachment::Attachment(const String &name) : _name(name), _refCount(0) { + assert(_name.length() > 0); +} + +Attachment::~Attachment() { +} + +const String &Attachment::getName() const { + return _name; +} + +int Attachment::getRefCount() { + return _refCount; +} + +void Attachment::reference() { + _refCount++; +} + +void Attachment::dereference() { + _refCount--; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp new file mode 100644 index 0000000..2dc2a09 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp @@ -0,0 +1,48 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(AttachmentLoader) + +AttachmentLoader::AttachmentLoader() { +} + +AttachmentLoader::~AttachmentLoader() { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp new file mode 100644 index 0000000..604b74d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(AttachmentTimeline, Timeline) + +AttachmentTimeline::AttachmentTimeline(size_t frameCount, int slotIndex) : Timeline(frameCount, 1), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Attachment << 32) | slotIndex}; + setPropertyIds(ids, 1); + + _attachmentNames.ensureCapacity(frameCount); + for (size_t i = 0; i < frameCount; ++i) { + _attachmentNames.add(String()); + } +} + +AttachmentTimeline::~AttachmentTimeline() {} + +void AttachmentTimeline::setAttachment(Skeleton &skeleton, Slot &slot, String *attachmentName) { + slot.setAttachment(attachmentName == NULL || attachmentName->isEmpty() ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName)); +} + +void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(alpha); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (direction == MixDirection_Out) { + if (blend == MixBlend_Setup) setAttachment(skeleton, *slot, &slot->_data._attachmentName); + return; + } + + if (time < _frames[0]) { + // Time is before first frame. + if (blend == MixBlend_Setup || blend == MixBlend_First) { + setAttachment(skeleton, *slot, &slot->_data._attachmentName); + } + return; + } + + if (time < _frames[0]) { + if (blend == MixBlend_Setup || blend == MixBlend_First) + setAttachment(skeleton, *slot, &slot->_data._attachmentName); + return; + } + + setAttachment(skeleton, *slot, &_attachmentNames[Animation::search(_frames, time)]); +} + +void AttachmentTimeline::setFrame(int frame, float time, const String &attachmentName) { + _frames[frame] = time; + _attachmentNames[frame] = attachmentName; +} + +Vector &AttachmentTimeline::getAttachmentNames() { + return _attachmentNames; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Bone.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Bone.cpp new file mode 100644 index 0000000..cfbe466 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -0,0 +1,576 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL(Bone, Updatable) + +bool Bone::yDown = false; + +void Bone::setYDown(bool inValue) { + yDown = inValue; +} + +bool Bone::isYDown() { + return yDown; +} + +Bone::Bone(BoneData &data, Skeleton &skeleton, Bone *parent) : Updatable(), + _data(data), + _skeleton(skeleton), + _parent(parent), + _x(0), + _y(0), + _rotation(0), + _scaleX(0), + _scaleY(0), + _shearX(0), + _shearY(0), + _ax(0), + _ay(0), + _arotation(0), + _ascaleX(0), + _ascaleY(0), + _ashearX(0), + _ashearY(0), + _a(1), + _b(0), + _worldX(0), + _c(0), + _d(1), + _worldY(0), + _sorted(false), + _active(false) { + setToSetupPose(); +} + +void Bone::update() { + updateWorldTransform(_ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY); +} + +void Bone::updateWorldTransform() { + updateWorldTransform(_x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY); +} + +void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { + float cosine, sine; + float pa, pb, pc, pd; + Bone *parent = _parent; + + _ax = x; + _ay = y; + _arotation = rotation; + _ascaleX = scaleX; + _ascaleY = scaleY; + _ashearX = shearX; + _ashearY = shearY; + + if (!parent) { /* Root bone. */ + float rotationY = rotation + 90 + shearY; + float sx = _skeleton.getScaleX(); + float sy = _skeleton.getScaleY(); + _a = MathUtil::cosDeg(rotation + shearX) * scaleX * sx; + _b = MathUtil::cosDeg(rotationY) * scaleY * sx; + _c = MathUtil::sinDeg(rotation + shearX) * scaleX * sy; + _d = MathUtil::sinDeg(rotationY) * scaleY * sy; + _worldX = x * sx + _skeleton.getX(); + _worldY = y * sy + _skeleton.getY(); + return; + } + + pa = parent->_a; + pb = parent->_b; + pc = parent->_c; + pd = parent->_d; + + _worldX = pa * x + pb * y + parent->_worldX; + _worldY = pc * x + pd * y + parent->_worldY; + + switch (_data.getTransformMode()) { + case TransformMode_Normal: { + float rotationY = rotation + 90 + shearY; + float la = MathUtil::cosDeg(rotation + shearX) * scaleX; + float lb = MathUtil::cosDeg(rotationY) * scaleY; + float lc = MathUtil::sinDeg(rotation + shearX) * scaleX; + float ld = MathUtil::sinDeg(rotationY) * scaleY; + _a = pa * la + pb * lc; + _b = pa * lb + pb * ld; + _c = pc * la + pd * lc; + _d = pc * lb + pd * ld; + return; + } + case TransformMode_OnlyTranslation: { + float rotationY = rotation + 90 + shearY; + _a = MathUtil::cosDeg(rotation + shearX) * scaleX; + _b = MathUtil::cosDeg(rotationY) * scaleY; + _c = MathUtil::sinDeg(rotation + shearX) * scaleX; + _d = MathUtil::sinDeg(rotationY) * scaleY; + break; + } + case TransformMode_NoRotationOrReflection: { + float s = pa * pa + pc * pc; + float prx, rx, ry, la, lb, lc, ld; + if (s > 0.0001f) { + s = MathUtil::abs(pa * pd - pb * pc) / s; + pa /= _skeleton.getScaleX(); + pc /= _skeleton.getScaleY(); + pb = pc * s; + pd = pa * s; + prx = MathUtil::atan2(pc, pa) * MathUtil::Rad_Deg; + } else { + pa = 0; + pc = 0; + prx = 90 - MathUtil::atan2(pd, pb) * MathUtil::Rad_Deg; + } + rx = rotation + shearX - prx; + ry = rotation + shearY - prx + 90; + la = MathUtil::cosDeg(rx) * scaleX; + lb = MathUtil::cosDeg(ry) * scaleY; + lc = MathUtil::sinDeg(rx) * scaleX; + ld = MathUtil::sinDeg(ry) * scaleY; + _a = pa * la - pb * lc; + _b = pa * lb - pb * ld; + _c = pc * la + pd * lc; + _d = pc * lb + pd * ld; + break; + } + case TransformMode_NoScale: + case TransformMode_NoScaleOrReflection: { + float za, zc, s; + float r, zb, zd, la, lb, lc, ld; + cosine = MathUtil::cosDeg(rotation); + sine = MathUtil::sinDeg(rotation); + za = (pa * cosine + pb * sine) / _skeleton.getScaleX(); + zc = (pc * cosine + pd * sine) / _skeleton.getScaleY(); + s = MathUtil::sqrt(za * za + zc * zc); + if (s > 0.00001f) s = 1 / s; + za *= s; + zc *= s; + s = MathUtil::sqrt(za * za + zc * zc); + if (_data.getTransformMode() == TransformMode_NoScale && + (pa * pd - pb * pc < 0) != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0)) + s = -s; + r = MathUtil::Pi / 2 + MathUtil::atan2(zc, za); + zb = MathUtil::cos(r) * s; + zd = MathUtil::sin(r) * s; + la = MathUtil::cosDeg(shearX) * scaleX; + lb = MathUtil::cosDeg(90 + shearY) * scaleY; + lc = MathUtil::sinDeg(shearX) * scaleX; + ld = MathUtil::sinDeg(90 + shearY) * scaleY; + _a = za * la + zb * lc; + _b = za * lb + zb * ld; + _c = zc * la + zd * lc; + _d = zc * lb + zd * ld; + } + } + _a *= _skeleton.getScaleX(); + _b *= _skeleton.getScaleX(); + _c *= _skeleton.getScaleY(); + _d *= _skeleton.getScaleY(); +} + +void Bone::setToSetupPose() { + BoneData &data = _data; + _x = data.getX(); + _y = data.getY(); + _rotation = data.getRotation(); + _scaleX = data.getScaleX(); + _scaleY = data.getScaleY(); + _shearX = data.getShearX(); + _shearY = data.getShearY(); +} + +void Bone::worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY) { + float a = _a; + float b = _b; + float c = _c; + float d = _d; + + float invDet = 1 / (a * d - b * c); + float x = worldX - _worldX; + float y = worldY - _worldY; + + outLocalX = (x * d * invDet - y * b * invDet); + outLocalY = (y * a * invDet - x * c * invDet); +} + +void Bone::localToWorld(float localX, float localY, float &outWorldX, float &outWorldY) { + outWorldX = localX * _a + localY * _b + _worldX; + outWorldY = localX * _c + localY * _d + _worldY; +} + +float Bone::worldToLocalRotation(float worldRotation) { + float sin = MathUtil::sinDeg(worldRotation); + float cos = MathUtil::cosDeg(worldRotation); + + return MathUtil::atan2(_a * sin - _c * cos, _d * cos - _b * sin) * MathUtil::Rad_Deg + this->_rotation - + this->_shearX; +} + +float Bone::localToWorldRotation(float localRotation) { + localRotation -= this->_rotation - this->_shearX; + float sin = MathUtil::sinDeg(localRotation); + float cos = MathUtil::cosDeg(localRotation); + + return MathUtil::atan2(cos * _c + sin * _d, cos * _a + sin * _b) * MathUtil::Rad_Deg; +} + +void Bone::rotateWorld(float degrees) { + float a = _a; + float b = _b; + float c = _c; + float d = _d; + + float cos = MathUtil::cosDeg(degrees); + float sin = MathUtil::sinDeg(degrees); + + _a = cos * a - sin * c; + _b = cos * b - sin * d; + _c = sin * a + cos * c; + _d = sin * b + cos * d; +} + +float Bone::getWorldToLocalRotationX() { + Bone *parent = _parent; + if (!parent) { + return _arotation; + } + + float pa = parent->_a; + float pb = parent->_b; + float pc = parent->_c; + float pd = parent->_d; + float a = _a; + float c = _c; + + return MathUtil::atan2(pa * c - pc * a, pd * a - pb * c) * MathUtil::Rad_Deg; +} + +float Bone::getWorldToLocalRotationY() { + Bone *parent = _parent; + if (!parent) { + return _arotation; + } + + float pa = parent->_a; + float pb = parent->_b; + float pc = parent->_c; + float pd = parent->_d; + float b = _b; + float d = _d; + + return MathUtil::atan2(pa * d - pc * b, pd * b - pb * d) * MathUtil::Rad_Deg; +} + +BoneData &Bone::getData() { + return _data; +} + +Skeleton &Bone::getSkeleton() { + return _skeleton; +} + +Bone *Bone::getParent() { + return _parent; +} + +Vector &Bone::getChildren() { + return _children; +} + +float Bone::getX() { + return _x; +} + +void Bone::setX(float inValue) { + _x = inValue; +} + +float Bone::getY() { + return _y; +} + +void Bone::setY(float inValue) { + _y = inValue; +} + +float Bone::getRotation() { + return _rotation; +} + +void Bone::setRotation(float inValue) { + _rotation = inValue; +} + +float Bone::getScaleX() { + return _scaleX; +} + +void Bone::setScaleX(float inValue) { + _scaleX = inValue; +} + +float Bone::getScaleY() { + return _scaleY; +} + +void Bone::setScaleY(float inValue) { + _scaleY = inValue; +} + +float Bone::getShearX() { + return _shearX; +} + +void Bone::setShearX(float inValue) { + _shearX = inValue; +} + +float Bone::getShearY() { + return _shearY; +} + +void Bone::setShearY(float inValue) { + _shearY = inValue; +} + +float Bone::getAppliedRotation() { + return _arotation; +} + +void Bone::setAppliedRotation(float inValue) { + _arotation = inValue; +} + +float Bone::getAX() { + return _ax; +} + +void Bone::setAX(float inValue) { + _ax = inValue; +} + +float Bone::getAY() { + return _ay; +} + +void Bone::setAY(float inValue) { + _ay = inValue; +} + +float Bone::getAScaleX() { + return _ascaleX; +} + +void Bone::setAScaleX(float inValue) { + _ascaleX = inValue; +} + +float Bone::getAScaleY() { + return _ascaleY; +} + +void Bone::setAScaleY(float inValue) { + _ascaleY = inValue; +} + +float Bone::getAShearX() { + return _ashearX; +} + +void Bone::setAShearX(float inValue) { + _ashearX = inValue; +} + +float Bone::getAShearY() { + return _ashearY; +} + +void Bone::setAShearY(float inValue) { + _ashearY = inValue; +} + +float Bone::getA() { + return _a; +} + +void Bone::setA(float inValue) { + _a = inValue; +} + +float Bone::getB() { + return _b; +} + +void Bone::setB(float inValue) { + _b = inValue; +} + +float Bone::getC() { + return _c; +} + +void Bone::setC(float inValue) { + _c = inValue; +} + +float Bone::getD() { + return _d; +} + +void Bone::setD(float inValue) { + _d = inValue; +} + +float Bone::getWorldX() { + return _worldX; +} + +void Bone::setWorldX(float inValue) { + _worldX = inValue; +} + +float Bone::getWorldY() { + return _worldY; +} + +void Bone::setWorldY(float inValue) { + _worldY = inValue; +} + +float Bone::getWorldRotationX() { + return MathUtil::atan2(_c, _a) * MathUtil::Rad_Deg; +} + +float Bone::getWorldRotationY() { + return MathUtil::atan2(_d, _b) * MathUtil::Rad_Deg; +} + +float Bone::getWorldScaleX() { + return MathUtil::sqrt(_a * _a + _c * _c); +} + +float Bone::getWorldScaleY() { + return MathUtil::sqrt(_b * _b + _d * _d); +} + +void Bone::updateAppliedTransform() { + Bone *parent = _parent; + if (!parent) { + _ax = _worldX - _skeleton.getX(); + _ay = _worldY - _skeleton.getY(); + _arotation = MathUtil::atan2(_c, _a) * MathUtil::Rad_Deg; + _ascaleX = MathUtil::sqrt(_a * _a + _c * _c); + _ascaleY = MathUtil::sqrt(_b * _b + _d * _d); + _ashearX = 0; + _ashearY = MathUtil::atan2(_a * _b + _c * _d, _a * _d - _b * _c) * MathUtil::Rad_Deg; + } + float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d; + float pid = 1 / (pa * pd - pb * pc); + float ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid; + float dx = _worldX - parent->_worldX, dy = _worldY - parent->_worldY; + _ax = (dx * ia - dy * ib); + _ay = (dy * id - dx * ic); + + float ra, rb, rc, rd; + if (_data.getTransformMode() == TransformMode_OnlyTranslation) { + ra = _a; + rb = _b; + rc = _c; + rd = _d; + } else { + switch (_data.getTransformMode()) { + case TransformMode_NoRotationOrReflection: { + float s = MathUtil::abs(pa * pd - pb * pc) / (pa * pa + pc * pc); + float sa = pa / _skeleton.getScaleX(); + float sc = pc / _skeleton.getScaleY(); + pb = -sc * s * _skeleton.getScaleX(); + pd = sa * s * _skeleton.getScaleY(); + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + break; + } + case TransformMode_NoScale: + case TransformMode_NoScaleOrReflection: { + float cos = MathUtil::cosDeg(_rotation), sin = MathUtil::sinDeg(_rotation); + pa = (pa * cos + pb * sin) / _skeleton.getScaleX(); + pc = (pc * cos + pd * sin) / _skeleton.getScaleY(); + float s = MathUtil::sqrt(pa * pa + pc * pc); + if (s > 0.00001f) s = 1 / s; + pa *= s; + pc *= s; + s = MathUtil::sqrt(pa * pa + pc * pc); + if (_data.getTransformMode() == TransformMode_NoScale && pid < 0 != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0)) s = -s; + float r = MathUtil::Pi / 2 + MathUtil::atan2(pc, pa); + pb = MathUtil::cos(r) * s; + pd = MathUtil::sin(r) * s; + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + ic = pc * pid; + id = pa * pid; + break; + } + default: + break; + } + ra = ia * _a - ib * _c; + rb = ia * _b - ib * _d; + rc = id * _c - ic * _a; + rd = id * _d - ic * _b; + } + + _ashearX = 0; + _ascaleX = MathUtil::sqrt(ra * ra + rc * rc); + if (_ascaleX > 0.0001f) { + float det = ra * rd - rb * rc; + _ascaleY = det / _ascaleX; + _ashearY = -MathUtil::atan2(ra * rb + rc * rd, det) * MathUtil::Rad_Deg; + _arotation = MathUtil::atan2(rc, ra) * MathUtil::Rad_Deg; + } else { + _ascaleX = 0; + _ascaleY = MathUtil::sqrt(rb * rb + rd * rd); + _ashearY = 0; + _arotation = 90 - MathUtil::atan2(rd, rb) * MathUtil::Rad_Deg; + } +} + +bool Bone::isActive() { + return _active; +} + +void Bone::setActive(bool inValue) { + _active = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/BoneData.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/BoneData.cpp new file mode 100644 index 0000000..87aca70 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/BoneData.cpp @@ -0,0 +1,148 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +BoneData::BoneData(int index, const String &name, BoneData *parent) : _index(index), + _name(name), + _parent(parent), + _length(0), + _x(0), + _y(0), + _rotation(0), + _scaleX(1), + _scaleY(1), + _shearX(0), + _shearY(0), + _transformMode(TransformMode_Normal), + _skinRequired(false), + _color() { + assert(index >= 0); + assert(_name.length() > 0); +} + +int BoneData::getIndex() { + return _index; +} + +const String &BoneData::getName() { + return _name; +} + +BoneData *BoneData::getParent() { + return _parent; +} + +float BoneData::getLength() { + return _length; +} + +void BoneData::setLength(float inValue) { + _length = inValue; +} + +float BoneData::getX() { + return _x; +} + +void BoneData::setX(float inValue) { + _x = inValue; +} + +float BoneData::getY() { + return _y; +} + +void BoneData::setY(float inValue) { + _y = inValue; +} + +float BoneData::getRotation() { + return _rotation; +} + +void BoneData::setRotation(float inValue) { + _rotation = inValue; +} + +float BoneData::getScaleX() { + return _scaleX; +} + +void BoneData::setScaleX(float inValue) { + _scaleX = inValue; +} + +float BoneData::getScaleY() { + return _scaleY; +} + +void BoneData::setScaleY(float inValue) { + _scaleY = inValue; +} + +float BoneData::getShearX() { + return _shearX; +} + +void BoneData::setShearX(float inValue) { + _shearX = inValue; +} + +float BoneData::getShearY() { + return _shearY; +} + +void BoneData::setShearY(float inValue) { + _shearY = inValue; +} + +TransformMode BoneData::getTransformMode() { + return _transformMode; +} + +void BoneData::setTransformMode(TransformMode inValue) { + _transformMode = inValue; +} + +bool BoneData::isSkinRequired() { + return _skinRequired; +} + +void BoneData::setSkinRequired(bool inValue) { + _skinRequired = inValue; +} + +Color &BoneData::getColor() { + return _color; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp new file mode 100644 index 0000000..758113c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp @@ -0,0 +1,47 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL(BoundingBoxAttachment, VertexAttachment) + +BoundingBoxAttachment::BoundingBoxAttachment(const String &name) : VertexAttachment(name), _color() { +} + +Color &BoundingBoxAttachment::getColor() { + return _color; +} + +Attachment *BoundingBoxAttachment::copy() { + BoundingBoxAttachment *copy = new (__FILE__, __LINE__) BoundingBoxAttachment(getName()); + copyTo(copy); + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp new file mode 100644 index 0000000..fa9e65c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp @@ -0,0 +1,58 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +RTTI_IMPL(ClippingAttachment, VertexAttachment) + +ClippingAttachment::ClippingAttachment(const String &name) : VertexAttachment(name), _endSlot(NULL), _color() { +} + +SlotData *ClippingAttachment::getEndSlot() { + return _endSlot; +} + +void ClippingAttachment::setEndSlot(SlotData *inValue) { + _endSlot = inValue; +} + +Color &ClippingAttachment::getColor() { + return _color; +} + +Attachment *ClippingAttachment::copy() { + ClippingAttachment *copy = new (__FILE__, __LINE__) ClippingAttachment(getName()); + copyTo(copy); + copy->_endSlot = _endSlot; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp new file mode 100644 index 0000000..f804c56 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -0,0 +1,493 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(RGBATimeline, CurveTimeline) + +RGBATimeline::RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount, + RGBATimeline::ENTRIES, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, + ((PropertyId) Property_Alpha << 32) | slotIndex}; + setPropertyIds(ids, 2); +} + +RGBATimeline::~RGBATimeline() { +} + +void RGBATimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) { + Color &color = slot->_color, &setup = slot->_data._color; + switch (blend) { + case MixBlend_Setup: + color.set(setup); + return; + case MixBlend_First: + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, + (setup.a - color.a) * alpha); + default: { + } + } + return; + } + + float r = 0, g = 0, b = 0, a = 0; + int i = Animation::search(_frames, time, RGBATimeline::ENTRIES); + int curveType = (int) _curves[i / RGBATimeline::ENTRIES]; + switch (curveType) { + case RGBATimeline::LINEAR: { + float before = _frames[i]; + r = _frames[i + RGBATimeline::R]; + g = _frames[i + RGBATimeline::G]; + b = _frames[i + RGBATimeline::B]; + a = _frames[i + RGBATimeline::A]; + float t = (time - before) / (_frames[i + RGBATimeline::ENTRIES] - before); + r += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::R] - r) * t; + g += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::G] - g) * t; + b += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::B] - b) * t; + a += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::A] - a) * t; + break; + } + case RGBATimeline::STEPPED: { + r = _frames[i + RGBATimeline::R]; + g = _frames[i + RGBATimeline::G]; + b = _frames[i + RGBATimeline::B]; + a = _frames[i + RGBATimeline::A]; + break; + } + default: { + r = getBezierValue(time, i, RGBATimeline::R, curveType - RGBATimeline::BEZIER); + g = getBezierValue(time, i, RGBATimeline::G, + curveType + RGBATimeline::BEZIER_SIZE - RGBATimeline::BEZIER); + b = getBezierValue(time, i, RGBATimeline::B, + curveType + RGBATimeline::BEZIER_SIZE * 2 - RGBATimeline::BEZIER); + a = getBezierValue(time, i, RGBATimeline::A, + curveType + RGBATimeline::BEZIER_SIZE * 3 - RGBATimeline::BEZIER); + } + } + Color &color = slot->_color; + if (alpha == 1) + color.set(r, g, b, a); + else { + if (blend == MixBlend_Setup) color.set(slot->_data._color); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } +} + +void RGBATimeline::setFrame(int frame, float time, float r, float g, float b, float a) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; + _frames[frame + A] = a; +} + +RTTI_IMPL(RGBTimeline, CurveTimeline) + +RGBTimeline::RGBTimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount, + RGBTimeline::ENTRIES, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex}; + setPropertyIds(ids, 1); +} + +RGBTimeline::~RGBTimeline() { +} + +void RGBTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) { + Color &color = slot->_color, &setup = slot->_data._color; + switch (blend) { + case MixBlend_Setup: + color.set(setup); + return; + case MixBlend_First: + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, + (setup.a - color.a) * alpha); + default: { + } + } + return; + } + + float r = 0, g = 0, b = 0; + int i = Animation::search(_frames, time, RGBTimeline::ENTRIES); + int curveType = (int) _curves[i / RGBTimeline::ENTRIES]; + switch (curveType) { + case RGBTimeline::LINEAR: { + float before = _frames[i]; + r = _frames[i + RGBTimeline::R]; + g = _frames[i + RGBTimeline::G]; + b = _frames[i + RGBTimeline::B]; + float t = (time - before) / (_frames[i + RGBTimeline::ENTRIES] - before); + r += (_frames[i + RGBTimeline::ENTRIES + RGBTimeline::R] - r) * t; + g += (_frames[i + RGBTimeline::ENTRIES + RGBTimeline::G] - g) * t; + b += (_frames[i + RGBTimeline::ENTRIES + RGBTimeline::B] - b) * t; + break; + } + case RGBTimeline::STEPPED: { + r = _frames[i + RGBTimeline::R]; + g = _frames[i + RGBTimeline::G]; + b = _frames[i + RGBTimeline::B]; + break; + } + default: { + r = getBezierValue(time, i, RGBTimeline::R, curveType - RGBTimeline::BEZIER); + g = getBezierValue(time, i, RGBTimeline::G, + curveType + RGBTimeline::BEZIER_SIZE - RGBTimeline::BEZIER); + b = getBezierValue(time, i, RGBTimeline::B, + curveType + RGBTimeline::BEZIER_SIZE * 2 - RGBTimeline::BEZIER); + } + } + Color &color = slot->_color; + if (alpha == 1) + color.set(r, g, b); + else { + Color &setup = slot->_data._color; + if (blend == MixBlend_Setup) color.set(setup.r, setup.g, setup.b); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha); + } +} + +void RGBTimeline::setFrame(int frame, float time, float r, float g, float b) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; +} + +RTTI_IMPL(AlphaTimeline, CurveTimeline1) + +AlphaTimeline::AlphaTimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline1(frameCount, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Alpha << 32) | slotIndex}; + setPropertyIds(ids, 1); +} + +AlphaTimeline::~AlphaTimeline() { +} + +void AlphaTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) {// Time is before first frame. + Color &color = slot->_color, &setup = slot->_data._color; + switch (blend) { + case MixBlend_Setup: + color.a = setup.a; + return; + case MixBlend_First: + color.a += (setup.a - color.a) * alpha; + default: { + } + } + return; + } + + float a = getCurveValue(time); + if (alpha == 1) + slot->_color.a = a; + else { + if (blend == MixBlend_Setup) slot->_color.a = slot->_data._color.a; + slot->_color.a += (a - slot->_color.a) * alpha; + } +} + +RTTI_IMPL(RGBA2Timeline, CurveTimeline) + +RGBA2Timeline::RGBA2Timeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount, + RGBA2Timeline::ENTRIES, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, + ((PropertyId) Property_Alpha << 32) | slotIndex, + ((PropertyId) Property_Rgb2 << 32) | slotIndex}; + setPropertyIds(ids, 3); +} + +RGBA2Timeline::~RGBA2Timeline() { +} + +void RGBA2Timeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) { + Color &light = slot->_color, &dark = slot->_darkColor, &setupLight = slot->_data._color, &setupDark = slot->_data._darkColor; + switch (blend) { + case MixBlend_Setup: + light.set(setupLight); + dark.set(setupDark.r, setupDark.g, setupDark.b); + return; + case MixBlend_First: + light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, + (setupLight.b - light.b) * alpha, + (setupLight.a - light.a) * alpha); + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + default: { + } + } + return; + } + + float r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + int i = Animation::search(_frames, time, RGBA2Timeline::ENTRIES); + int curveType = (int) _curves[i / RGBA2Timeline::ENTRIES]; + switch (curveType) { + case RGBA2Timeline::LINEAR: { + float before = _frames[i]; + r = _frames[i + RGBA2Timeline::R]; + g = _frames[i + RGBA2Timeline::G]; + b = _frames[i + RGBA2Timeline::B]; + a = _frames[i + RGBA2Timeline::A]; + r2 = _frames[i + RGBA2Timeline::R2]; + g2 = _frames[i + RGBA2Timeline::G2]; + b2 = _frames[i + RGBA2Timeline::B2]; + float t = (time - before) / (_frames[i + RGBA2Timeline::ENTRIES] - before); + r += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::R] - r) * t; + g += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::G] - g) * t; + b += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::B] - b) * t; + a += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::A] - a) * t; + r2 += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::R2] - r2) * t; + g2 += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::G2] - g2) * t; + b2 += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::B2] - b2) * t; + break; + } + case RGBA2Timeline::STEPPED: { + r = _frames[i + RGBA2Timeline::R]; + g = _frames[i + RGBA2Timeline::G]; + b = _frames[i + RGBA2Timeline::B]; + a = _frames[i + RGBA2Timeline::A]; + r2 = _frames[i + RGBA2Timeline::R2]; + g2 = _frames[i + RGBA2Timeline::G2]; + b2 = _frames[i + RGBA2Timeline::B2]; + break; + } + default: { + r = getBezierValue(time, i, RGBA2Timeline::R, curveType - RGBA2Timeline::BEZIER); + g = getBezierValue(time, i, RGBA2Timeline::G, + curveType + RGBA2Timeline::BEZIER_SIZE - RGBA2Timeline::BEZIER); + b = getBezierValue(time, i, RGBA2Timeline::B, + curveType + RGBA2Timeline::BEZIER_SIZE * 2 - RGBA2Timeline::BEZIER); + a = getBezierValue(time, i, RGBA2Timeline::A, + curveType + RGBA2Timeline::BEZIER_SIZE * 3 - RGBA2Timeline::BEZIER); + r2 = getBezierValue(time, i, RGBA2Timeline::R2, + curveType + RGBA2Timeline::BEZIER_SIZE * 4 - RGBA2Timeline::BEZIER); + g2 = getBezierValue(time, i, RGBA2Timeline::G2, + curveType + RGBA2Timeline::BEZIER_SIZE * 5 - RGBA2Timeline::BEZIER); + b2 = getBezierValue(time, i, RGBA2Timeline::B2, + curveType + RGBA2Timeline::BEZIER_SIZE * 6 - RGBA2Timeline::BEZIER); + } + } + Color &light = slot->_color, &dark = slot->_darkColor; + if (alpha == 1) { + light.set(r, g, b, a); + dark.set(r2, g2, b2); + } else { + if (blend == MixBlend_Setup) { + light.set(slot->_data._color); + dark.set(slot->_data._darkColor); + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } +} + +void RGBA2Timeline::setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; + _frames[frame + A] = a; + _frames[frame + R2] = r2; + _frames[frame + G2] = g2; + _frames[frame + B2] = b2; +} + +RTTI_IMPL(RGB2Timeline, CurveTimeline) + +RGB2Timeline::RGB2Timeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount, + RGB2Timeline::ENTRIES, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, + ((PropertyId) Property_Rgb2 << 32) | slotIndex}; + setPropertyIds(ids, 2); +} + +RGB2Timeline::~RGB2Timeline() { +} + +void RGB2Timeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) { + Color &light = slot->_color, &dark = slot->_darkColor, &setupLight = slot->_data._color, &setupDark = slot->_data._darkColor; + switch (blend) { + case MixBlend_Setup: + light.set(setupLight.r, setupLight.g, setupLight.b); + dark.set(setupDark.r, setupDark.g, setupDark.b); + return; + case MixBlend_First: + light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, + (setupLight.b - light.b) * alpha); + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + default: { + } + } + return; + } + + float r = 0, g = 0, b = 0, r2 = 0, g2 = 0, b2 = 0; + int i = Animation::search(_frames, time, RGB2Timeline::ENTRIES); + int curveType = (int) _curves[i / RGB2Timeline::ENTRIES]; + switch (curveType) { + case RGB2Timeline::LINEAR: { + float before = _frames[i]; + r = _frames[i + RGB2Timeline::R]; + g = _frames[i + RGB2Timeline::G]; + b = _frames[i + RGB2Timeline::B]; + r2 = _frames[i + RGB2Timeline::R2]; + g2 = _frames[i + RGB2Timeline::G2]; + b2 = _frames[i + RGB2Timeline::B2]; + float t = (time - before) / (_frames[i + RGB2Timeline::ENTRIES] - before); + r += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::R] - r) * t; + g += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::G] - g) * t; + b += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::B] - b) * t; + r2 += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::R2] - r2) * t; + g2 += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::G2] - g2) * t; + b2 += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::B2] - b2) * t; + break; + } + case RGB2Timeline::STEPPED: { + r = _frames[i + RGB2Timeline::R]; + g = _frames[i + RGB2Timeline::G]; + b = _frames[i + RGB2Timeline::B]; + r2 = _frames[i + RGB2Timeline::R2]; + g2 = _frames[i + RGB2Timeline::G2]; + b2 = _frames[i + RGB2Timeline::B2]; + break; + } + default: { + r = getBezierValue(time, i, RGB2Timeline::R, curveType - RGB2Timeline::BEZIER); + g = getBezierValue(time, i, RGB2Timeline::G, + curveType + RGB2Timeline::BEZIER_SIZE - RGB2Timeline::BEZIER); + b = getBezierValue(time, i, RGB2Timeline::B, + curveType + RGB2Timeline::BEZIER_SIZE * 2 - RGB2Timeline::BEZIER); + r2 = getBezierValue(time, i, RGB2Timeline::R2, + curveType + RGB2Timeline::BEZIER_SIZE * 4 - RGB2Timeline::BEZIER); + g2 = getBezierValue(time, i, RGB2Timeline::G2, + curveType + RGB2Timeline::BEZIER_SIZE * 5 - RGB2Timeline::BEZIER); + b2 = getBezierValue(time, i, RGB2Timeline::B2, + curveType + RGB2Timeline::BEZIER_SIZE * 6 - RGB2Timeline::BEZIER); + } + } + Color &light = slot->_color, &dark = slot->_darkColor; + if (alpha == 1) { + light.set(r, g, b); + dark.set(r2, g2, b2); + } else { + if (blend == MixBlend_Setup) { + light.set(slot->_data._color.r, slot->_data._color.g, slot->_data._color.b); + dark.set(slot->_data._darkColor); + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha); + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } +} + +void RGB2Timeline::setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; + _frames[frame + R2] = r2; + _frames[frame + G2] = g2; + _frames[frame + B2] = b2; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp new file mode 100644 index 0000000..e60872e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp @@ -0,0 +1,60 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(ConstraintData) + +ConstraintData::ConstraintData(const String &name) : _name(name), _order(0), _skinRequired(false) { +} + +ConstraintData::~ConstraintData() { +} + +const String &ConstraintData::getName() { + return _name; +} + +size_t ConstraintData::getOrder() { + return _order; +} + +void ConstraintData::setOrder(size_t inValue) { + _order = inValue; +} + +bool ConstraintData::isSkinRequired() { + return _skinRequired; +} + +void ConstraintData::setSkinRequired(bool inValue) { + _skinRequired = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp new file mode 100644 index 0000000..c0f17b7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp @@ -0,0 +1,150 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +RTTI_IMPL(CurveTimeline, Timeline) + +CurveTimeline::CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount) : Timeline(frameCount, + frameEntries) { + _curves.setSize(frameCount + bezierCount * BEZIER_SIZE, 0); + _curves[frameCount - 1] = STEPPED; +} + +CurveTimeline::~CurveTimeline() { +} + +void CurveTimeline::setLinear(size_t frame) { + _curves[frame] = LINEAR; +} + +void CurveTimeline::setStepped(size_t frame) { + _curves[frame] = STEPPED; +} + +void CurveTimeline::setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, + float cx2, float cy2, float time2, float value2) { + size_t i = getFrameCount() + bezier * BEZIER_SIZE; + if (value == 0) _curves[frame] = BEZIER + i; + float tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03; + float dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 0.006; + float ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + float dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667; + float x = time1 + dx, y = value1 + dy; + for (size_t n = i + BEZIER_SIZE; i < n; i += 2) { + _curves[i] = x; + _curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } +} + +float CurveTimeline::getBezierValue(float time, size_t frameIndex, size_t valueOffset, size_t i) { + if (_curves[i] > time) { + float x = _frames[frameIndex], y = _frames[frameIndex + valueOffset]; + return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y); + } + size_t n = i + BEZIER_SIZE; + for (i += 2; i < n; i += 2) { + if (_curves[i] >= time) { + float x = _curves[i - 2], y = _curves[i - 1]; + return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y); + } + } + frameIndex += getFrameEntries(); + float x = _curves[n - 2], y = _curves[n - 1]; + return y + (time - x) / (_frames[frameIndex] - x) * (_frames[frameIndex + valueOffset] - y); +} + +Vector &CurveTimeline::getCurves() { + return _curves; +} + +RTTI_IMPL(CurveTimeline1, CurveTimeline) + +CurveTimeline1::CurveTimeline1(size_t frameCount, size_t bezierCount) : CurveTimeline(frameCount, + CurveTimeline1::ENTRIES, + bezierCount) { +} + +CurveTimeline1::~CurveTimeline1() { +} + +void CurveTimeline1::setFrame(size_t frame, float time, float value) { + frame <<= 1; + _frames[frame] = time; + _frames[frame + CurveTimeline1::VALUE] = value; +} + +float CurveTimeline1::getCurveValue(float time) { + int i = (int) _frames.size() - 2; + for (int ii = 2; ii <= i; ii += 2) { + if (_frames[ii] > time) { + i = ii - 2; + break; + } + } + + int curveType = (int) _curves[i >> 1]; + switch (curveType) { + case CurveTimeline::LINEAR: { + float before = _frames[i], value = _frames[i + CurveTimeline1::VALUE]; + return value + (time - before) / (_frames[i + CurveTimeline1::ENTRIES] - before) * + (_frames[i + CurveTimeline1::ENTRIES + CurveTimeline1::VALUE] - value); + } + case CurveTimeline::STEPPED: + return _frames[i + CurveTimeline1::VALUE]; + } + return getBezierValue(time, i, CurveTimeline1::VALUE, curveType - CurveTimeline1::BEZIER); +} + +RTTI_IMPL(CurveTimeline2, CurveTimeline) + +CurveTimeline2::CurveTimeline2(size_t frameCount, size_t bezierCount) : CurveTimeline(frameCount, + CurveTimeline2::ENTRIES, + bezierCount) { +} + +CurveTimeline2::~CurveTimeline2() { +} + +void CurveTimeline2::setFrame(size_t frame, float time, float value1, float value2) { + frame *= CurveTimeline2::ENTRIES; + _frames[frame] = time; + _frames[frame + CurveTimeline2::VALUE1] = value1; + _frames[frame + CurveTimeline2::VALUE2] = value2; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp new file mode 100644 index 0000000..9f0cc4d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -0,0 +1,328 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(DeformTimeline, CurveTimeline) + +DeformTimeline::DeformTimeline(size_t frameCount, size_t bezierCount, int slotIndex, VertexAttachment *attachment) + : CurveTimeline(frameCount, 1, bezierCount), _slotIndex(slotIndex), _attachment(attachment) { + PropertyId ids[] = {((PropertyId) Property_Deform << 32) | ((slotIndex << 16 | attachment->_id) & 0xffffffff)}; + setPropertyIds(ids, 1); + + _vertices.ensureCapacity(frameCount); + for (size_t i = 0; i < frameCount; ++i) { + Vector vec; + _vertices.add(vec); + } +} + +void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slotP = skeleton._slots[_slotIndex]; + Slot &slot = *slotP; + if (!slot._bone.isActive()) return; + + Attachment *slotAttachment = slot.getAttachment(); + if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) { + return; + } + + VertexAttachment *attachment = static_cast(slotAttachment); + if (attachment->_timelineAttachment != _attachment) { + return; + } + + Vector &deformArray = slot._deform; + if (deformArray.size() == 0) { + blend = MixBlend_Setup; + } + + Vector> &vertices = _vertices; + size_t vertexCount = vertices[0].size(); + + Vector &frames = _frames; + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + deformArray.clear(); + return; + case MixBlend_First: { + if (alpha == 1) { + deformArray.clear(); + return; + } + deformArray.setSize(vertexCount, 0); + Vector &deform = deformArray; + if (attachment->getBones().size() == 0) { + // Unweighted vertex positions. + Vector &setupVertices = attachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) + deform[i] += (setupVertices[i] - deform[i]) * alpha; + } else { + // Weighted deform offsets. + alpha = 1 - alpha; + for (size_t i = 0; i < vertexCount; i++) + deform[i] *= alpha; + } + } + case MixBlend_Replace: + case MixBlend_Add: { + } + } + return; + } + + deformArray.setSize(vertexCount, 0); + Vector &deform = deformArray; + + if (time >= frames[frames.size() - 1]) {// Time is after last frame. + Vector &lastVertices = vertices[frames.size() - 1]; + if (alpha == 1) { + if (blend == MixBlend_Add) { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, no alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) + deform[i] += lastVertices[i] - setupVertices[i]; + } else { + // Weighted deform offsets, no alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] += lastVertices[i]; + } + } else { + // Vertex positions or deform offsets, no alpha. + memcpy(deform.buffer(), lastVertices.buffer(), vertexCount * sizeof(float)); + } + } else { + switch (blend) { + case MixBlend_Setup: { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, with alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float setup = setupVertices[i]; + deform[i] = setup + (lastVertices[i] - setup) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] = lastVertices[i] * alpha; + } + break; + } + case MixBlend_First: + case MixBlend_Replace: + // Vertex positions or deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] += (lastVertices[i] - deform[i]) * alpha; + break; + case MixBlend_Add: + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, no alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) + deform[i] += (lastVertices[i] - setupVertices[i]) * alpha; + } else { + // Weighted deform offsets, alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] += lastVertices[i] * alpha; + } + } + } + return; + } + + // Interpolate between the previous frame and the current frame. + int frame = Animation::search(frames, time); + float percent = getCurvePercent(time, frame); + Vector &prevVertices = vertices[frame]; + Vector &nextVertices = vertices[frame + 1]; + + if (alpha == 1) { + if (blend == MixBlend_Add) { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, no alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i]; + } + } else { + // Weighted deform offsets, no alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += prev + (nextVertices[i] - prev) * percent; + } + } + } else { + // Vertex positions or deform offsets, no alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] = prev + (nextVertices[i] - prev) * percent; + } + } + } else { + switch (blend) { + case MixBlend_Setup: { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, with alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i], setup = setupVertices[i]; + deform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } + break; + } + case MixBlend_First: + case MixBlend_Replace: + // Vertex positions or deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha; + } + break; + case MixBlend_Add: + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, with alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } + } + } +} + +void DeformTimeline::setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, + float cx2, float cy2, float time2, float value2) { + SP_UNUSED(value1); + SP_UNUSED(value2); + size_t i = getFrameCount() + bezier * DeformTimeline::BEZIER_SIZE; + if (value == 0) _curves[frame] = DeformTimeline::BEZIER + i; + float tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06; + float dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = (cy1 - cy2 + 0.33333333) * 0.018; + float ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + float dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667; + float x = time1 + dx, y = dy; + for (size_t n = i + DeformTimeline::BEZIER_SIZE; i < n; i += 2) { + _curves[i] = x; + _curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } +} + +float DeformTimeline::getCurvePercent(float time, int frame) { + int i = (int) _curves[frame]; + switch (i) { + case DeformTimeline::LINEAR: { + float x = _frames[frame]; + return (time - x) / (_frames[frame + getFrameEntries()] - x); + } + case DeformTimeline::STEPPED: { + return 0; + } + default: { + } + } + i -= DeformTimeline::BEZIER; + if (_curves[i] > time) { + float x = _frames[frame]; + return _curves[i + 1] * (time - x) / (_curves[i] - x); + } + int n = i + DeformTimeline::BEZIER_SIZE; + for (i += 2; i < n; i += 2) { + if (_curves[i] >= time) { + float x = _curves[i - 2], y = _curves[i - 1]; + return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y); + } + } + float x = _curves[n - 2], y = _curves[n - 1]; + return y + (1 - y) * (time - x) / (_frames[frame + getFrameEntries()] - x); +} + +void DeformTimeline::setFrame(int frame, float time, Vector &vertices) { + _frames[frame] = time; + _vertices[frame].clear(); + _vertices[frame].addAll(vertices); +} + +Vector> &DeformTimeline::getVertices() { + return _vertices; +} + +VertexAttachment *DeformTimeline::getAttachment() { + return _attachment; +} + +void DeformTimeline::setAttachment(VertexAttachment *inValue) { + _attachment = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp new file mode 100644 index 0000000..26b9dbf --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -0,0 +1,102 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(DrawOrderTimeline, Timeline) + +DrawOrderTimeline::DrawOrderTimeline(size_t frameCount) : Timeline(frameCount, 1) { + PropertyId ids[] = {((PropertyId) Property_DrawOrder << 32)}; + setPropertyIds(ids, 1); + + _drawOrders.ensureCapacity(frameCount); + for (size_t i = 0; i < frameCount; ++i) { + Vector vec; + _drawOrders.add(vec); + } +} + +void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(alpha); + + Vector &drawOrder = skeleton._drawOrder; + Vector &slots = skeleton._slots; + if (direction == MixDirection_Out) { + if (blend == MixBlend_Setup) { + drawOrder.clear(); + drawOrder.ensureCapacity(slots.size()); + for (size_t i = 0, n = slots.size(); i < n; ++i) + drawOrder.add(slots[i]); + } + return; + } + + if (time < _frames[0]) { + if (blend == MixBlend_Setup || blend == MixBlend_First) { + drawOrder.clear(); + drawOrder.ensureCapacity(slots.size()); + for (size_t i = 0, n = slots.size(); i < n; ++i) + drawOrder.add(slots[i]); + } + return; + } + + Vector &drawOrderToSetupIndex = _drawOrders[Animation::search(_frames, time)]; + if (drawOrderToSetupIndex.size() == 0) { + drawOrder.clear(); + for (size_t i = 0, n = slots.size(); i < n; ++i) + drawOrder.add(slots[i]); + } else { + for (size_t i = 0, n = drawOrderToSetupIndex.size(); i < n; ++i) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } +} + +void DrawOrderTimeline::setFrame(size_t frame, float time, Vector &drawOrder) { + _frames[frame] = time; + _drawOrders[frame].clear(); + _drawOrders[frame].addAll(drawOrder); +} + +Vector> &DrawOrderTimeline::getDrawOrders() { + return _drawOrders; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Event.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Event.cpp new file mode 100644 index 0000000..ffe1809 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Event.cpp @@ -0,0 +1,90 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +spine::Event::Event(float time, const spine::EventData &data) : _data(data), + _time(time), + _intValue(0), + _floatValue(0), + _stringValue(), + _volume(1), + _balance(0) { +} + +const spine::EventData &spine::Event::getData() { + return _data; +} + +float spine::Event::getTime() { + return _time; +} + +int spine::Event::getIntValue() { + return _intValue; +} + +void spine::Event::setIntValue(int inValue) { + _intValue = inValue; +} + +float spine::Event::getFloatValue() { + return _floatValue; +} + +void spine::Event::setFloatValue(float inValue) { + _floatValue = inValue; +} + +const spine::String &spine::Event::getStringValue() { + return _stringValue; +} + +void spine::Event::setStringValue(const spine::String &inValue) { + _stringValue = inValue; +} + + +float spine::Event::getVolume() { + return _volume; +} + +void spine::Event::setVolume(float inValue) { + _volume = inValue; +} + +float spine::Event::getBalance() { + return _balance; +} + +void spine::Event::setBalance(float inValue) { + _balance = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/EventData.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/EventData.cpp new file mode 100644 index 0000000..a6af9dd --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/EventData.cpp @@ -0,0 +1,96 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +spine::EventData::EventData(const spine::String &name) : _name(name), + _intValue(0), + _floatValue(0), + _stringValue(), + _audioPath(), + _volume(1), + _balance(0) { + assert(_name.length() > 0); +} + +/// The name of the event, which is unique within the skeleton. +const spine::String &spine::EventData::getName() const { + return _name; +} + +int spine::EventData::getIntValue() const { + return _intValue; +} + +void spine::EventData::setIntValue(int inValue) { + _intValue = inValue; +} + +float spine::EventData::getFloatValue() const { + return _floatValue; +} + +void spine::EventData::setFloatValue(float inValue) { + _floatValue = inValue; +} + +const spine::String &spine::EventData::getStringValue() const { + return _stringValue; +} + +void spine::EventData::setStringValue(const spine::String &inValue) { + this->_stringValue = inValue; +} + +const spine::String &spine::EventData::getAudioPath() const { + return _audioPath; +} + +void spine::EventData::setAudioPath(const spine::String &inValue) { + _audioPath = inValue; +} + + +float spine::EventData::getVolume() const { + return _volume; +} + +void spine::EventData::setVolume(float inValue) { + _volume = inValue; +} + +float spine::EventData::getBalance() const { + return _balance; +} + +void spine::EventData::setBalance(float inValue) { + _balance = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp new file mode 100644 index 0000000..857b69c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -0,0 +1,99 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(EventTimeline, Timeline) + +EventTimeline::EventTimeline(size_t frameCount) : Timeline(frameCount, 1) { + PropertyId ids[] = {((PropertyId) Property_Event << 32)}; + setPropertyIds(ids, 1); + _events.setSize(frameCount, NULL); +} + +EventTimeline::~EventTimeline() { + ContainerUtil::cleanUpVectorOfPointers(_events); +} + +void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + if (pEvents == NULL) return; + + Vector &events = *pEvents; + + size_t frameCount = _frames.size(); + + if (lastTime > time) { + // Fire events after last time for looped animations. + apply(skeleton, lastTime, FLT_MAX, pEvents, alpha, blend, direction); + lastTime = -1.0f; + } else if (lastTime >= _frames[frameCount - 1]) { + // Last time is after last i. + return; + } + + if (time < _frames[0]) return;// Time is before first i. + + int i; + if (lastTime < _frames[0]) { + i = 0; + } else { + i = Animation::search(_frames, lastTime) + 1; + float frameTime = _frames[i]; + while (i > 0) { + // Fire multiple events with the same i. + if (_frames[i - 1] != frameTime) break; + i--; + } + } + + for (; (size_t) i < frameCount && time >= _frames[i]; i++) + events.add(_events[i]); +} + +void EventTimeline::setFrame(size_t frame, Event *event) { + _frames[frame] = event->getTime(); + _events[frame] = event; +} + +Vector &EventTimeline::getEvents() { return _events; } diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Extension.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Extension.cpp new file mode 100644 index 0000000..43939ba --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Extension.cpp @@ -0,0 +1,127 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +#include + +using namespace spine; + +SpineExtension *SpineExtension::_instance = NULL; + +void SpineExtension::setInstance(SpineExtension *inValue) { + assert(inValue); + + _instance = inValue; +} + +SpineExtension *SpineExtension::getInstance() { + if (!_instance) _instance = spine::getDefaultExtension(); + assert(_instance); + + return _instance; +} + +SpineExtension::~SpineExtension() { +} + +SpineExtension::SpineExtension() { +} + +DefaultSpineExtension::~DefaultSpineExtension() { +} + +void *DefaultSpineExtension::_alloc(size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + if (size == 0) + return 0; + void *ptr = ::malloc(size); + return ptr; +} + +void *DefaultSpineExtension::_calloc(size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + if (size == 0) + return 0; + + void *ptr = ::malloc(size); + if (ptr) { + memset(ptr, 0, size); + } + return ptr; +} + +void *DefaultSpineExtension::_realloc(void *ptr, size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + void *mem = NULL; + if (size == 0) + return 0; + if (ptr == NULL) + mem = ::malloc(size); + else + mem = ::realloc(ptr, size); + return mem; +} + +void DefaultSpineExtension::_free(void *mem, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + ::free(mem); +} + +char *DefaultSpineExtension::_readFile(const String &path, int *length) { +#ifndef __EMSCRIPTEN__ + char *data; + FILE *file = fopen(path.buffer(), "rb"); + if (!file) return 0; + + fseek(file, 0, SEEK_END); + *length = (int) ftell(file); + fseek(file, 0, SEEK_SET); + + data = SpineExtension::alloc(*length, __FILE__, __LINE__); + fread(data, 1, *length, file); + fclose(file); + + return data; +#else + return nullptr; +#endif +} + +DefaultSpineExtension::DefaultSpineExtension() : SpineExtension() { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp new file mode 100644 index 0000000..279c76d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -0,0 +1,366 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(IkConstraint, Updatable) + +void IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha) { + Bone *p = bone.getParent(); + float pa = p->_a, pb = p->_b, pc = p->_c, pd = p->_d; + float rotationIK = -bone._ashearX - bone._arotation; + float tx = 0, ty = 0; + + switch (bone._data.getTransformMode()) { + case TransformMode_OnlyTranslation: + tx = (targetX - bone._worldX) * MathUtil::sign(bone.getSkeleton().getScaleX()); + ty = (targetY - bone._worldY) * MathUtil::sign(bone.getSkeleton().getScaleY()); + break; + case TransformMode_NoRotationOrReflection: { + float s = MathUtil::abs(pa * pd - pb * pc) / MathUtil::max(0.0001f, pa * pa + pc * pc); + float sa = pa / bone._skeleton.getScaleX(); + float sc = pc / bone._skeleton.getScaleY(); + pb = -sc * s * bone._skeleton.getScaleX(); + pd = sa * s * bone._skeleton.getScaleY(); + rotationIK += MathUtil::atan2(sc, sa) * MathUtil::Rad_Deg; + } + default: + float x = targetX - p->_worldX, y = targetY - p->_worldY; + float d = pa * pd - pb * pc; + if (MathUtil::abs(d) <= 0.0001f) { + tx = 0; + ty = 0; + } else { + tx = (x * pd - y * pb) / d - bone._ax; + ty = (y * pa - x * pc) / d - bone._ay; + } + } + rotationIK += MathUtil::atan2(ty, tx) * MathUtil::Rad_Deg; + if (bone._ascaleX < 0) rotationIK += 180; + if (rotationIK > 180) rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + float sx = bone._ascaleX; + float sy = bone._ascaleY; + if (compress || stretch) { + switch (bone._data.getTransformMode()) { + case TransformMode_NoScale: + case TransformMode_NoScaleOrReflection: + tx = targetX - bone._worldX; + ty = targetY - bone._worldY; + default:; + } + float b = bone._data.getLength() * sx, dd = MathUtil::sqrt(tx * tx + ty * ty); + if (((compress && dd < b) || (stretch && dd > b)) && (b > 0.0001f)) { + float s = (dd / b - 1) * alpha + 1; + sx *= s; + if (uniform) sy *= s; + } + } + bone.updateWorldTransform(bone._ax, bone._ay, bone._arotation + rotationIK * alpha, sx, sy, bone._ashearX, + bone._ashearY); +} + +void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, bool uniform, + float softness, + float alpha) { + float a, b, c, d; + float px, py, psx, psy, sx, sy; + float cx, cy, csx, cwx, cwy; + int o1, o2, s2, u; + Bone *pp = parent.getParent(); + float tx, ty, dx, dy, dd, l1, l2, a1, a2, r, td, sd, p; + float id, x, y; + px = parent._ax; + py = parent._ay; + psx = parent._ascaleX; + psy = parent._ascaleY; + sx = psx; + sy = psy; + csx = child._ascaleX; + if (psx < 0) { + psx = -psx; + o1 = 180; + s2 = -1; + } else { + o1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + o2 = 180; + } else + o2 = 0; + r = psx - psy; + cx = child._ax; + u = (r < 0 ? -r : r) <= 0.0001f; + if (!u || stretch) { + cy = 0; + cwx = parent._a * cx + parent._worldX; + cwy = parent._c * cx + parent._worldY; + } else { + cy = child._ay; + cwx = parent._a * cx + parent._b * cy + parent._worldX; + cwy = parent._c * cx + parent._d * cy + parent._worldY; + } + a = pp->_a; + b = pp->_b; + c = pp->_c; + d = pp->_d; + id = a * d - b * c; + id = MathUtil::abs(id) <= 0.0001f ? 0 : 1 / id; + x = cwx - pp->_worldX; + y = cwy - pp->_worldY; + dx = (x * d - y * b) * id - px; + dy = (y * a - x * c) * id - py; + l1 = MathUtil::sqrt(dx * dx + dy * dy); + l2 = child._data.getLength() * csx; + if (l1 < 0.0001) { + apply(parent, targetX, targetY, false, stretch, false, alpha); + child.updateWorldTransform(cx, cy, 0, child._ascaleX, child._ascaleY, child._ashearX, child._ashearY); + return; + } + x = targetX - pp->_worldX; + y = targetY - pp->_worldY; + tx = (x * d - y * b) * id - px; + ty = (y * a - x * c) * id - py; + dd = tx * tx + ty * ty; + if (softness != 0) { + softness *= psx * (csx + 1) * 0.5f; + td = MathUtil::sqrt(dd); + sd = td - l1 - l2 * psx + softness; + if (sd > 0) { + p = MathUtil::min(1.0f, sd / (softness * 2)) - 1; + p = (sd - softness * (1 - p * p)) / td; + tx -= p * tx; + ty -= p * ty; + dd = tx * tx + ty * ty; + } + } + if (u) { + float cosine; + l2 *= psx; + cosine = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cosine < -1) { + cosine = -1; + a2 = MathUtil::Pi * bendDir; + } else if (cosine > 1) { + cosine = 1; + a2 = 0; + if (stretch) { + a = (MathUtil::sqrt(dd) / (l1 + l2) - 1) * alpha + 1; + sx *= a; + if (uniform) sy *= a; + } + } else + a2 = MathUtil::acos(cosine) * bendDir; + a = l1 + l2 * cosine; + b = l2 * MathUtil::sin(a2); + a1 = MathUtil::atan2(ty * a - tx * b, tx * a + ty * b); + } else { + a = psx * l2; + b = psy * l2; + float aa = a * a, bb = b * b, ll = l1 * l1, ta = MathUtil::atan2(ty, tx); + float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c0; + if (d >= 0) { + float q = MathUtil::sqrt(d), r0, r1; + if (c1 < 0) q = -q; + q = -(c1 + q) * 0.5f; + r0 = q / c2; + r1 = c0 / q; + r = MathUtil::abs(r0) < MathUtil::abs(r1) ? r0 : r1; + float ddrr = dd - r * r; + if (ddrr >= 0) { + y = MathUtil::sqrt(ddrr) * bendDir; + a1 = ta - MathUtil::atan2(y, r); + a2 = MathUtil::atan2(y / psy, (r - l1) / psx); + goto break_outer; + } + } + { + float minAngle = MathUtil::Pi, minX = l1 - a, minDist = minX * minX, minY = 0; + float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c0 = -a * l1 / (aa - bb); + if (c0 >= -1 && c0 <= 1) { + c0 = MathUtil::acos(c0); + x = a * MathUtil::cos(c0) + l1; + y = b * MathUtil::sin(c0); + d = x * x + y * y; + if (d < minDist) { + minAngle = c0; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c0; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) * 0.5f) { + a1 = ta - MathUtil::atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } else { + a1 = ta - MathUtil::atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + } +break_outer : { + float os = MathUtil::atan2(cy, cx) * s2; + a1 = (a1 - os) * MathUtil::Rad_Deg + o1 - parent._arotation; + if (a1 > 180) a1 -= 360; + else if (a1 < -180) + a1 += 360; + parent.updateWorldTransform(px, py, parent._arotation + a1 * alpha, sx, sy, 0, 0); + a2 = ((a2 + os) * MathUtil::Rad_Deg - child._ashearX) * s2 + o2 - child._arotation; + if (a2 > 180) a2 -= 360; + else if (a2 < -180) + a2 += 360; + child.updateWorldTransform(cx, cy, child._arotation + a2 * alpha, child._ascaleX, child._ascaleY, + child._ashearX, child._ashearY); +} +} + +IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Updatable(), + _data(data), + _bendDirection(data.getBendDirection()), + _compress(data.getCompress()), + _stretch(data.getStretch()), + _mix(data.getMix()), + _softness(data.getSoftness()), + _target(skeleton.findBone( + data.getTarget()->getName())), + _active(false) { + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); i++) { + BoneData *boneData = _data.getBones()[i]; + _bones.add(skeleton.findBone(boneData->getName())); + } +} + +void IkConstraint::update() { + if (_mix == 0) return; + switch (_bones.size()) { + case 1: { + Bone *bone0 = _bones[0]; + apply(*bone0, _target->getWorldX(), _target->getWorldY(), _compress, _stretch, _data._uniform, _mix); + } break; + case 2: { + Bone *bone0 = _bones[0]; + Bone *bone1 = _bones[1]; + apply(*bone0, *bone1, _target->getWorldX(), _target->getWorldY(), _bendDirection, _stretch, _data._uniform, + _softness, + _mix); + } break; + } +} + +int IkConstraint::getOrder() { + return (int) _data.getOrder(); +} + +IkConstraintData &IkConstraint::getData() { + return _data; +} + +Vector &IkConstraint::getBones() { + return _bones; +} + +Bone *IkConstraint::getTarget() { + return _target; +} + +void IkConstraint::setTarget(Bone *inValue) { + _target = inValue; +} + +int IkConstraint::getBendDirection() { + return _bendDirection; +} + +void IkConstraint::setBendDirection(int inValue) { + _bendDirection = inValue; +} + +float IkConstraint::getMix() { + return _mix; +} + +void IkConstraint::setMix(float inValue) { + _mix = inValue; +} + +bool IkConstraint::getStretch() { + return _stretch; +} + +void IkConstraint::setStretch(bool inValue) { + _stretch = inValue; +} + +bool IkConstraint::getCompress() { + return _compress; +} + +void IkConstraint::setCompress(bool inValue) { + _compress = inValue; +} + +bool IkConstraint::isActive() { + return _active; +} + +void IkConstraint::setActive(bool inValue) { + _active = inValue; +} + +float IkConstraint::getSoftness() { + return _softness; +} + +void IkConstraint::setSoftness(float inValue) { + _softness = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp new file mode 100644 index 0000000..090e098 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -0,0 +1,107 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +RTTI_IMPL(IkConstraintData, ConstraintData) + +IkConstraintData::IkConstraintData(const String &name) : ConstraintData(name), + _target(NULL), + _bendDirection(1), + _compress(false), + _stretch(false), + _uniform(false), + _mix(1), + _softness(0) { +} + +Vector &IkConstraintData::getBones() { + return _bones; +} + +BoneData *IkConstraintData::getTarget() { + return _target; +} + +void IkConstraintData::setTarget(BoneData *inValue) { + _target = inValue; +} + +int IkConstraintData::getBendDirection() { + return _bendDirection; +} + +void IkConstraintData::setBendDirection(int inValue) { + _bendDirection = inValue; +} + +float IkConstraintData::getMix() { + return _mix; +} + +void IkConstraintData::setMix(float inValue) { + _mix = inValue; +} + +bool IkConstraintData::getStretch() { + return _stretch; +} + +void IkConstraintData::setStretch(bool inValue) { + _stretch = inValue; +} + +bool IkConstraintData::getCompress() { + return _compress; +} + +void IkConstraintData::setCompress(bool inValue) { + _compress = inValue; +} + + +bool IkConstraintData::getUniform() { + return _uniform; +} + +void IkConstraintData::setUniform(bool inValue) { + _uniform = inValue; +} + +float IkConstraintData::getSoftness() { + return _softness; +} + +void IkConstraintData::setSoftness(float inValue) { + _softness = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp new file mode 100644 index 0000000..f07ac1f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -0,0 +1,141 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(IkConstraintTimeline, CurveTimeline) + +IkConstraintTimeline::IkConstraintTimeline(size_t frameCount, size_t bezierCount, int ikConstraintIndex) + : CurveTimeline(frameCount, IkConstraintTimeline::ENTRIES, bezierCount), _ikConstraintIndex(ikConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_IkConstraint << 32) | ikConstraintIndex}; + setPropertyIds(ids, 1); +} + +void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + IkConstraint *constraintP = skeleton._ikConstraints[_ikConstraintIndex]; + IkConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._mix = constraint._data._mix; + constraint._softness = constraint._data._softness; + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + return; + case MixBlend_First: + constraint._mix += (constraint._data._mix - constraint._mix) * alpha; + constraint._softness += (constraint._data._softness - constraint._softness) * alpha; + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + return; + default: + return; + } + } + + float mix = 0, softness = 0; + int i = Animation::search(_frames, time, IkConstraintTimeline::ENTRIES); + int curveType = (int) _curves[i / IkConstraintTimeline::ENTRIES]; + switch (curveType) { + case IkConstraintTimeline::LINEAR: { + float before = _frames[i]; + mix = _frames[i + IkConstraintTimeline::MIX]; + softness = _frames[i + IkConstraintTimeline::SOFTNESS]; + float t = (time - before) / (_frames[i + IkConstraintTimeline::ENTRIES] - before); + mix += (_frames[i + IkConstraintTimeline::ENTRIES + IkConstraintTimeline::MIX] - mix) * t; + softness += (_frames[i + IkConstraintTimeline::ENTRIES + IkConstraintTimeline::SOFTNESS] - softness) * t; + break; + } + case IkConstraintTimeline::STEPPED: { + mix = _frames[i + IkConstraintTimeline::MIX]; + softness = _frames[i + IkConstraintTimeline::SOFTNESS]; + break; + } + default: { + mix = getBezierValue(time, i, IkConstraintTimeline::MIX, curveType - IkConstraintTimeline::BEZIER); + softness = getBezierValue(time, i, IkConstraintTimeline::SOFTNESS, + curveType + IkConstraintTimeline::BEZIER_SIZE - + IkConstraintTimeline::BEZIER); + } + } + + if (blend == MixBlend_Setup) { + constraint._mix = constraint._data._mix + (mix - constraint._data._mix) * alpha; + constraint._softness = constraint._data._softness + (softness - constraint._data._softness) * alpha; + + if (direction == MixDirection_Out) { + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + } else { + constraint._bendDirection = _frames[i + IkConstraintTimeline::BEND_DIRECTION]; + constraint._compress = _frames[i + IkConstraintTimeline::COMPRESS] != 0; + constraint._stretch = _frames[i + IkConstraintTimeline::STRETCH] != 0; + } + } else { + constraint._mix += (mix - constraint._mix) * alpha; + constraint._softness += (softness - constraint._softness) * alpha; + if (direction == MixDirection_In) { + constraint._bendDirection = _frames[i + IkConstraintTimeline::BEND_DIRECTION]; + constraint._compress = _frames[i + IkConstraintTimeline::COMPRESS] != 0; + constraint._stretch = _frames[i + IkConstraintTimeline::STRETCH] != 0; + } + } +} + +void IkConstraintTimeline::setFrame(int frame, float time, float mix, float softness, int bendDirection, bool compress, + bool stretch) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + MIX] = mix; + _frames[frame + SOFTNESS] = softness; + _frames[frame + BEND_DIRECTION] = (float) bendDirection; + _frames[frame + COMPRESS] = compress ? 1 : 0; + _frames[frame + STRETCH] = stretch ? 1 : 0; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Json.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Json.cpp new file mode 100644 index 0000000..417d4b5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Json.cpp @@ -0,0 +1,561 @@ +/* +Copyright (c) 2009, Dave Gamble +Copyright (c) 2013, Esoteric Software + +Permission is hereby granted, dispose of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* Json */ +/* JSON parser in CPP, from json.c in the spine-c runtime */ + +#ifndef _DEFAULT_SOURCE +/* Bring strings.h definitions into string.h, where appropriate */ +#define _DEFAULT_SOURCE +#endif + +#ifndef _BSD_SOURCE +/* Bring strings.h definitions into string.h, where appropriate */ +#define _BSD_SOURCE +#endif + +#include +#include +#include + +#include +#include + +using namespace spine; + +const int Json::JSON_FALSE = 0; +const int Json::JSON_TRUE = 1; +const int Json::JSON_NULL = 2; +const int Json::JSON_NUMBER = 3; +const int Json::JSON_STRING = 4; +const int Json::JSON_ARRAY = 5; +const int Json::JSON_OBJECT = 6; + +const char *Json::_error = NULL; + +Json *Json::getItem(Json *object, const char *string) { + Json *c = object->_child; + while (c && json_strcasecmp(c->_name, string)) { + c = c->_next; + } + return c; +} + +Json *Json::getItem(Json *object, int childIndex) { + Json *current = object->_child; + while (current != NULL && childIndex > 0) { + childIndex--; + current = current->_next; + } + return current; +} + +const char *Json::getString(Json *object, const char *name, const char *defaultValue) { + object = getItem(object, name); + if (object) { + return object->_valueString; + } + + return defaultValue; +} + +float Json::getFloat(Json *value, const char *name, float defaultValue) { + value = getItem(value, name); + return value ? value->_valueFloat : defaultValue; +} + +int Json::getInt(Json *value, const char *name, int defaultValue) { + value = getItem(value, name); + return value ? value->_valueInt : defaultValue; +} + +bool Json::getBoolean(spine::Json *value, const char *name, bool defaultValue) { + value = getItem(value, name); + if (value) { + if (value->_valueString) return strcmp(value->_valueString, "true") == 0; + if (value->_type == JSON_NULL) return false; + if (value->_type == JSON_NUMBER) return value->_valueFloat != 0; + if (value->_type == JSON_FALSE) return false; + if (value->_type == JSON_TRUE) return true; + return defaultValue; + } else { + return defaultValue; + } +} + +const char *Json::getError() { + return _error; +} + +Json::Json(const char *value) : _next(NULL), +#if SPINE_JSON_HAVE_PREV + _prev(NULL), +#endif + _child(NULL), + _type(0), + _size(0), + _valueString(NULL), + _valueInt(0), + _valueFloat(0), + _name(NULL) { + if (value) { + value = parseValue(this, skip(value)); + + assert(value); + } +} + +Json::~Json() { + spine::Json *curr = NULL; + spine::Json *next = _child; + do { + curr = next; + if (curr) { + next = curr->_next; + } + delete curr; + } while (next); + + if (_valueString) { + SpineExtension::free(_valueString, __FILE__, __LINE__); + } + + if (_name) { + SpineExtension::free(_name, __FILE__, __LINE__); + } +} + +const char *Json::skip(const char *inValue) { + if (!inValue) { + /* must propagate NULL since it's often called in skip(f(...)) form */ + return NULL; + } + + while (*inValue && (unsigned char) *inValue <= 32) { + inValue++; + } + + return inValue; +} + +const char *Json::parseValue(Json *item, const char *value) { + /* Referenced by constructor, parseArray(), and parseObject(). */ + /* Always called with the result of skip(). */ +#ifdef SPINE_JSON_DEBUG /* Checked at entry to graph, constructor, and after every parse call. */ + if (!value) { + /* Fail on null. */ + return NULL; + } +#endif + + switch (*value) { + case 'n': { + if (!strncmp(value + 1, "ull", 3)) { + item->_type = JSON_NULL; + return value + 4; + } + break; + } + case 'f': { + if (!strncmp(value + 1, "alse", 4)) { + item->_type = JSON_FALSE; + /* calloc prevents us needing item->_type = JSON_FALSE or valueInt = 0 here */ + return value + 5; + } + break; + } + case 't': { + if (!strncmp(value + 1, "rue", 3)) { + item->_type = JSON_TRUE; + item->_valueInt = 1; + return value + 4; + } + break; + } + case '\"': + return parseString(item, value); + case '[': + return parseArray(item, value); + case '{': + return parseObject(item, value); + case '-': /* fallthrough */ + case '0': /* fallthrough */ + case '1': /* fallthrough */ + case '2': /* fallthrough */ + case '3': /* fallthrough */ + case '4': /* fallthrough */ + case '5': /* fallthrough */ + case '6': /* fallthrough */ + case '7': /* fallthrough */ + case '8': /* fallthrough */ + case '9': + return parseNumber(item, value); + default: + break; + } + + _error = value; + return NULL; /* failure. */ +} + +static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC}; + +const char *Json::parseString(Json *item, const char *str) { + const char *ptr = str + 1; + char *ptr2; + char *out; + int len = 0; + unsigned uc, uc2; + if (*str != '\"') { + /* TODO: don't need this check when called from parseValue, but do need from parseObject */ + _error = str; + return 0; + } /* not a string! */ + + while (*ptr != '\"' && *ptr && ++len) { + if (*ptr++ == '\\') { + ptr++; /* Skip escaped quotes. */ + } + } + + out = SpineExtension::alloc(len + 1, __FILE__, __LINE__); /* The length needed for the string, roughly. */ + if (!out) { + return 0; + } + + ptr = str + 1; + ptr2 = out; + while (*ptr != '\"' && *ptr) { + if (*ptr != '\\') { + *ptr2++ = *ptr++; + } else { + ptr++; + switch (*ptr) { + case 'b': + *ptr2++ = '\b'; + break; + case 'f': + *ptr2++ = '\f'; + break; + case 'n': + *ptr2++ = '\n'; + break; + case 'r': + *ptr2++ = '\r'; + break; + case 't': + *ptr2++ = '\t'; + break; + case 'u': { + /* transcode utf16 to utf8. */ + sscanf(ptr + 1, "%4x", &uc); + ptr += 4; /* get the unicode char. */ + + if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) { + break; /* check for invalid. */ + } + + /* TODO provide an option to ignore surrogates, use unicode replacement character? */ + if (uc >= 0xD800 && uc <= 0xDBFF) /* UTF16 surrogate pairs. */ { + if (ptr[1] != '\\' || ptr[2] != 'u') { + break; /* missing second-half of surrogate. */ + } + sscanf(ptr + 3, "%4x", &uc2); + ptr += 6; + if (uc2 < 0xDC00 || uc2 > 0xDFFF) { + break; /* invalid second-half of surrogate. */ + } + uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF)); + } + + len = 4; + if (uc < 0x80) { + len = 1; + } else if (uc < 0x800) { + len = 2; + } else if (uc < 0x10000) { + len = 3; + } + ptr2 += len; + + switch (len) { + case 4: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 3: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 2: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 1: + *--ptr2 = (uc | firstByteMark[len]); + } + ptr2 += len; + break; + } + default: + *ptr2++ = *ptr; + break; + } + ptr++; + } + } + + *ptr2 = 0; + + if (*ptr == '\"') { + ptr++; /* TODO error handling if not \" or \0 ? */ + } + + item->_valueString = out; + item->_type = JSON_STRING; + + return ptr; +} + +const char *Json::parseNumber(Json *item, const char *num) { + double result = 0.0; + int negative = 0; + char *ptr = (char *) num; + + if (*ptr == '-') { + negative = -1; + ++ptr; + } + + while (*ptr >= '0' && *ptr <= '9') { + result = result * 10.0 + (*ptr - '0'); + ++ptr; + } + + if (*ptr == '.') { + double fraction = 0.0; + int n = 0; + ++ptr; + + while (*ptr >= '0' && *ptr <= '9') { + fraction = (fraction * 10.0) + (*ptr - '0'); + ++ptr; + ++n; + } + result += fraction / pow(10.0, n); + } + + if (negative) { + result = -result; + } + + if (*ptr == 'e' || *ptr == 'E') { + double exponent = 0; + int expNegative = 0; + int n = 0; + ++ptr; + + if (*ptr == '-') { + expNegative = -1; + ++ptr; + } else if (*ptr == '+') { + ++ptr; + } + + while (*ptr >= '0' && *ptr <= '9') { + exponent = (exponent * 10.0) + (*ptr - '0'); + ++ptr; + ++n; + } + + if (expNegative) { + result = result / pow(10, exponent); + } else { + result = result * pow(10, exponent); + } + } + + if (ptr != num) { + /* Parse success, number found. */ + item->_valueFloat = (float) result; + item->_valueInt = (int) result; + item->_type = JSON_NUMBER; + return ptr; + } else { + /* Parse failure, _error is set. */ + _error = num; + return NULL; + } +} + +const char *Json::parseArray(Json *item, const char *value) { + Json *child; + +#ifdef SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */ + if (*value != '[') { + ep = value; + return 0; + } /* not an array! */ +#endif + + item->_type = JSON_ARRAY; + value = skip(value + 1); + if (*value == ']') { + return value + 1; /* empty array. */ + } + + item->_child = child = new (__FILE__, __LINE__) Json(NULL); + if (!item->_child) { + return NULL; /* memory fail */ + } + + value = skip(parseValue(child, skip(value))); /* skip any spacing, get the value. */ + + if (!value) { + return NULL; + } + + item->_size = 1; + + while (*value == ',') { + Json *new_item = new (__FILE__, __LINE__) Json(NULL); + if (!new_item) { + return NULL; /* memory fail */ + } + child->_next = new_item; +#if SPINE_JSON_HAVE_PREV + new_item->prev = child; +#endif + child = new_item; + value = skip(parseValue(child, skip(value + 1))); + if (!value) { + return NULL; /* parse fail */ + } + item->_size++; + } + + if (*value == ']') { + return value + 1; /* end of array */ + } + + _error = value; + + return NULL; /* malformed. */ +} + +/* Build an object from the text. */ +const char *Json::parseObject(Json *item, const char *value) { + Json *child; + +#ifdef SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */ + if (*value != '{') { + ep = value; + return 0; + } /* not an object! */ +#endif + + item->_type = JSON_OBJECT; + value = skip(value + 1); + if (*value == '}') { + return value + 1; /* empty array. */ + } + + item->_child = child = new (__FILE__, __LINE__) Json(NULL); + if (!item->_child) { + return NULL; + } + value = skip(parseString(child, skip(value))); + if (!value) { + return NULL; + } + child->_name = child->_valueString; + child->_valueString = 0; + if (*value != ':') { + _error = value; + return NULL; + } /* fail! */ + + value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return NULL; + } + + item->_size = 1; + + while (*value == ',') { + Json *new_item = new (__FILE__, __LINE__) Json(NULL); + if (!new_item) { + return NULL; /* memory fail */ + } + child->_next = new_item; +#if SPINE_JSON_HAVE_PREV + new_item->prev = child; +#endif + child = new_item; + value = skip(parseString(child, skip(value + 1))); + if (!value) { + return NULL; + } + child->_name = child->_valueString; + child->_valueString = 0; + if (*value != ':') { + _error = value; + return NULL; + } /* fail! */ + + value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return NULL; + } + item->_size++; + } + + if (*value == '}') { + return value + 1; /* end of array */ + } + + _error = value; + + return NULL; /* malformed. */ +} + +int Json::json_strcasecmp(const char *s1, const char *s2) { + /* TODO we may be able to elide these NULL checks if we can prove + * the graph and input (only callsite is Json_getItem) should not have NULLs + */ + if (s1 && s2) { +#if defined(_WIN32) + return _stricmp(s1, s2); +#else + return strcasecmp(s1, s2); +#endif + } else { + if (s1 < s2) { + return -1; /* s1 is null, s2 is not */ + } else if (s1 == s2) { + return 0; /* both are null */ + } else { + return 1; /* s2 is nul s1 is not */ + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp new file mode 100644 index 0000000..a67e917 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp @@ -0,0 +1,42 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +LinkedMesh::LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, + bool inheritTimeline) : _mesh(mesh), + _skin(skin), + _slotIndex(slotIndex), + _parent(parent), + _inheritTimeline(inheritTimeline) { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Log.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Log.cpp new file mode 100644 index 0000000..70ac744 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Log.cpp @@ -0,0 +1,123 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +void spine::spDebug_printSkeletonData(SkeletonData *skeletonData) { + int i, n; + spDebug_printBoneDatas(skeletonData->getBones()); + + for (i = 0, n = (int) skeletonData->getAnimations().size(); i < n; i++) { + spDebug_printAnimation(skeletonData->getAnimations()[i]); + } +} + +void _spDebug_printTimelineBase(Timeline *timeline) { + printf(" Timeline %s:\n", timeline->getRTTI().getClassName()); + printf(" frame count: %zu\n", timeline->getFrameCount()); + printf(" frame entries: %zu\n", timeline->getFrameEntries()); + printf(" frames: "); + spDebug_printFloats(timeline->getFrames()); + printf("\n"); +} + +void _spDebug_printCurveTimeline(CurveTimeline *timeline) { + _spDebug_printTimelineBase(timeline); + printf(" curves: "); + spDebug_printFloats(timeline->getCurves()); + printf("\n"); +} + +void spine::spDebug_printTimeline(Timeline *timeline) { + if (timeline->getRTTI().instanceOf(CurveTimeline::rtti)) + _spDebug_printCurveTimeline(static_cast(timeline)); + else + _spDebug_printTimelineBase(timeline); +} + +void spine::spDebug_printAnimation(Animation *animation) { + int i, n; + printf("Animation %s: %zu timelines\n", animation->getName().buffer(), animation->getTimelines().size()); + + for (i = 0, n = (int) animation->getTimelines().size(); i < n; i++) { + Timeline *timeline = animation->getTimelines()[i]; + spDebug_printTimeline(timeline); + } +} + +void spine::spDebug_printBoneDatas(Vector &boneDatas) { + int i, n; + for (i = 0, n = (int) boneDatas.size(); i < n; i++) { + spDebug_printBoneData(boneDatas[i]); + } +} + +void spine::spDebug_printBoneData(BoneData *boneData) { + printf("Bone data %s: %f, %f, %f, %f, %f, %f %f\n", boneData->getName().buffer(), boneData->getRotation(), + boneData->getScaleX(), boneData->getScaleY(), boneData->getX(), boneData->getY(), boneData->getShearX(), + boneData->getShearY()); +} + +void spine::spDebug_printSkeleton(Skeleton *skeleton) { + spDebug_printBones(skeleton->getBones()); +} + +void spine::spDebug_printBones(Vector &bones) { + int i, n; + for (i = 0, n = (int) bones.size(); i < n; i++) { + spDebug_printBone(bones[i]); + } +} + +void spine::spDebug_printBone(Bone *bone) { + printf("Bone %s: %f, %f, %f, %f, %f, %f\n", bone->getData().getName().buffer(), bone->getA(), bone->getB(), + bone->getC(), bone->getD(), bone->getWorldX(), bone->getWorldY()); +} + +void spine::spDebug_printFloats(float *values, int numFloats) { + int i; + printf("(%i) [", numFloats); + for (i = 0; i < numFloats; i++) { + printf("%f, ", values[i]); + } + printf("]"); +} + +void spine::spDebug_printFloats(Vector &values) { + int i, n; + printf("(%zu) [", values.size()); + for (i = 0, n = (int) values.size(); i < n; i++) { + printf("%f, ", values[i]); + } + printf("]"); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/MathUtil.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/MathUtil.cpp new file mode 100644 index 0000000..d3df88a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/MathUtil.cpp @@ -0,0 +1,124 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +// Required for division by 0 in _isNaN on MSVC +#ifdef _MSC_VER +#pragma warning(disable : 4723) +#endif + +using namespace spine; + +const float MathUtil::Pi = 3.1415926535897932385f; +const float MathUtil::Pi_2 = 3.1415926535897932385f * 2; +const float MathUtil::Deg_Rad = (3.1415926535897932385f / 180.0f); +const float MathUtil::Rad_Deg = (180.0f / 3.1415926535897932385f); + +float MathUtil::abs(float v) { + return ((v) < 0 ? -(v) : (v)); +} + +float MathUtil::sign(float v) { + return ((v) < 0 ? -1.0f : (v) > 0 ? 1.0f + : 0.0f); +} + +float MathUtil::clamp(float x, float min, float max) { + return ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))); +} + +float MathUtil::fmod(float a, float b) { + return (float) ::fmod(a, b); +} + +/// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 +/// degrees), largest error of 0.00488 radians (0.2796 degrees). +float MathUtil::atan2(float y, float x) { + return (float) ::atan2(y, x); +} + +/// Returns the cosine in radians from a lookup table. +float MathUtil::cos(float radians) { + return (float) ::cos(radians); +} + +/// Returns the sine in radians from a lookup table. +float MathUtil::sin(float radians) { + return (float) ::sin(radians); +} + +float MathUtil::sqrt(float v) { + return (float) ::sqrt(v); +} + +float MathUtil::acos(float v) { + return (float) ::acos(v); +} + +/// Returns the sine in radians from a lookup table. +float MathUtil::sinDeg(float degrees) { + return (float) ::sin(degrees * MathUtil::Deg_Rad); +} + +/// Returns the cosine in radians from a lookup table. +float MathUtil::cosDeg(float degrees) { + return (float) ::cos(degrees * MathUtil::Deg_Rad); +} + +/* Need to pass 0 as an argument, so VC++ doesn't error with C2124 */ +static bool _isNan(float value, float zero) { + float _nan = (float) 0.0 / zero; + return 0 == memcmp((void *) &value, (void *) &_nan, sizeof(value)); +} + +bool MathUtil::isNan(float v) { + return _isNan(v, 0); +} + +float MathUtil::random() { + return ::rand() / (float) RAND_MAX; +} + +float MathUtil::randomTriangular(float min, float max) { + return randomTriangular(min, max, (min + max) * 0.5f); +} + +float MathUtil::randomTriangular(float min, float max, float mode) { + float u = random(); + float d = max - min; + if (u <= (mode - min) / d) return min + sqrt(u * d * (mode - min)); + return max - sqrt((1 - u) * d * (max - mode)); +} + +float MathUtil::pow(float a, float b) { + return (float) ::pow(a, b); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp new file mode 100644 index 0000000..da8cdd2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp @@ -0,0 +1,241 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL(MeshAttachment, VertexAttachment) + +MeshAttachment::MeshAttachment(const String &name) : VertexAttachment(name), + _parentMesh(NULL), + _path(), + _color(1, 1, 1, 1), + _hullLength(0), + _width(0), + _height(0), + _region(NULL), + _sequence(NULL) {} + +MeshAttachment::~MeshAttachment() { + if (_sequence) delete _sequence; +} + +void MeshAttachment::updateRegion() { + if (_uvs.size() != _regionUVs.size()) { + _uvs.setSize(_regionUVs.size(), 0); + } + + if (_region == nullptr) { + return; + } + + int i = 0, n = (int) _regionUVs.size(); + float u = _region->u, v = _region->v; + float width = 0, height = 0; + switch (_region->degrees) { + case 90: { + float textureWidth = _region->height / (_region->u2 - _region->u); + float textureHeight = _region->width / (_region->v2 - _region->v); + u -= (_region->originalHeight - _region->offsetY - _region->height) / textureWidth; + v -= (_region->originalWidth - _region->offsetX - _region->width) / textureHeight; + width = _region->originalHeight / textureWidth; + height = _region->originalWidth / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + _regionUVs[i + 1] * width; + _uvs[i + 1] = v + (1 - _regionUVs[i]) * height; + } + return; + } + case 180: { + float textureWidth = _region->width / (_region->u2 - _region->u); + float textureHeight = _region->height / (_region->v2 - _region->v); + u -= (_region->originalWidth - _region->offsetX - _region->width) / textureWidth; + v -= _region->offsetY / textureHeight; + width = _region->originalWidth / textureWidth; + height = _region->originalHeight / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + (1 - _regionUVs[i]) * width; + _uvs[i + 1] = v + (1 - _regionUVs[i + 1]) * height; + } + return; + } + case 270: { + float textureHeight = _region->height / (_region->v2 - _region->v); + float textureWidth = _region->width / (_region->u2 - _region->u); + u -= _region->offsetY / textureWidth; + v -= _region->offsetX / textureHeight; + width = _region->originalHeight / textureWidth; + height = _region->originalWidth / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + (1 - _regionUVs[i + 1]) * width; + _uvs[i + 1] = v + _regionUVs[i] * height; + } + return; + } + default: { + float textureWidth = _region->width / (_region->u2 - _region->u); + float textureHeight = _region->height / (_region->v2 - _region->v); + u -= _region->offsetX / textureWidth; + v -= (_region->originalHeight - _region->offsetY - _region->height) / textureHeight; + width = _region->originalWidth / textureWidth; + height = _region->originalHeight / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + _regionUVs[i] * width; + _uvs[i + 1] = v + _regionUVs[i + 1] * height; + } + } + } +} + +int MeshAttachment::getHullLength() { + return _hullLength; +} + +void MeshAttachment::setHullLength(int inValue) { + _hullLength = inValue; +} + +Vector &MeshAttachment::getRegionUVs() { + return _regionUVs; +} + +Vector &MeshAttachment::getUVs() { + return _uvs; +} + +Vector &MeshAttachment::getTriangles() { + return _triangles; +} + +const String &MeshAttachment::getPath() { + return _path; +} + +void MeshAttachment::setPath(const String &inValue) { + _path = inValue; +} + +TextureRegion *MeshAttachment::getRegion() { + return _region; +} + +void MeshAttachment::setRegion(TextureRegion *region) { + _region = region; +} + +Sequence *MeshAttachment::getSequence() { + return _sequence; +} + +void MeshAttachment::setSequence(Sequence *sequence) { + _sequence = sequence; +} + +MeshAttachment *MeshAttachment::getParentMesh() { + return _parentMesh; +} + +void MeshAttachment::setParentMesh(MeshAttachment *inValue) { + _parentMesh = inValue; + if (inValue != NULL) { + _bones.clearAndAddAll(inValue->_bones); + _vertices.clearAndAddAll(inValue->_vertices); + _worldVerticesLength = inValue->_worldVerticesLength; + _regionUVs.clearAndAddAll(inValue->_regionUVs); + _triangles.clearAndAddAll(inValue->_triangles); + _hullLength = inValue->_hullLength; + _edges.clearAndAddAll(inValue->_edges); + _width = inValue->_width; + _height = inValue->_height; + } +} + +Vector &MeshAttachment::getEdges() { + return _edges; +} + +float MeshAttachment::getWidth() { + return _width; +} + +void MeshAttachment::setWidth(float inValue) { + _width = inValue; +} + +float MeshAttachment::getHeight() { + return _height; +} + +void MeshAttachment::setHeight(float inValue) { + _height = inValue; +} + +spine::Color &MeshAttachment::getColor() { + return _color; +} + +Attachment *MeshAttachment::copy() { + if (_parentMesh) return newLinkedMesh(); + + MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName()); + copy->setRegion(_region); + copy->setSequence(_sequence != NULL ? _sequence->copy() : NULL); + copy->_path = _path; + copy->_color.set(_color); + + copyTo(copy); + copy->_regionUVs.clearAndAddAll(_regionUVs); + copy->_uvs.clearAndAddAll(_uvs); + copy->_triangles.clearAndAddAll(_triangles); + copy->_hullLength = _hullLength; + + // Nonessential. + copy->_edges.clearAndAddAll(copy->_edges); + copy->_width = _width; + copy->_height = _height; + return copy; +} + +MeshAttachment *MeshAttachment::newLinkedMesh() { + MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName()); + copy->setRegion(_region); + copy->_path = _path; + copy->_color.set(_color); + copy->_timelineAttachment = this->_timelineAttachment; + copy->setParentMesh(_parentMesh ? _parentMesh : this); + if (copy->_region) copy->updateRegion(); + return copy; +} + +void MeshAttachment::computeWorldVertices(Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride) { + if (_sequence) _sequence->apply(&slot, this); + VertexAttachment::computeWorldVertices(slot, start, count, worldVertices, offset, stride); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp new file mode 100644 index 0000000..35c0177 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp @@ -0,0 +1,71 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL(PathAttachment, VertexAttachment) + +PathAttachment::PathAttachment(const String &name) : VertexAttachment(name), _closed(false), _constantSpeed(false), + _color() { +} + +Vector &PathAttachment::getLengths() { + return _lengths; +} + +bool PathAttachment::isClosed() { + return _closed; +} + +void PathAttachment::setClosed(bool inValue) { + _closed = inValue; +} + +bool PathAttachment::isConstantSpeed() { + return _constantSpeed; +} + +void PathAttachment::setConstantSpeed(bool inValue) { + _constantSpeed = inValue; +} + +Color &PathAttachment::getColor() { + return _color; +} + +Attachment *PathAttachment::copy() { + PathAttachment *copy = new (__FILE__, __LINE__) PathAttachment(getName()); + copyTo(copy); + copy->_lengths.clearAndAddAll(_lengths); + copy->_closed = _closed; + copy->_constantSpeed = _constantSpeed; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp new file mode 100644 index 0000000..df399fd --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -0,0 +1,582 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraint, Updatable) + +const float PathConstraint::EPSILON = 0.00001f; +const int PathConstraint::NONE = -1; +const int PathConstraint::BEFORE = -2; +const int PathConstraint::AFTER = -3; + +PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : Updatable(), + _data(data), + _target(skeleton.findSlot( + data.getTarget()->getName())), + _position(data.getPosition()), + _spacing(data.getSpacing()), + _mixRotate(data.getMixRotate()), + _mixX(data.getMixX()), + _mixY(data.getMixY()), + _active(false) { + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); i++) { + BoneData *boneData = _data.getBones()[i]; + _bones.add(skeleton.findBone(boneData->getName())); + } + + _segments.setSize(10, 0); +} + +void PathConstraint::update() { + Attachment *baseAttachment = _target->getAttachment(); + if (baseAttachment == NULL || !baseAttachment->getRTTI().instanceOf(PathAttachment::rtti)) { + return; + } + PathAttachment *attachment = static_cast(baseAttachment); + + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY; + if (mixRotate == 0 && mixX == 0 && mixY == 0) return; + + PathConstraintData &data = _data; + bool tangents = data._rotateMode == RotateMode_Tangent, scale = data._rotateMode == RotateMode_ChainScale; + size_t boneCount = _bones.size(); + size_t spacesCount = tangents ? boneCount : boneCount + 1; + _spaces.setSize(spacesCount, 0); + if (scale) _lengths.setSize(boneCount, 0); + float spacing = _spacing; + + switch (data._spacingMode) { + case SpacingMode_Percent: { + if (scale) { + for (size_t i = 0, n = spacesCount - 1; i < n; i++) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + float setupLength = bone._data.getLength(); + if (setupLength < PathConstraint::EPSILON) { + _lengths[i] = 0; + } else { + float x = setupLength * bone._a, y = setupLength * bone._c; + _lengths[i] = MathUtil::sqrt(x * x + y * y); + } + } + } + for (size_t i = 1; i < spacesCount; ++i) { + _spaces[i] = spacing; + } + break; + } + case SpacingMode_Proportional: { + float sum = 0; + for (size_t i = 0, n = spacesCount - 1; i < n;) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + float setupLength = bone._data.getLength(); + if (setupLength < PathConstraint::EPSILON) { + if (scale) _lengths[i] = 0; + _spaces[++i] = spacing; + } else { + float x = setupLength * bone._a, y = setupLength * bone._c; + float length = MathUtil::sqrt(x * x + y * y); + if (scale) _lengths[i] = length; + _spaces[++i] = length; + sum += length; + } + } + if (sum > 0) { + sum = spacesCount / sum * spacing; + for (size_t i = 1; i < spacesCount; i++) { + _spaces[i] *= sum; + } + } + break; + } + default: { + bool lengthSpacing = data._spacingMode == SpacingMode_Length; + for (size_t i = 0, n = spacesCount - 1; i < n;) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + float setupLength = bone._data.getLength(); + if (setupLength < PathConstraint::EPSILON) { + if (scale) _lengths[i] = 0; + _spaces[++i] = spacing; + } else { + float x = setupLength * bone._a, y = setupLength * bone._c; + float length = MathUtil::sqrt(x * x + y * y); + if (scale) _lengths[i] = length; + _spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; + } + } + } + } + + Vector &positions = computeWorldPositions(*attachment, (int) spacesCount, tangents); + float boneX = positions[0]; + float boneY = positions[1]; + float offsetRotation = data.getOffsetRotation(); + bool tip; + if (offsetRotation == 0) { + tip = data._rotateMode == RotateMode_Chain; + } else { + tip = false; + Bone &p = _target->getBone(); + offsetRotation *= p.getA() * p.getD() - p.getB() * p.getC() > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; + } + + for (size_t i = 0, p = 3; i < boneCount; i++, p += 3) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + bone._worldX += (boneX - bone._worldX) * mixX; + bone._worldY += (boneY - bone._worldY) * mixY; + float x = positions[p]; + float y = positions[p + 1]; + float dx = x - boneX; + float dy = y - boneY; + if (scale) { + float length = _lengths[i]; + if (length >= PathConstraint::EPSILON) { + float s = (MathUtil::sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1; + bone._a *= s; + bone._c *= s; + } + } + + boneX = x; + boneY = y; + + if (mixRotate > 0) { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d, r, cos, sin; + if (tangents) + r = positions[p - 1]; + else if (_spaces[i + 1] < PathConstraint::EPSILON) + r = positions[p + 2]; + else + r = MathUtil::atan2(dy, dx); + + r -= MathUtil::atan2(c, a); + + if (tip) { + cos = MathUtil::cos(r); + sin = MathUtil::sin(r); + float length = bone._data.getLength(); + boneX += (length * (cos * a - sin * c) - dx) * mixRotate; + boneY += (length * (sin * a + cos * c) - dy) * mixRotate; + } else + r += offsetRotation; + + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r *= mixRotate; + cos = MathUtil::cos(r); + sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + } + + bone.updateAppliedTransform(); + } +} + +int PathConstraint::getOrder() { + return (int) _data.getOrder(); +} + +float PathConstraint::getPosition() { + return _position; +} + +void PathConstraint::setPosition(float inValue) { + _position = inValue; +} + +float PathConstraint::getSpacing() { + return _spacing; +} + +void PathConstraint::setSpacing(float inValue) { + _spacing = inValue; +} + +float PathConstraint::getMixRotate() { + return _mixRotate; +} + +void PathConstraint::setMixRotate(float inValue) { + _mixRotate = inValue; +} + +float PathConstraint::getMixX() { + return _mixX; +} + +void PathConstraint::setMixX(float inValue) { + _mixX = inValue; +} + +float PathConstraint::getMixY() { + return _mixY; +} + +void PathConstraint::setMixY(float inValue) { + _mixY = inValue; +} + +Vector &PathConstraint::getBones() { + return _bones; +} + +Slot *PathConstraint::getTarget() { + return _target; +} + +void PathConstraint::setTarget(Slot *inValue) { + _target = inValue; +} + +PathConstraintData &PathConstraint::getData() { + return _data; +} + +Vector & +PathConstraint::computeWorldPositions(PathAttachment &path, int spacesCount, bool tangents) { + Slot &target = *_target; + float position = _position; + _positions.setSize(spacesCount * 3 + 2, 0); + Vector &out = _positions; + Vector &world = _world; + bool closed = path.isClosed(); + int verticesLength = (int) path.getWorldVerticesLength(); + int curveCount = verticesLength / 6; + int prevCurve = NONE; + + float pathLength; + if (!path.isConstantSpeed()) { + Vector &lengths = path.getLengths(); + curveCount -= closed ? 1 : 2; + pathLength = lengths[curveCount]; + if (_data._positionMode == PositionMode_Percent) position *= pathLength; + + float multiplier = 0; + switch (_data._spacingMode) { + case SpacingMode_Percent: + multiplier = pathLength; + break; + case SpacingMode_Proportional: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + + world.setSize(8, 0); + for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + float space = _spaces[i] * multiplier; + position += space; + float p = position; + + if (closed) { + p = MathUtil::fmod(p, pathLength); + if (p < 0) p += pathLength; + curve = 0; + } else if (p < 0) { + if (prevCurve != BEFORE) { + prevCurve = BEFORE; + path.computeWorldVertices(target, 2, 4, world, 0); + } + + addBeforePosition(p, world, 0, out, o); + + continue; + } else if (p > pathLength) { + if (prevCurve != AFTER) { + prevCurve = AFTER; + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0); + } + + addAfterPosition(p - pathLength, world, 0, out, o); + + continue; + } + + // Determine curve containing position. + for (;; curve++) { + float length = lengths[curve]; + if (p > length) continue; + + if (curve == 0) + p /= length; + else { + float prev = lengths[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + + if (curve != prevCurve) { + prevCurve = curve; + if (closed && curve == curveCount) { + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0); + path.computeWorldVertices(target, 0, 4, world, 4); + } else + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0); + } + + addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], + out, o, tangents || (i > 0 && space < EPSILON)); + } + return out; + } + + // World vertices. + if (closed) { + verticesLength += 2; + world.setSize(verticesLength, 0); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } else { + curveCount--; + verticesLength -= 4; + world.setSize(verticesLength, 0); + path.computeWorldVertices(target, 2, verticesLength, world, 0); + } + + // Curve lengths. + _curves.setSize(curveCount, 0); + pathLength = 0; + float x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy; + for (int i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875f; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875f; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375f; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375f; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f; + dfy = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + + if (_data._positionMode == PositionMode_Percent) position *= pathLength; + + float multiplier = 0; + switch (_data._spacingMode) { + case SpacingMode_Percent: + multiplier = pathLength; + break; + case SpacingMode_Proportional: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + + float curveLength = 0; + for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + float space = _spaces[i] * multiplier; + position += space; + float p = position; + + if (closed) { + p = MathUtil::fmod(p, pathLength); + if (p < 0) p += pathLength; + curve = 0; + } else if (p < 0) { + addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength) { + addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + + // Determine curve containing position. + for (;; curve++) { + float length = _curves[curve]; + if (p > length) continue; + if (curve == 0) + p /= length; + else { + float prev = _curves[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + + // Curve segment lengths. + if (curve != prevCurve) { + prevCurve = curve; + int ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03f; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03f; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006f; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006f; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f; + dfy = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f; + curveLength = MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[9] = curveLength; + segment = 0; + } + + // Weight by segment length. + p *= curveLength; + for (;; segment++) { + float length = _segments[segment]; + if (p > length) continue; + if (segment == 0) + p /= length; + else { + float prev = _segments[segment - 1]; + p = segment + (p - prev) / (length - prev); + } + break; + } + addCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, + tangents || (i > 0 && space < EPSILON)); + } + + return out; +} + +void PathConstraint::addBeforePosition(float p, Vector &temp, int i, Vector &output, int o) { + float x1 = temp[i]; + float y1 = temp[i + 1]; + float dx = temp[i + 2] - x1; + float dy = temp[i + 3] - y1; + float r = MathUtil::atan2(dy, dx); + output[o] = x1 + p * MathUtil::cos(r); + output[o + 1] = y1 + p * MathUtil::sin(r); + output[o + 2] = r; +} + +void PathConstraint::addAfterPosition(float p, Vector &temp, int i, Vector &output, int o) { + float x1 = temp[i + 2]; + float y1 = temp[i + 3]; + float dx = x1 - temp[i]; + float dy = y1 - temp[i + 1]; + float r = MathUtil::atan2(dy, dx); + output[o] = x1 + p * MathUtil::cos(r); + output[o + 1] = y1 + p * MathUtil::sin(r); + output[o + 2] = r; +} + +void PathConstraint::addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, + float y2, Vector &output, int o, bool tangents) { + if (p < EPSILON || MathUtil::isNan(p)) { + output[o] = x1; + output[o + 1] = y1; + output[o + 2] = MathUtil::atan2(cy1 - y1, cx1 - x1); + return; + } + + float tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + float ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + float x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + output[o] = x; + output[o + 1] = y; + if (tangents) { + if (p < 0.001) + output[o + 2] = MathUtil::atan2(cy1 - y1, cx1 - x1); + else + output[o + 2] = MathUtil::atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), + x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } +} + +bool PathConstraint::isActive() { + return _active; +} + +void PathConstraint::setActive(bool inValue) { + _active = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp new file mode 100644 index 0000000..d8bd175 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -0,0 +1,136 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintData, ConstraintData) + +PathConstraintData::PathConstraintData(const String &name) : ConstraintData(name), + _target(NULL), + _positionMode(PositionMode_Fixed), + _spacingMode(SpacingMode_Length), + _rotateMode(RotateMode_Tangent), + _offsetRotation(0), + _position(0), + _spacing(0), + _mixRotate(0), + _mixX(0), + _mixY(0) { +} + +Vector &PathConstraintData::getBones() { + return _bones; +} + +SlotData *PathConstraintData::getTarget() { + return _target; +} + +void PathConstraintData::setTarget(SlotData *inValue) { + _target = inValue; +} + +PositionMode PathConstraintData::getPositionMode() { + return _positionMode; +} + +void PathConstraintData::setPositionMode(PositionMode inValue) { + _positionMode = inValue; +} + +SpacingMode PathConstraintData::getSpacingMode() { + return _spacingMode; +} + +void PathConstraintData::setSpacingMode(SpacingMode inValue) { + _spacingMode = inValue; +} + +RotateMode PathConstraintData::getRotateMode() { + return _rotateMode; +} + +void PathConstraintData::setRotateMode(RotateMode inValue) { + _rotateMode = inValue; +} + +float PathConstraintData::getOffsetRotation() { + return _offsetRotation; +} + +void PathConstraintData::setOffsetRotation(float inValue) { + _offsetRotation = inValue; +} + +float PathConstraintData::getPosition() { + return _position; +} + +void PathConstraintData::setPosition(float inValue) { + _position = inValue; +} + +float PathConstraintData::getSpacing() { + return _spacing; +} + +void PathConstraintData::setSpacing(float inValue) { + _spacing = inValue; +} + +float PathConstraintData::getMixRotate() { + return _mixRotate; +} + +void PathConstraintData::setMixRotate(float inValue) { + _mixRotate = inValue; +} + +float PathConstraintData::getMixX() { + return _mixX; +} + +void PathConstraintData::setMixX(float inValue) { + _mixX = inValue; +} + +float PathConstraintData::getMixY() { + return _mixY; +} + +void PathConstraintData::setMixY(float inValue) { + _mixY = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp new file mode 100644 index 0000000..8702d88 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -0,0 +1,126 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline) + +PathConstraintMixTimeline::PathConstraintMixTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex) + : CurveTimeline(frameCount, PathConstraintMixTimeline::ENTRIES, bezierCount), + _pathConstraintIndex(pathConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_PathConstraintMix << 32) | pathConstraintIndex}; + setPropertyIds(ids, 1); +} + +void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; + PathConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._mixRotate = constraint._data._mixRotate; + constraint._mixX = constraint._data._mixX; + constraint._mixY = constraint._data._mixY; + return; + case MixBlend_First: + constraint._mixRotate += (constraint._data._mixRotate - constraint._mixRotate) * alpha; + constraint._mixX += (constraint._data._mixX - constraint._mixX) * alpha; + constraint._mixY += (constraint._data._mixY - constraint._mixY) * alpha; + default: { + } + } + return; + } + + float rotate, x, y; + int i = Animation::search(_frames, time, PathConstraintMixTimeline::ENTRIES); + int curveType = (int) _curves[i >> 2]; + switch (curveType) { + case LINEAR: { + float before = _frames[i]; + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + float t = (time - before) / (_frames[i + ENTRIES] - before); + rotate += (_frames[i + ENTRIES + ROTATE] - rotate) * t; + x += (_frames[i + ENTRIES + X] - x) * t; + y += (_frames[i + ENTRIES + Y] - y) * t; + break; + } + case STEPPED: { + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + break; + } + default: { + rotate = getBezierValue(time, i, ROTATE, curveType - BEZIER); + x = getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER); + y = getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER); + } + } + + if (blend == MixBlend_Setup) { + PathConstraintData data = constraint._data; + constraint._mixRotate = data._mixRotate + (rotate - data._mixRotate) * alpha; + constraint._mixX = data._mixX + (x - data._mixX) * alpha; + constraint._mixY = data._mixY + (y - data._mixY) * alpha; + } else { + constraint._mixRotate += (rotate - constraint._mixRotate) * alpha; + constraint._mixX += (x - constraint._mixX) * alpha; + constraint._mixY += (y - constraint._mixY) * alpha; + } +} + +void PathConstraintMixTimeline::setFrame(int frame, float time, float mixRotate, float mixX, float mixY) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + ROTATE] = mixRotate; + _frames[frame + X] = mixX; + _frames[frame + Y] = mixY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp new file mode 100644 index 0000000..49b79a5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -0,0 +1,87 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline1) + +PathConstraintPositionTimeline::PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, + int pathConstraintIndex) : CurveTimeline1(frameCount, + bezierCount), + _pathConstraintIndex( + pathConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_PathConstraintPosition << 32) | pathConstraintIndex}; + setPropertyIds(ids, 1); +} + +PathConstraintPositionTimeline::~PathConstraintPositionTimeline() { +} + +void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; + PathConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._position = constraint._data._position; + return; + case MixBlend_First: + constraint._position += (constraint._data._position - constraint._position) * alpha; + return; + default: + return; + } + } + + float position = getCurveValue(time); + + if (blend == MixBlend_Setup) + constraint._position = constraint._data._position + (position - constraint._data._position) * alpha; + else + constraint._position += (position - constraint._position) * alpha; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp new file mode 100644 index 0000000..7494e14 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -0,0 +1,84 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline) + +PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(size_t frameCount, size_t bezierCount, + int pathConstraintIndex) : CurveTimeline1(frameCount, + bezierCount), + _pathConstraintIndex( + pathConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_PathConstraintSpacing << 32) | pathConstraintIndex}; + setPropertyIds(ids, 1); +} + +void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; + PathConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._spacing = constraint._data._spacing; + return; + case MixBlend_First: + constraint._spacing += (constraint._data._spacing - constraint._spacing) * alpha; + return; + default: + return; + } + } + + float spacing = getCurveValue(time); + + if (blend == MixBlend_Setup) + constraint._spacing = constraint._data._spacing + (spacing - constraint._data._spacing) * alpha; + else + constraint._spacing += (spacing - constraint._spacing) * alpha; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp new file mode 100644 index 0000000..64ea89b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp @@ -0,0 +1,90 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +#include + +using namespace spine; + +RTTI_IMPL(PointAttachment, Attachment) + +PointAttachment::PointAttachment(const String &name) : Attachment(name), _x(0), _y(0), _rotation(0), _color() { +} + +void PointAttachment::computeWorldPosition(Bone &bone, float &ox, float &oy) { + bone.localToWorld(_x, _y, ox, oy); +} + +float PointAttachment::computeWorldRotation(Bone &bone) { + float cos = MathUtil::cosDeg(_rotation); + float sin = MathUtil::sinDeg(_rotation); + float ix = cos * bone._a + sin * bone._b; + float iy = cos * bone._c + sin * bone._d; + + return MathUtil::atan2(iy, ix) * MathUtil::Rad_Deg; +} + +float PointAttachment::getX() { + return _x; +} + +void PointAttachment::setX(float inValue) { + _x = inValue; +} + +float PointAttachment::getY() { + return _y; +} + +void PointAttachment::setY(float inValue) { + _y = inValue; +} + +float PointAttachment::getRotation() { + return _rotation; +} + +void PointAttachment::setRotation(float inValue) { + _rotation = inValue; +} + +Color &PointAttachment::getColor() { + return _color; +} + +Attachment *PointAttachment::copy() { + PointAttachment *copy = new (__FILE__, __LINE__) PointAttachment(getName()); + copy->_x = _x; + copy->_y = _y; + copy->_rotation = _rotation; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/RTTI.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/RTTI.cpp new file mode 100644 index 0000000..e8dbb94 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/RTTI.cpp @@ -0,0 +1,56 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +using namespace spine; + +RTTI::RTTI(const char *className) : _className(className), _pBaseRTTI(NULL) { +} + +RTTI::RTTI(const char *className, const RTTI &baseRTTI) : _className(className), _pBaseRTTI(&baseRTTI) { +} + +const char *RTTI::getClassName() const { + return _className; +} + +bool RTTI::isExactly(const RTTI &rtti) const { + return !strcmp(this->_className, rtti._className); +} + +bool RTTI::instanceOf(const RTTI &rtti) const { + const RTTI *pCompare = this; + while (pCompare) { + if (!strcmp(pCompare->_className, rtti._className)) return true; + pCompare = pCompare->_pBaseRTTI; + } + return false; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp new file mode 100644 index 0000000..f669b65 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -0,0 +1,275 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(RegionAttachment, Attachment) + +const int RegionAttachment::BLX = 0; +const int RegionAttachment::BLY = 1; +const int RegionAttachment::ULX = 2; +const int RegionAttachment::ULY = 3; +const int RegionAttachment::URX = 4; +const int RegionAttachment::URY = 5; +const int RegionAttachment::BRX = 6; +const int RegionAttachment::BRY = 7; + +RegionAttachment::RegionAttachment(const String &name) : Attachment(name), + _x(0), + _y(0), + _rotation(0), + _scaleX(1), + _scaleY(1), + _width(0), + _height(0), + _path(), + _color(1, 1, 1, 1), + _region(NULL), + _sequence(NULL) { + _vertexOffset.setSize(NUM_UVS, 0); + _uvs.setSize(NUM_UVS, 0); +} + +RegionAttachment::~RegionAttachment() { + if (_sequence) delete _sequence; +} + +void RegionAttachment::updateRegion() { + if (_region == NULL) { + _uvs[BLX] = 0; + _uvs[BLY] = 0; + _uvs[ULX] = 0; + _uvs[ULY] = 1; + _uvs[URX] = 1; + _uvs[URY] = 1; + _uvs[BRX] = 1; + _uvs[BRY] = 0; + return; + } + + float regionScaleX = _width / _region->originalWidth * _scaleX; + float regionScaleY = _height / _region->originalHeight * _scaleY; + float localX = -_width / 2 * _scaleX + _region->offsetX * regionScaleX; + float localY = -_height / 2 * _scaleY + _region->offsetY * regionScaleY; + float localX2 = localX + _region->width * regionScaleX; + float localY2 = localY + _region->height * regionScaleY; + float cos = MathUtil::cosDeg(_rotation); + float sin = MathUtil::sinDeg(_rotation); + float localXCos = localX * cos + _x; + float localXSin = localX * sin; + float localYCos = localY * cos + _y; + float localYSin = localY * sin; + float localX2Cos = localX2 * cos + _x; + float localX2Sin = localX2 * sin; + float localY2Cos = localY2 * cos + _y; + float localY2Sin = localY2 * sin; + + _vertexOffset[BLX] = localXCos - localYSin; + _vertexOffset[BLY] = localYCos + localXSin; + _vertexOffset[ULX] = localXCos - localY2Sin; + _vertexOffset[ULY] = localY2Cos + localXSin; + _vertexOffset[URX] = localX2Cos - localY2Sin; + _vertexOffset[URY] = localY2Cos + localX2Sin; + _vertexOffset[BRX] = localX2Cos - localYSin; + _vertexOffset[BRY] = localYCos + localX2Sin; + + if (_region->degrees == 90) { + _uvs[URX] = _region->u; + _uvs[URY] = _region->v2; + _uvs[BRX] = _region->u; + _uvs[BRY] = _region->v; + _uvs[BLX] = _region->u2; + _uvs[BLY] = _region->v; + _uvs[ULX] = _region->u2; + _uvs[ULY] = _region->v2; + } else { + _uvs[ULX] = _region->u; + _uvs[ULY] = _region->v2; + _uvs[URX] = _region->u; + _uvs[URY] = _region->v; + _uvs[BRX] = _region->u2; + _uvs[BRY] = _region->v; + _uvs[BLX] = _region->u2; + _uvs[BLY] = _region->v2; + } +} + +void RegionAttachment::computeWorldVertices(Slot &slot, Vector &worldVertices, size_t offset, size_t stride) { + assert(worldVertices.size() >= (offset + 8)); + computeWorldVertices(slot, worldVertices.buffer(), offset, stride); +} + +void RegionAttachment::computeWorldVertices(Slot &slot, float *worldVertices, size_t offset, size_t stride) { + if (_sequence) _sequence->apply(&slot, this); + + Bone &bone = slot.getBone(); + float x = bone.getWorldX(), y = bone.getWorldY(); + float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD(); + float offsetX, offsetY; + + offsetX = _vertexOffset[BRX]; + offsetY = _vertexOffset[BRY]; + worldVertices[offset] = offsetX * a + offsetY * b + x;// br + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = _vertexOffset[BLX]; + offsetY = _vertexOffset[BLY]; + worldVertices[offset] = offsetX * a + offsetY * b + x;// bl + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = _vertexOffset[ULX]; + offsetY = _vertexOffset[ULY]; + worldVertices[offset] = offsetX * a + offsetY * b + x;// ul + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = _vertexOffset[URX]; + offsetY = _vertexOffset[URY]; + worldVertices[offset] = offsetX * a + offsetY * b + x;// ur + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; +} + +float RegionAttachment::getX() { + return _x; +} + +void RegionAttachment::setX(float inValue) { + _x = inValue; +} + +float RegionAttachment::getY() { + return _y; +} + +void RegionAttachment::setY(float inValue) { + _y = inValue; +} + +float RegionAttachment::getRotation() { + return _rotation; +} + +void RegionAttachment::setRotation(float inValue) { + _rotation = inValue; +} + +float RegionAttachment::getScaleX() { + return _scaleX; +} + +void RegionAttachment::setScaleX(float inValue) { + _scaleX = inValue; +} + +float RegionAttachment::getScaleY() { + return _scaleY; +} + +void RegionAttachment::setScaleY(float inValue) { + _scaleY = inValue; +} + +float RegionAttachment::getWidth() { + return _width; +} + +void RegionAttachment::setWidth(float inValue) { + _width = inValue; +} + +float RegionAttachment::getHeight() { + return _height; +} + +void RegionAttachment::setHeight(float inValue) { + _height = inValue; +} + +const String &RegionAttachment::getPath() { + return _path; +} + +void RegionAttachment::setPath(const String &inValue) { + _path = inValue; +} + +TextureRegion *RegionAttachment::getRegion() { + return _region; +} + +void RegionAttachment::setRegion(TextureRegion *region) { + _region = region; +} + +Sequence *RegionAttachment::getSequence() { + return _sequence; +} + +void RegionAttachment::setSequence(Sequence *sequence) { + _sequence = sequence; +} + +Vector &RegionAttachment::getOffset() { + return _vertexOffset; +} + +Vector &RegionAttachment::getUVs() { + return _uvs; +} + +spine::Color &RegionAttachment::getColor() { + return _color; +} + +Attachment *RegionAttachment::copy() { + RegionAttachment *copy = new (__FILE__, __LINE__) RegionAttachment(getName()); + copy->_region = _region; + copy->_path = _path; + copy->_x = _x; + copy->_y = _y; + copy->_scaleX = _scaleX; + copy->_scaleY = _scaleY; + copy->_rotation = _rotation; + copy->_width = _width; + copy->_height = _height; + copy->_uvs.clearAndAddAll(_uvs); + copy->_vertexOffset.clearAndAddAll(_vertexOffset); + copy->_color.set(_color); + copy->_sequence = _sequence != NULL ? _sequence->copy() : NULL; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp new file mode 100644 index 0000000..230a276 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -0,0 +1,84 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(RotateTimeline, CurveTimeline1) + +RotateTimeline::RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_Rotate << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_rotation = bone->_data._rotation; + return; + case MixBlend_First: + bone->_rotation += (bone->_data._rotation - bone->_rotation) * alpha; + default: { + } + } + return; + } + + float r = getCurveValue(time); + switch (blend) { + case MixBlend_Setup: + bone->_rotation = bone->_data._rotation + r * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + r += bone->_data._rotation - bone->_rotation; + case MixBlend_Add: + bone->_rotation += r * alpha; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp new file mode 100644 index 0000000..88d66bc --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -0,0 +1,300 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(ScaleTimeline, CurveTimeline2) + +ScaleTimeline::ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ScaleX << 32) | boneIndex, + ((PropertyId) Property_ScaleY << 32) | boneIndex}; + setPropertyIds(ids, 2); +} + +ScaleTimeline::~ScaleTimeline() {} + +void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_scaleX = bone->_data._scaleX; + bone->_scaleY = bone->_data._scaleY; + return; + case MixBlend_First: + bone->_scaleX += (bone->_data._scaleX - bone->_scaleX) * alpha; + bone->_scaleY += (bone->_data._scaleY - bone->_scaleY) * alpha; + default: { + } + } + return; + } + + float x, y; + int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES); + int curveType = (int) _curves[i / CurveTimeline2::ENTRIES]; + switch (curveType) { + case CurveTimeline::LINEAR: { + float before = _frames[i]; + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before); + x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t; + y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t; + break; + } + case CurveTimeline::STEPPED: { + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + break; + } + default: { + x = getBezierValue(time, i, CurveTimeline2::VALUE1, curveType - CurveTimeline2::BEZIER); + y = getBezierValue(time, i, CurveTimeline2::VALUE2, + curveType + CurveTimeline2::BEZIER_SIZE - CurveTimeline2::BEZIER); + } + } + x *= bone->_data._scaleX; + y *= bone->_data._scaleY; + + if (alpha == 1) { + if (blend == MixBlend_Add) { + bone->_scaleX += x - bone->_data._scaleX; + bone->_scaleY += y - bone->_data._scaleY; + } else { + bone->_scaleX = x; + bone->_scaleY = y; + } + } else { + float bx, by; + if (direction == MixDirection_Out) { + switch (blend) { + case MixBlend_Setup: + bx = bone->_data._scaleX; + by = bone->_data._scaleY; + bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; + bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bx = bone->_scaleX; + by = bone->_scaleY; + bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; + bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; + break; + case MixBlend_Add: + bone->_scaleX += (x - bone->_data._scaleX) * alpha; + bone->_scaleY += (y - bone->_data._scaleY) * alpha; + } + } else { + switch (blend) { + case MixBlend_Setup: + bx = MathUtil::abs(bone->_data._scaleX) * MathUtil::sign(x); + by = MathUtil::abs(bone->_data._scaleY) * MathUtil::sign(y); + bone->_scaleX = bx + (x - bx) * alpha; + bone->_scaleY = by + (y - by) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bx = MathUtil::abs(bone->_scaleX) * MathUtil::sign(x); + by = MathUtil::abs(bone->_scaleY) * MathUtil::sign(y); + bone->_scaleX = bx + (x - bx) * alpha; + bone->_scaleY = by + (y - by) * alpha; + break; + case MixBlend_Add: + bone->_scaleX += (x - bone->_data._scaleX) * alpha; + bone->_scaleY += (y - bone->_data._scaleY) * alpha; + } + } + } +} + +RTTI_IMPL(ScaleXTimeline, CurveTimeline1) + +ScaleXTimeline::ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ScaleX << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +ScaleXTimeline::~ScaleXTimeline() {} + +void ScaleXTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_scaleX = bone->_data._scaleX; + return; + case MixBlend_First: + bone->_scaleX += (bone->_data._scaleX - bone->_scaleX) * alpha; + default: { + } + } + return; + } + + float x = getCurveValue(time) * bone->_data._scaleX; + if (alpha == 1) { + if (blend == MixBlend_Add) + bone->_scaleX += x - bone->_data._scaleX; + else + bone->_scaleX = x; + } else { + // Mixing out uses sign of setup or current pose, else use sign of key. + float bx; + if (direction == MixDirection_Out) { + switch (blend) { + case MixBlend_Setup: + bx = bone->_data._scaleX; + bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bx = bone->_scaleX; + bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; + break; + case MixBlend_Add: + bone->_scaleX += (x - bone->_data._scaleX) * alpha; + } + } else { + switch (blend) { + case MixBlend_Setup: + bx = MathUtil::abs(bone->_data._scaleX) * MathUtil::sign(x); + bone->_scaleX = bx + (x - bx) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bx = MathUtil::abs(bone->_scaleX) * MathUtil::sign(x); + bone->_scaleX = bx + (x - bx) * alpha; + break; + case MixBlend_Add: + bone->_scaleX += (x - bone->_data._scaleX) * alpha; + } + } + } +} + +RTTI_IMPL(ScaleYTimeline, CurveTimeline1) + +ScaleYTimeline::ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ScaleY << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +ScaleYTimeline::~ScaleYTimeline() {} + +void ScaleYTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_scaleY = bone->_data._scaleY; + return; + case MixBlend_First: + bone->_scaleY += (bone->_data._scaleY - bone->_scaleY) * alpha; + default: { + } + } + return; + } + + float y = getCurveValue(time) * bone->_data._scaleY; + if (alpha == 1) { + if (blend == MixBlend_Add) + bone->_scaleY += y - bone->_data._scaleY; + else + bone->_scaleY = y; + } else { + // Mixing out uses sign of setup or current pose, else use sign of key. + float by = 0; + if (direction == MixDirection_Out) { + switch (blend) { + case MixBlend_Setup: + by = bone->_data._scaleY; + bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + by = bone->_scaleY; + bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; + break; + case MixBlend_Add: + bone->_scaleY += (y - bone->_data._scaleY) * alpha; + } + } else { + switch (blend) { + case MixBlend_Setup: + by = MathUtil::abs(bone->_data._scaleY) * MathUtil::sign(y); + bone->_scaleY = by + (y - by) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + by = MathUtil::abs(bone->_scaleY) * MathUtil::sign(y); + bone->_scaleY = by + (y - by) * alpha; + break; + case MixBlend_Add: + bone->_scaleY += (y - bone->_data._scaleY) * alpha; + } + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Sequence.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Sequence.cpp new file mode 100644 index 0000000..e1844b3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Sequence.cpp @@ -0,0 +1,96 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include + +using namespace spine; + +Sequence::Sequence(int count) : _id(Sequence::getNextID()), + _regions(), + _start(0), + _digits(0), + _setupIndex(0) { + _regions.setSize(count, NULL); +} + +Sequence::~Sequence() { +} + +Sequence *Sequence::copy() { + Sequence *copy = new (__FILE__, __LINE__) Sequence((int) _regions.size()); + for (size_t i = 0; i < _regions.size(); i++) { + copy->_regions[i] = _regions[i]; + } + copy->_start = _start; + copy->_digits = _digits; + copy->_setupIndex = _setupIndex; + return copy; +} + +void Sequence::apply(Slot *slot, Attachment *attachment) { + int index = slot->getSequenceIndex(); + if (index == -1) index = _setupIndex; + if (index >= (int) _regions.size()) index = (int) _regions.size() - 1; + TextureRegion *region = _regions[index]; + + if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) { + RegionAttachment *regionAttachment = static_cast(attachment); + if (regionAttachment->getRegion() != region) { + regionAttachment->setRegion(region); + regionAttachment->updateRegion(); + } + } + + if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) { + MeshAttachment *meshAttachment = static_cast(attachment); + if (meshAttachment->getRegion() != region) { + meshAttachment->setRegion(region); + meshAttachment->updateRegion(); + } + } +} + +String Sequence::getPath(const String &basePath, int index) { + String result(basePath); + String frame; + frame.append(_start + index); + for (int i = _digits - (int) frame.length(); i > 0; i--) + result.append("0"); + result.append(frame); + return result; +} + +int Sequence::getNextID() { + static int _nextID = 0; + return _nextID; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp new file mode 100644 index 0000000..c13acfe --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp @@ -0,0 +1,124 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(SequenceTimeline, Timeline) + +SequenceTimeline::SequenceTimeline(size_t frameCount, int slotIndex, Attachment *attachment) : Timeline(frameCount, ENTRIES), _slotIndex(slotIndex), _attachment(attachment) { + int sequenceId = 0; + if (attachment->getRTTI().instanceOf(RegionAttachment::rtti)) sequenceId = ((RegionAttachment *) attachment)->getSequence()->getId(); + if (attachment->getRTTI().instanceOf(MeshAttachment::rtti)) sequenceId = ((MeshAttachment *) attachment)->getSequence()->getId(); + PropertyId ids[] = {((PropertyId) Property_Sequence << 32) | ((slotIndex << 16 | sequenceId) & 0xffffffff)}; + setPropertyIds(ids, 1); +} + +SequenceTimeline::~SequenceTimeline() { +} + +void SequenceTimeline::setFrame(int frame, float time, SequenceMode mode, int index, float delay) { + Vector &frames = this->_frames; + frame *= ENTRIES; + frames[frame] = time; + frames[frame + MODE] = mode | (index << 4); + frames[frame + DELAY] = delay; +} + +void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction) { + SP_UNUSED(alpha); + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton.getSlots()[_slotIndex]; + if (!slot->getBone().isActive()) return; + Attachment *slotAttachment = slot->getAttachment(); + if (slotAttachment != _attachment) { + if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti) || ((VertexAttachment *) slotAttachment)->getTimelineAttachment() != _attachment) return; + } + + Vector &frames = this->_frames; + if (time < frames[0]) {// Time is before first frame. + if (blend == MixBlend_Setup || blend == MixBlend_First) slot->setSequenceIndex(-1); + return; + } + + int i = Animation::search(frames, time, ENTRIES); + float before = frames[i]; + int modeAndIndex = (int) frames[i + MODE]; + float delay = frames[i + DELAY]; + + Sequence *sequence = NULL; + if (_attachment->getRTTI().instanceOf(RegionAttachment::rtti)) sequence = ((RegionAttachment *) _attachment)->getSequence(); + if (_attachment->getRTTI().instanceOf(MeshAttachment::rtti)) sequence = ((MeshAttachment *) _attachment)->getSequence(); + if (!sequence) return; + int index = modeAndIndex >> 4, count = (int) sequence->getRegions().size(); + int mode = modeAndIndex & 0xf; + if (mode != SequenceMode::hold) { + index += (int) (((time - before) / delay + 0.00001)); + switch (mode) { + case SequenceMode::once: + index = MathUtil::min(count - 1, index); + break; + case SequenceMode::loop: + index %= count; + break; + case SequenceMode::pingpong: { + int n = (count << 1) - 2; + index = n == 0 ? 0 : index % n; + if (index >= count) index = n - index; + break; + } + case SequenceMode::onceReverse: + index = MathUtil::max(count - 1 - index, 0); + break; + case SequenceMode::loopReverse: + index = count - 1 - (index % count); + break; + case SequenceMode::pingpongReverse: { + int n = (count << 1) - 2; + index = n == 0 ? 0 : (index + count - 1) % n; + if (index >= count) index = n - index; + } + } + } + slot->setSequenceIndex(index); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp new file mode 100644 index 0000000..c1d097b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -0,0 +1,214 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(ShearTimeline, CurveTimeline2) + +ShearTimeline::ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ShearX << 32) | boneIndex, + ((PropertyId) Property_ShearY << 32) | boneIndex}; + setPropertyIds(ids, 2); +} + +ShearTimeline::~ShearTimeline() { +} + +void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_shearX = bone->_data._shearX; + bone->_shearY = bone->_data._shearY; + return; + case MixBlend_First: + bone->_shearX += (bone->_data._shearX - bone->_shearX) * alpha; + bone->_shearY += (bone->_data._shearY - bone->_shearY) * alpha; + default: { + } + } + return; + } + + float x, y; + int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES); + int curveType = (int) _curves[i / CurveTimeline2::ENTRIES]; + switch (curveType) { + case CurveTimeline2::LINEAR: { + float before = _frames[i]; + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before); + x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t; + y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t; + break; + } + case CurveTimeline2::STEPPED: { + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + break; + } + default: { + x = getBezierValue(time, i, CurveTimeline2::VALUE1, curveType - CurveTimeline2::BEZIER); + y = getBezierValue(time, i, CurveTimeline2::VALUE2, + curveType + CurveTimeline2::BEZIER_SIZE - CurveTimeline2::BEZIER); + } + } + + switch (blend) { + case MixBlend_Setup: + bone->_shearX = bone->_data._shearX + x * alpha; + bone->_shearY = bone->_data._shearY + y * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_shearX += (bone->_data._shearX + x - bone->_shearX) * alpha; + bone->_shearY += (bone->_data._shearY + y - bone->_shearY) * alpha; + break; + case MixBlend_Add: + bone->_shearX += x * alpha; + bone->_shearY += y * alpha; + } +} + +RTTI_IMPL(ShearXTimeline, CurveTimeline1) + +ShearXTimeline::ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ShearX << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +ShearXTimeline::~ShearXTimeline() { +} + +void ShearXTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_shearX = bone->_data._shearX; + return; + case MixBlend_First: + bone->_shearX += (bone->_data._shearX - bone->_shearX) * alpha; + default: { + } + } + return; + } + + float x = getCurveValue(time); + switch (blend) { + case MixBlend_Setup: + bone->_shearX = bone->_data._shearX + x * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_shearX += (bone->_data._shearX + x - bone->_shearX) * alpha; + break; + case MixBlend_Add: + bone->_shearX += x * alpha; + } +} + +RTTI_IMPL(ShearYTimeline, CurveTimeline1) + +ShearYTimeline::ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ShearX << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +ShearYTimeline::~ShearYTimeline() { +} + +void ShearYTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_shearY = bone->_data._shearY; + return; + case MixBlend_First: + bone->_shearY += (bone->_data._shearY - bone->_shearY) * alpha; + default: { + } + } + return; + } + + float y = getCurveValue(time); + switch (blend) { + case MixBlend_Setup: + bone->_shearY = bone->_data._shearY + y * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_shearY += (bone->_data._shearY + y - bone->_shearY) * alpha; + break; + case MixBlend_Add: + bone->_shearY += y * alpha; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Skeleton.cpp new file mode 100644 index 0000000..6b05f9e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -0,0 +1,685 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace spine; + +Skeleton::Skeleton(SkeletonData *skeletonData) : _data(skeletonData), + _skin(NULL), + _color(1, 1, 1, 1), + _scaleX(1), + _scaleY(1), + _x(0), + _y(0) { + _bones.ensureCapacity(_data->getBones().size()); + for (size_t i = 0; i < _data->getBones().size(); ++i) { + BoneData *data = _data->getBones()[i]; + + Bone *bone; + if (data->getParent() == NULL) { + bone = new (__FILE__, __LINE__) Bone(*data, *this, NULL); + } else { + Bone *parent = _bones[data->getParent()->getIndex()]; + bone = new (__FILE__, __LINE__) Bone(*data, *this, parent); + parent->getChildren().add(bone); + } + + _bones.add(bone); + } + + _slots.ensureCapacity(_data->getSlots().size()); + _drawOrder.ensureCapacity(_data->getSlots().size()); + for (size_t i = 0; i < _data->getSlots().size(); ++i) { + SlotData *data = _data->getSlots()[i]; + + Bone *bone = _bones[data->getBoneData().getIndex()]; + Slot *slot = new (__FILE__, __LINE__) Slot(*data, *bone); + + _slots.add(slot); + _drawOrder.add(slot); + } + + _ikConstraints.ensureCapacity(_data->getIkConstraints().size()); + for (size_t i = 0; i < _data->getIkConstraints().size(); ++i) { + IkConstraintData *data = _data->getIkConstraints()[i]; + + IkConstraint *constraint = new (__FILE__, __LINE__) IkConstraint(*data, *this); + + _ikConstraints.add(constraint); + } + + _transformConstraints.ensureCapacity(_data->getTransformConstraints().size()); + for (size_t i = 0; i < _data->getTransformConstraints().size(); ++i) { + TransformConstraintData *data = _data->getTransformConstraints()[i]; + + TransformConstraint *constraint = new (__FILE__, __LINE__) TransformConstraint(*data, *this); + + _transformConstraints.add(constraint); + } + + _pathConstraints.ensureCapacity(_data->getPathConstraints().size()); + for (size_t i = 0; i < _data->getPathConstraints().size(); ++i) { + PathConstraintData *data = _data->getPathConstraints()[i]; + + PathConstraint *constraint = new (__FILE__, __LINE__) PathConstraint(*data, *this); + + _pathConstraints.add(constraint); + } + + updateCache(); +} + +Skeleton::~Skeleton() { + ContainerUtil::cleanUpVectorOfPointers(_bones); + ContainerUtil::cleanUpVectorOfPointers(_slots); + ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); + ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); + ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); +} + +void Skeleton::updateCache() { + _updateCache.clear(); + + for (size_t i = 0, n = _bones.size(); i < n; ++i) { + Bone *bone = _bones[i]; + bone->_sorted = bone->_data.isSkinRequired(); + bone->_active = !bone->_sorted; + } + + if (_skin) { + Vector &skinBones = _skin->getBones(); + for (size_t i = 0, n = skinBones.size(); i < n; i++) { + Bone *bone = _bones[skinBones[i]->getIndex()]; + do { + bone->_sorted = false; + bone->_active = true; + bone = bone->_parent; + } while (bone); + } + } + + size_t ikCount = _ikConstraints.size(); + size_t transformCount = _transformConstraints.size(); + size_t pathCount = _pathConstraints.size(); + + size_t constraintCount = ikCount + transformCount + pathCount; + + size_t i = 0; +continue_outer: + for (; i < constraintCount; ++i) { + for (size_t ii = 0; ii < ikCount; ++ii) { + IkConstraint *constraint = _ikConstraints[ii]; + if (constraint->getData().getOrder() == i) { + sortIkConstraint(constraint); + i++; + goto continue_outer; + } + } + + for (size_t ii = 0; ii < transformCount; ++ii) { + TransformConstraint *constraint = _transformConstraints[ii]; + if (constraint->getData().getOrder() == i) { + sortTransformConstraint(constraint); + i++; + goto continue_outer; + } + } + + for (size_t ii = 0; ii < pathCount; ++ii) { + PathConstraint *constraint = _pathConstraints[ii]; + if (constraint->getData().getOrder() == i) { + sortPathConstraint(constraint); + i++; + goto continue_outer; + } + } + } + + size_t n = _bones.size(); + for (i = 0; i < n; ++i) { + sortBone(_bones[i]); + } +} + +void Skeleton::printUpdateCache() { + for (size_t i = 0; i < _updateCache.size(); i++) { + Updatable *updatable = _updateCache[i]; + if (updatable->getRTTI().isExactly(Bone::rtti)) { + printf("bone %s\n", ((Bone *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(TransformConstraint::rtti)) { + printf("transform constraint %s\n", ((TransformConstraint *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(IkConstraint::rtti)) { + printf("ik constraint %s\n", ((IkConstraint *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(PathConstraint::rtti)) { + printf("path constraint %s\n", ((PathConstraint *) updatable)->getData().getName().buffer()); + } + } +} + +void Skeleton::updateWorldTransform() { + for (size_t i = 0, n = _bones.size(); i < n; i++) { + Bone *bone = _bones[i]; + bone->_ax = bone->_x; + bone->_ay = bone->_y; + bone->_arotation = bone->_rotation; + bone->_ascaleX = bone->_scaleX; + bone->_ascaleY = bone->_scaleY; + bone->_ashearX = bone->_shearX; + bone->_ashearY = bone->_shearY; + } + + for (size_t i = 0, n = _updateCache.size(); i < n; ++i) { + _updateCache[i]->update(); + } +} + +void Skeleton::updateWorldTransform(Bone *parent) { + // Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection. + Bone &rootBone = *getRootBone(); + float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d; + rootBone._worldX = pa * _x + pb * _y + parent->_worldX; + rootBone._worldY = pc * _x + pd * _y + parent->_worldY; + + float rotationY = rootBone._rotation + 90 + rootBone._shearY; + float la = MathUtil::cosDeg(rootBone._rotation + rootBone._shearX) * rootBone._scaleX; + float lb = MathUtil::cosDeg(rotationY) * rootBone._scaleY; + float lc = MathUtil::sinDeg(rootBone._rotation + rootBone._shearX) * rootBone._scaleX; + float ld = MathUtil::sinDeg(rotationY) * rootBone._scaleY; + rootBone._a = (pa * la + pb * lc) * _scaleX; + rootBone._b = (pa * lb + pb * ld) * _scaleX; + rootBone._c = (pc * la + pd * lc) * _scaleY; + rootBone._d = (pc * lb + pd * ld) * _scaleY; + + // Update everything except root bone. + Bone *rb = getRootBone(); + for (size_t i = 0, n = _updateCache.size(); i < n; i++) { + Updatable *updatable = _updateCache[i]; + if (updatable != rb) updatable->update(); + } +} + +void Skeleton::setToSetupPose() { + setBonesToSetupPose(); + setSlotsToSetupPose(); +} + +void Skeleton::setBonesToSetupPose() { + for (size_t i = 0, n = _bones.size(); i < n; ++i) { + _bones[i]->setToSetupPose(); + } + + for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) { + IkConstraint *constraintP = _ikConstraints[i]; + IkConstraint &constraint = *constraintP; + + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + constraint._mix = constraint._data._mix; + constraint._softness = constraint._data._softness; + } + + for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) { + TransformConstraint *constraintP = _transformConstraints[i]; + TransformConstraint &constraint = *constraintP; + TransformConstraintData &constraintData = constraint._data; + + constraint._mixRotate = constraintData._mixRotate; + constraint._mixX = constraintData._mixX; + constraint._mixY = constraintData._mixY; + constraint._mixScaleX = constraintData._mixScaleX; + constraint._mixScaleY = constraintData._mixScaleY; + constraint._mixShearY = constraintData._mixShearY; + } + + for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) { + PathConstraint *constraintP = _pathConstraints[i]; + PathConstraint &constraint = *constraintP; + PathConstraintData &constraintData = constraint._data; + + constraint._position = constraintData._position; + constraint._spacing = constraintData._spacing; + constraint._mixRotate = constraintData._mixRotate; + constraint._mixX = constraintData._mixX; + constraint._mixY = constraintData._mixY; + } +} + +void Skeleton::setSlotsToSetupPose() { + _drawOrder.clear(); + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + _drawOrder.add(_slots[i]); + } + + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + _slots[i]->setToSetupPose(); + } +} + +Bone *Skeleton::findBone(const String &boneName) { + return ContainerUtil::findWithDataName(_bones, boneName); +} + +Slot *Skeleton::findSlot(const String &slotName) { + return ContainerUtil::findWithDataName(_slots, slotName); +} + +void Skeleton::setSkin(const String &skinName) { + Skin *foundSkin = skinName.isEmpty() ? NULL : _data->findSkin(skinName); + setSkin(foundSkin); +} + +void Skeleton::setSkin(Skin *newSkin) { + if (_skin == newSkin) return; + if (newSkin != NULL) { + if (_skin != NULL) { + Skeleton &thisRef = *this; + newSkin->attachAll(thisRef, *_skin); + } else { + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + Slot *slotP = _slots[i]; + Slot &slot = *slotP; + const String &name = slot._data.getAttachmentName(); + if (name.length() > 0) { + Attachment *attachment = newSkin->getAttachment(i, name); + if (attachment != NULL) { + slot.setAttachment(attachment); + } + } + } + } + } + + _skin = newSkin; + updateCache(); +} + +Attachment *Skeleton::getAttachment(const String &slotName, const String &attachmentName) { + return getAttachment(_data->findSlot(slotName)->getIndex(), attachmentName); +} + +Attachment *Skeleton::getAttachment(int slotIndex, const String &attachmentName) { + if (attachmentName.isEmpty()) return NULL; + + if (_skin != NULL) { + Attachment *attachment = _skin->getAttachment(slotIndex, attachmentName); + if (attachment != NULL) { + return attachment; + } + } + + return _data->getDefaultSkin() != NULL ? _data->getDefaultSkin()->getAttachment(slotIndex, attachmentName) : NULL; +} + +void Skeleton::setAttachment(const String &slotName, const String &attachmentName) { + assert(slotName.length() > 0); + + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + Slot *slot = _slots[i]; + if (slot->_data.getName() == slotName) { + Attachment *attachment = NULL; + if (attachmentName.length() > 0) { + attachment = getAttachment((int) i, attachmentName); + + assert(attachment != NULL); + } + + slot->setAttachment(attachment); + + return; + } + } + + printf("Slot not found: %s", slotName.buffer()); + + assert(false); +} + +IkConstraint *Skeleton::findIkConstraint(const String &constraintName) { + assert(constraintName.length() > 0); + + for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) { + IkConstraint *ikConstraint = _ikConstraints[i]; + if (ikConstraint->_data.getName() == constraintName) { + return ikConstraint; + } + } + return NULL; +} + +TransformConstraint *Skeleton::findTransformConstraint(const String &constraintName) { + assert(constraintName.length() > 0); + + for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) { + TransformConstraint *transformConstraint = _transformConstraints[i]; + if (transformConstraint->_data.getName() == constraintName) { + return transformConstraint; + } + } + + return NULL; +} + +PathConstraint *Skeleton::findPathConstraint(const String &constraintName) { + assert(constraintName.length() > 0); + + for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) { + PathConstraint *constraint = _pathConstraints[i]; + if (constraint->_data.getName() == constraintName) { + return constraint; + } + } + + return NULL; +} + +void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector &outVertexBuffer) { + float minX = FLT_MAX; + float minY = FLT_MAX; + float maxX = -FLT_MAX; + float maxY = -FLT_MAX; + + for (size_t i = 0; i < _drawOrder.size(); ++i) { + Slot *slot = _drawOrder[i]; + if (!slot->_bone._active) continue; + size_t verticesLength = 0; + Attachment *attachment = slot->getAttachment(); + + if (attachment != NULL && attachment->getRTTI().instanceOf(RegionAttachment::rtti)) { + RegionAttachment *regionAttachment = static_cast(attachment); + + verticesLength = 8; + if (outVertexBuffer.size() < 8) { + outVertexBuffer.setSize(8, 0); + } + regionAttachment->computeWorldVertices(*slot, outVertexBuffer, 0); + } else if (attachment != NULL && attachment->getRTTI().instanceOf(MeshAttachment::rtti)) { + MeshAttachment *mesh = static_cast(attachment); + + verticesLength = mesh->getWorldVerticesLength(); + if (outVertexBuffer.size() < verticesLength) { + outVertexBuffer.setSize(verticesLength, 0); + } + + mesh->computeWorldVertices(*slot, 0, verticesLength, outVertexBuffer.buffer(), 0); + } + + for (size_t ii = 0; ii < verticesLength; ii += 2) { + float vx = outVertexBuffer[ii]; + float vy = outVertexBuffer[ii + 1]; + + minX = MathUtil::min(minX, vx); + minY = MathUtil::min(minY, vy); + maxX = MathUtil::max(maxX, vx); + maxY = MathUtil::max(maxY, vy); + } + } + + outX = minX; + outY = minY; + outWidth = maxX - minX; + outHeight = maxY - minY; +} + +Bone *Skeleton::getRootBone() { + return _bones.size() == 0 ? NULL : _bones[0]; +} + +SkeletonData *Skeleton::getData() { + return _data; +} + +Vector &Skeleton::getBones() { + return _bones; +} + +Vector &Skeleton::getUpdateCacheList() { + return _updateCache; +} + +Vector &Skeleton::getSlots() { + return _slots; +} + +Vector &Skeleton::getDrawOrder() { + return _drawOrder; +} + +Vector &Skeleton::getIkConstraints() { + return _ikConstraints; +} + +Vector &Skeleton::getPathConstraints() { + return _pathConstraints; +} + +Vector &Skeleton::getTransformConstraints() { + return _transformConstraints; +} + +Skin *Skeleton::getSkin() { + return _skin; +} + +Color &Skeleton::getColor() { + return _color; +} + +void Skeleton::setPosition(float x, float y) { + _x = x; + _y = y; +} + +float Skeleton::getX() { + return _x; +} + +void Skeleton::setX(float inValue) { + _x = inValue; +} + +float Skeleton::getY() { + return _y; +} + +void Skeleton::setY(float inValue) { + _y = inValue; +} + +float Skeleton::getScaleX() { + return _scaleX; +} + +void Skeleton::setScaleX(float inValue) { + _scaleX = inValue; +} + +float Skeleton::getScaleY() { + return _scaleY * (Bone::isYDown() ? -1 : 1); +} + +void Skeleton::setScaleY(float inValue) { + _scaleY = inValue; +} + +void Skeleton::sortIkConstraint(IkConstraint *constraint) { + constraint->_active = constraint->_target->_active && (!constraint->_data.isSkinRequired() || + (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) return; + + Bone *target = constraint->getTarget(); + sortBone(target); + + Vector &constrained = constraint->getBones(); + Bone *parent = constrained[0]; + sortBone(parent); + + if (constrained.size() == 1) { + _updateCache.add(constraint); + sortReset(parent->_children); + } else { + Bone *child = constrained[constrained.size() - 1]; + sortBone(child); + + _updateCache.add(constraint); + + sortReset(parent->_children); + child->_sorted = true; + } +} + +void Skeleton::sortPathConstraint(PathConstraint *constraint) { + constraint->_active = constraint->_target->_bone._active && (!constraint->_data.isSkinRequired() || (_skin && + _skin->_constraints.contains( + &constraint->_data))); + if (!constraint->_active) return; + + Slot *slot = constraint->getTarget(); + int slotIndex = slot->getData().getIndex(); + Bone &slotBone = slot->getBone(); + if (_skin != NULL) sortPathConstraintAttachment(_skin, slotIndex, slotBone); + if (_data->_defaultSkin != NULL && _data->_defaultSkin != _skin) + sortPathConstraintAttachment(_data->_defaultSkin, slotIndex, slotBone); + for (size_t ii = 0, nn = _data->_skins.size(); ii < nn; ii++) + sortPathConstraintAttachment(_data->_skins[ii], slotIndex, slotBone); + + Attachment *attachment = slot->getAttachment(); + if (attachment != NULL && attachment->getRTTI().instanceOf(PathAttachment::rtti)) + sortPathConstraintAttachment(attachment, slotBone); + + Vector &constrained = constraint->getBones(); + size_t boneCount = constrained.size(); + for (size_t i = 0; i < boneCount; ++i) { + sortBone(constrained[i]); + } + + _updateCache.add(constraint); + + for (size_t i = 0; i < boneCount; i++) + sortReset(constrained[i]->getChildren()); + for (size_t i = 0; i < boneCount; i++) + constrained[i]->_sorted = true; +} + +void Skeleton::sortTransformConstraint(TransformConstraint *constraint) { + constraint->_active = constraint->_target->_active && (!constraint->_data.isSkinRequired() || + (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) return; + + sortBone(constraint->getTarget()); + + Vector &constrained = constraint->getBones(); + size_t boneCount = constrained.size(); + if (constraint->_data.isLocal()) { + for (size_t i = 0; i < boneCount; i++) { + Bone *child = constrained[i]; + sortBone(child->getParent()); + sortBone(child); + } + } else { + for (size_t i = 0; i < boneCount; ++i) { + sortBone(constrained[i]); + } + } + + _updateCache.add(constraint); + + for (size_t i = 0; i < boneCount; ++i) + sortReset(constrained[i]->getChildren()); + for (size_t i = 0; i < boneCount; ++i) + constrained[i]->_sorted = true; +} + +void Skeleton::sortPathConstraintAttachment(Skin *skin, size_t slotIndex, Bone &slotBone) { + Skin::AttachmentMap::Entries attachments = skin->getAttachments(); + + while (attachments.hasNext()) { + Skin::AttachmentMap::Entry entry = attachments.next(); + if (entry._slotIndex == slotIndex) { + Attachment *value = entry._attachment; + sortPathConstraintAttachment(value, slotBone); + } + } +} + +void Skeleton::sortPathConstraintAttachment(Attachment *attachment, Bone &slotBone) { + if (attachment == NULL || !attachment->getRTTI().instanceOf(PathAttachment::rtti)) return; + Vector &pathBones = static_cast(attachment)->getBones(); + if (pathBones.size() == 0) + sortBone(&slotBone); + else { + for (size_t i = 0, n = pathBones.size(); i < n;) { + size_t nn = pathBones[i++]; + nn += i; + while (i < nn) { + sortBone(_bones[pathBones[i++]]); + } + } + } +} + +void Skeleton::sortBone(Bone *bone) { + if (bone->_sorted) return; + Bone *parent = bone->_parent; + if (parent != NULL) sortBone(parent); + bone->_sorted = true; + _updateCache.add(bone); +} + +void Skeleton::sortReset(Vector &bones) { + for (size_t i = 0, n = bones.size(); i < n; ++i) { + Bone *bone = bones[i]; + if (!bone->_active) continue; + if (bone->_sorted) sortReset(bone->getChildren()); + bone->_sorted = false; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp new file mode 100644 index 0000000..79cc73d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -0,0 +1,1407 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +SkeletonBinary::SkeletonBinary(Atlas *atlasArray) : _attachmentLoader( + new (__FILE__, __LINE__) AtlasAttachmentLoader(atlasArray)), + _error(), _scale(1), _ownsLoader(true) { +} + +SkeletonBinary::SkeletonBinary(AttachmentLoader *attachmentLoader, bool ownsLoader) : _attachmentLoader( + attachmentLoader), + _error(), + _scale(1), + _ownsLoader(ownsLoader) { + assert(_attachmentLoader != NULL); +} + +SkeletonBinary::~SkeletonBinary() { + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + if (_ownsLoader) delete _attachmentLoader; +} + +SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, const int length) { + bool nonessential; + SkeletonData *skeletonData; + + DataInput *input = new (__FILE__, __LINE__) DataInput(); + input->cursor = binary; + input->end = binary + length; + + _linkedMeshes.clear(); + + skeletonData = new (__FILE__, __LINE__) SkeletonData(); + + char buffer[16] = {0}; + int lowHash = readInt(input); + int hightHash = readInt(input); + String hashString; + snprintf(buffer, 16, "%x", hightHash); + hashString.append(buffer); + snprintf(buffer, 16, "%x", lowHash); + hashString.append(buffer); + skeletonData->_hash = hashString; + + char *skeletonDataVersion = readString(input); + skeletonData->_version.own(skeletonDataVersion); + + if (!skeletonData->_version.startsWith(SPINE_VERSION_STRING)) { + char errorMsg[255]; + snprintf(errorMsg, 255, "Skeleton version %s does not match runtime version %s", skeletonData->_version.buffer(), SPINE_VERSION_STRING); + setError(errorMsg, ""); + return NULL; + } + + skeletonData->_x = readFloat(input); + skeletonData->_y = readFloat(input); + skeletonData->_width = readFloat(input); + skeletonData->_height = readFloat(input); + + nonessential = readBoolean(input); + + if (nonessential) { + skeletonData->_fps = readFloat(input); + skeletonData->_imagesPath.own(readString(input)); + skeletonData->_audioPath.own(readString(input)); + } + + int numStrings = readVarint(input, true); + for (int i = 0; i < numStrings; i++) + skeletonData->_strings.add(readString(input)); + + /* Bones. */ + int numBones = readVarint(input, true); + skeletonData->_bones.setSize(numBones, 0); + for (int i = 0; i < numBones; ++i) { + const char *name = readString(input); + BoneData *parent = i == 0 ? 0 : skeletonData->_bones[readVarint(input, true)]; + BoneData *data = new (__FILE__, __LINE__) BoneData(i, String(name, true), parent); + data->_rotation = readFloat(input); + data->_x = readFloat(input) * _scale; + data->_y = readFloat(input) * _scale; + data->_scaleX = readFloat(input); + data->_scaleY = readFloat(input); + data->_shearX = readFloat(input); + data->_shearY = readFloat(input); + data->_length = readFloat(input) * _scale; + data->_transformMode = static_cast(readVarint(input, true)); + data->_skinRequired = readBoolean(input); + if (nonessential) { + readColor(input, data->getColor()); + } + skeletonData->_bones[i] = data; + } + + /* Slots. */ + int slotsCount = readVarint(input, true); + skeletonData->_slots.setSize(slotsCount, 0); + for (int i = 0; i < slotsCount; ++i) { + const char *slotName = readString(input); + BoneData *boneData = skeletonData->_bones[readVarint(input, true)]; + SlotData *slotData = new (__FILE__, __LINE__) SlotData(i, String(slotName, true), *boneData); + + readColor(input, slotData->getColor()); + unsigned char a = readByte(input); + unsigned char r = readByte(input); + unsigned char g = readByte(input); + unsigned char b = readByte(input); + if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) { + slotData->getDarkColor().set(r / 255.0f, g / 255.0f, b / 255.0f, 1); + slotData->setHasDarkColor(true); + } + slotData->_attachmentName = readStringRef(input, skeletonData); + slotData->_blendMode = static_cast(readVarint(input, true)); + skeletonData->_slots[i] = slotData; + } + + /* IK constraints. */ + int ikConstraintsCount = readVarint(input, true); + skeletonData->_ikConstraints.setSize(ikConstraintsCount, 0); + for (int i = 0; i < ikConstraintsCount; ++i) { + const char *name = readString(input); + IkConstraintData *data = new (__FILE__, __LINE__) IkConstraintData(String(name, true)); + data->setOrder(readVarint(input, true)); + data->setSkinRequired(readBoolean(input)); + int bonesCount = readVarint(input, true); + data->_bones.setSize(bonesCount, 0); + for (int ii = 0; ii < bonesCount; ++ii) + data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; + data->_target = skeletonData->_bones[readVarint(input, true)]; + data->_mix = readFloat(input); + data->_softness = readFloat(input) * _scale; + data->_bendDirection = readSByte(input); + data->_compress = readBoolean(input); + data->_stretch = readBoolean(input); + data->_uniform = readBoolean(input); + skeletonData->_ikConstraints[i] = data; + } + + /* Transform constraints. */ + int transformConstraintsCount = readVarint(input, true); + skeletonData->_transformConstraints.setSize(transformConstraintsCount, 0); + for (int i = 0; i < transformConstraintsCount; ++i) { + const char *name = readString(input); + TransformConstraintData *data = new (__FILE__, __LINE__) TransformConstraintData(String(name, true)); + data->setOrder(readVarint(input, true)); + data->setSkinRequired(readBoolean(input)); + int bonesCount = readVarint(input, true); + data->_bones.setSize(bonesCount, 0); + for (int ii = 0; ii < bonesCount; ++ii) + data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; + data->_target = skeletonData->_bones[readVarint(input, true)]; + data->_local = readBoolean(input); + data->_relative = readBoolean(input); + data->_offsetRotation = readFloat(input); + data->_offsetX = readFloat(input) * _scale; + data->_offsetY = readFloat(input) * _scale; + data->_offsetScaleX = readFloat(input); + data->_offsetScaleY = readFloat(input); + data->_offsetShearY = readFloat(input); + data->_mixRotate = readFloat(input); + data->_mixX = readFloat(input); + data->_mixY = readFloat(input); + data->_mixScaleX = readFloat(input); + data->_mixScaleY = readFloat(input); + data->_mixShearY = readFloat(input); + skeletonData->_transformConstraints[i] = data; + } + + /* Path constraints */ + int pathConstraintsCount = readVarint(input, true); + skeletonData->_pathConstraints.setSize(pathConstraintsCount, 0); + for (int i = 0; i < pathConstraintsCount; ++i) { + const char *name = readString(input); + PathConstraintData *data = new (__FILE__, __LINE__) PathConstraintData(String(name, true)); + data->setOrder(readVarint(input, true)); + data->setSkinRequired(readBoolean(input)); + int bonesCount = readVarint(input, true); + data->_bones.setSize(bonesCount, 0); + for (int ii = 0; ii < bonesCount; ++ii) + data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; + data->_target = skeletonData->_slots[readVarint(input, true)]; + data->_positionMode = static_cast(readVarint(input, true)); + data->_spacingMode = static_cast(readVarint(input, true)); + data->_rotateMode = static_cast(readVarint(input, true)); + data->_offsetRotation = readFloat(input); + data->_position = readFloat(input); + if (data->_positionMode == PositionMode_Fixed) data->_position *= _scale; + data->_spacing = readFloat(input); + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) + data->_spacing *= _scale; + data->_mixRotate = readFloat(input); + data->_mixX = readFloat(input); + data->_mixY = readFloat(input); + skeletonData->_pathConstraints[i] = data; + } + + /* Default skin. */ + Skin *defaultSkin = readSkin(input, true, skeletonData, nonessential); + if (defaultSkin) { + skeletonData->_defaultSkin = defaultSkin; + skeletonData->_skins.add(defaultSkin); + } + + if (!this->getError().isEmpty()) { + delete input; + delete skeletonData; + return NULL; + } + + /* Skins. */ + for (size_t i = 0, n = (size_t) readVarint(input, true); i < n; ++i) { + Skin *skin = readSkin(input, false, skeletonData, nonessential); + if (skin) + skeletonData->_skins.add(skin); + else { + delete input; + delete skeletonData; + return NULL; + } + } + + /* Linked meshes. */ + for (int i = 0, n = (int) _linkedMeshes.size(); i < n; ++i) { + LinkedMesh *linkedMesh = _linkedMeshes[i]; + Skin *skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin(linkedMesh->_skin); + if (skin == NULL) { + delete input; + delete skeletonData; + setError("Skin not found: ", linkedMesh->_skin.buffer()); + return NULL; + } + Attachment *parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); + if (parent == NULL) { + delete input; + delete skeletonData; + setError("Parent mesh not found: ", linkedMesh->_parent.buffer()); + return NULL; + } + linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritTimeline ? static_cast(parent) + : linkedMesh->_mesh; + linkedMesh->_mesh->setParentMesh(static_cast(parent)); + if (linkedMesh->_mesh->_region) linkedMesh->_mesh->updateRegion(); + _attachmentLoader->configureAttachment(linkedMesh->_mesh); + } + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + /* Events. */ + int eventsCount = readVarint(input, true); + skeletonData->_events.setSize(eventsCount, 0); + for (int i = 0; i < eventsCount; ++i) { + const char *name = readStringRef(input, skeletonData); + EventData *eventData = new (__FILE__, __LINE__) EventData(String(name)); + eventData->_intValue = readVarint(input, false); + eventData->_floatValue = readFloat(input); + eventData->_stringValue.own(readString(input)); + eventData->_audioPath.own(readString(input)); + if (!eventData->_audioPath.isEmpty()) { + eventData->_volume = readFloat(input); + eventData->_balance = readFloat(input); + } + skeletonData->_events[i] = eventData; + } + + /* Animations. */ + int animationsCount = readVarint(input, true); + skeletonData->_animations.setSize(animationsCount, 0); + for (int i = 0; i < animationsCount; ++i) { + String name(readString(input), true); + Animation *animation = readAnimation(name, input, skeletonData); + if (!animation) { + delete input; + delete skeletonData; + return NULL; + } + skeletonData->_animations[i] = animation; + } + + delete input; + return skeletonData; +} + +SkeletonData *SkeletonBinary::readSkeletonDataFile(const String &path) { + int length; + SkeletonData *skeletonData; + const char *binary = SpineExtension::readFile(path.buffer(), &length); + if (length == 0 || !binary) { + setError("Unable to read skeleton file: ", path.buffer()); + return NULL; + } + skeletonData = readSkeletonData((unsigned char *) binary, length); + SpineExtension::free(binary, __FILE__, __LINE__); + return skeletonData; +} + +void SkeletonBinary::setError(const char *value1, const char *value2) { + char message[256]; + int length; + strcpy(message, value1); + length = (int) strlen(value1); + if (value2) strncat(message + length, value2, 255 - length); + _error = String(message); +} + +char *SkeletonBinary::readString(DataInput *input) { + int length = readVarint(input, true); + char *string; + if (length == 0) return NULL; + string = SpineExtension::alloc(length, __FILE__, __LINE__); + memcpy(string, input->cursor, length - 1); + input->cursor += length - 1; + string[length - 1] = '\0'; + return string; +} + +char *SkeletonBinary::readStringRef(DataInput *input, SkeletonData *skeletonData) { + int index = readVarint(input, true); + return index == 0 ? NULL : skeletonData->_strings[index - 1]; +} + +float SkeletonBinary::readFloat(DataInput *input) { + union { + int intValue; + float floatValue; + } intToFloat; + intToFloat.intValue = readInt(input); + return intToFloat.floatValue; +} + +unsigned char SkeletonBinary::readByte(DataInput *input) { + return *input->cursor++; +} + +signed char SkeletonBinary::readSByte(DataInput *input) { + return (signed char) readByte(input); +} + +bool SkeletonBinary::readBoolean(DataInput *input) { + return readByte(input) != 0; +} + +int SkeletonBinary::readInt(DataInput *input) { + int result = readByte(input); + result <<= 8; + result |= readByte(input); + result <<= 8; + result |= readByte(input); + result <<= 8; + result |= readByte(input); + return result; +} + +void SkeletonBinary::readColor(DataInput *input, Color &color) { + color.r = readByte(input) / 255.0f; + color.g = readByte(input) / 255.0f; + color.b = readByte(input) / 255.0f; + color.a = readByte(input) / 255.0f; +} + +int SkeletonBinary::readVarint(DataInput *input, bool optimizePositive) { + unsigned char b = readByte(input); + int value = b & 0x7F; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 7; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 14; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 21; + if (b & 0x80) value |= (readByte(input) & 0x7F) << 28; + } + } + } + if (!optimizePositive) value = (((unsigned int) value >> 1) ^ -(value & 1)); + return value; +} + +Skin *SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential) { + Skin *skin; + int slotCount = 0; + if (defaultSkin) { + slotCount = readVarint(input, true); + if (slotCount == 0) return NULL; + skin = new (__FILE__, __LINE__) Skin("default"); + } else { + skin = new (__FILE__, __LINE__) Skin(readStringRef(input, skeletonData)); + for (int i = 0, n = readVarint(input, true); i < n; i++) { + int boneIndex = readVarint(input, true); + if (boneIndex >= (int) skeletonData->_bones.size()) return NULL; + skin->getBones().add(skeletonData->_bones[boneIndex]); + } + + for (int i = 0, n = readVarint(input, true); i < n; i++) { + int ikIndex = readVarint(input, true); + if (ikIndex >= (int) skeletonData->_ikConstraints.size()) return NULL; + skin->getConstraints().add(skeletonData->_ikConstraints[ikIndex]); + } + + for (int i = 0, n = readVarint(input, true); i < n; i++) { + int transformIndex = readVarint(input, true); + if (transformIndex >= (int) skeletonData->_transformConstraints.size()) return NULL; + skin->getConstraints().add(skeletonData->_transformConstraints[transformIndex]); + } + + for (int i = 0, n = readVarint(input, true); i < n; i++) { + int pathIndex = readVarint(input, true); + if (pathIndex >= (int) skeletonData->_pathConstraints.size()) return NULL; + skin->getConstraints().add(skeletonData->_pathConstraints[pathIndex]); + } + slotCount = readVarint(input, true); + } + + for (int i = 0; i < slotCount; ++i) { + int slotIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + String name(readStringRef(input, skeletonData)); + Attachment *attachment = readAttachment(input, skin, slotIndex, name, skeletonData, nonessential); + if (attachment) + skin->setAttachment(slotIndex, String(name), attachment); + else { + delete skin; + return NULL; + } + } + } + return skin; +} + +Sequence *SkeletonBinary::readSequence(DataInput *input) { + if (!readBoolean(input)) return NULL; + Sequence *sequence = new (__FILE__, __LINE__) Sequence(readVarint(input, true)); + sequence->_start = readVarint(input, true); + sequence->_digits = readVarint(input, true); + sequence->_setupIndex = readVarint(input, true); + return sequence; +} + +Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName, + SkeletonData *skeletonData, bool nonessential) { + String name(readStringRef(input, skeletonData)); + if (name.isEmpty()) name = attachmentName; + + AttachmentType type = static_cast(readByte(input)); + switch (type) { + case AttachmentType_Region: { + String path(readStringRef(input, skeletonData)); + if (path.isEmpty()) path = name; + float rotation = readFloat(input); + float x = readFloat(input) * _scale; + float y = readFloat(input) * _scale; + float scaleX = readFloat(input); + float scaleY = readFloat(input); + float width = readFloat(input) * _scale; + float height = readFloat(input) * _scale; + Color color; + readColor(input, color); + Sequence *sequence = readSequence(input); + RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path), sequence); + if (!region) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + region->_path = path; + region->_rotation = rotation; + region->_x = x; + region->_y = y; + region->_scaleX = scaleX; + region->_scaleY = scaleY; + region->_width = width; + region->_height = height; + region->getColor().set(color); + region->_sequence = sequence; + if (sequence == NULL) region->updateRegion(); + _attachmentLoader->configureAttachment(region); + return region; + } + case AttachmentType_Boundingbox: { + int vertexCount = readVarint(input, true); + BoundingBoxAttachment *box = _attachmentLoader->newBoundingBoxAttachment(*skin, String(name)); + if (!box) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + readVertices(input, box->getVertices(), box->getBones(), vertexCount); + box->setWorldVerticesLength(vertexCount << 1); + if (nonessential) { + readColor(input, box->getColor()); + } + _attachmentLoader->configureAttachment(box); + return box; + } + case AttachmentType_Mesh: { + Color color; + int vertexCount; + Vector uvs; + Vector triangles; + Vector vertices; + Vector bones; + int hullLength; + Sequence *sequence; + float width = 0; + float height = 0; + Vector edges; + + String path(readStringRef(input, skeletonData)); + if (path.isEmpty()) path = name; + readColor(input, color); + vertexCount = readVarint(input, true); + readFloatArray(input, vertexCount << 1, 1, uvs); + readShortArray(input, triangles); + readVertices(input, vertices, bones, vertexCount); + hullLength = readVarint(input, true) << 1; + sequence = readSequence(input); + if (nonessential) { + readShortArray(input, edges); + width = readFloat(input) * _scale; + height = readFloat(input) * _scale; + } + + MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path), sequence); + if (!mesh) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + mesh->_path = path; + mesh->_color.set(color); + mesh->_bones.addAll(bones); + mesh->_vertices.addAll(vertices); + mesh->setWorldVerticesLength(vertexCount << 1); + mesh->_triangles.addAll(triangles); + mesh->_regionUVs.addAll(uvs); + if (sequence == NULL) mesh->updateRegion(); + mesh->_hullLength = hullLength; + mesh->_sequence = sequence; + if (nonessential) { + mesh->_edges.addAll(edges); + mesh->_width = width; + mesh->_height = height; + } + _attachmentLoader->configureAttachment(mesh); + return mesh; + } + case AttachmentType_Linkedmesh: { + String path(readStringRef(input, skeletonData)); + if (path.isEmpty()) path = name; + + Color color; + float width = 0, height = 0; + readColor(input, color); + String skinName(readStringRef(input, skeletonData)); + String parent(readStringRef(input, skeletonData)); + bool inheritTimelines = readBoolean(input); + Sequence *sequence = readSequence(input); + if (nonessential) { + width = readFloat(input) * _scale; + height = readFloat(input) * _scale; + } + + MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path), sequence); + if (!mesh) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + mesh->_path = path; + mesh->_color.set(color); + mesh->_sequence = sequence; + if (nonessential) { + mesh->_width = width; + mesh->_height = height; + } + + LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, String(skinName), slotIndex, + String(parent), inheritTimelines); + _linkedMeshes.add(linkedMesh); + return mesh; + } + case AttachmentType_Path: { + PathAttachment *path = _attachmentLoader->newPathAttachment(*skin, String(name)); + if (!path) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + path->_closed = readBoolean(input); + path->_constantSpeed = readBoolean(input); + int vertexCount = readVarint(input, true); + readVertices(input, path->getVertices(), path->getBones(), vertexCount); + path->setWorldVerticesLength(vertexCount << 1); + int lengthsLength = vertexCount / 3; + path->_lengths.setSize(lengthsLength, 0); + for (int i = 0; i < lengthsLength; ++i) { + path->_lengths[i] = readFloat(input) * _scale; + } + if (nonessential) { + readColor(input, path->getColor()); + } + _attachmentLoader->configureAttachment(path); + return path; + } + case AttachmentType_Point: { + PointAttachment *point = _attachmentLoader->newPointAttachment(*skin, String(name)); + if (!point) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + point->_rotation = readFloat(input); + point->_x = readFloat(input) * _scale; + point->_y = readFloat(input) * _scale; + + if (nonessential) { + readColor(input, point->getColor()); + } + _attachmentLoader->configureAttachment(point); + return point; + } + case AttachmentType_Clipping: { + int endSlotIndex = readVarint(input, true); + int vertexCount = readVarint(input, true); + ClippingAttachment *clip = _attachmentLoader->newClippingAttachment(*skin, name); + if (!clip) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + readVertices(input, clip->getVertices(), clip->getBones(), vertexCount); + clip->setWorldVerticesLength(vertexCount << 1); + clip->_endSlot = skeletonData->_slots[endSlotIndex]; + if (nonessential) { + readColor(input, clip->getColor()); + } + _attachmentLoader->configureAttachment(clip); + return clip; + } + } + return NULL; +} + +void SkeletonBinary::readVertices(DataInput *input, Vector &vertices, Vector &bones, int vertexCount) { + float scale = _scale; + int verticesLength = vertexCount << 1; + + if (!readBoolean(input)) { + readFloatArray(input, verticesLength, scale, vertices); + return; + } + + vertices.ensureCapacity(verticesLength * 3 * 3); + bones.ensureCapacity(verticesLength * 3); + + for (int i = 0; i < vertexCount; ++i) { + int boneCount = readVarint(input, true); + bones.add(boneCount); + for (int ii = 0; ii < boneCount; ++ii) { + bones.add(readVarint(input, true)); + vertices.add(readFloat(input) * scale); + vertices.add(readFloat(input) * scale); + vertices.add(readFloat(input)); + } + } +} + +void SkeletonBinary::readFloatArray(DataInput *input, int n, float scale, Vector &array) { + array.setSize(n, 0); + + int i; + if (scale == 1) { + for (i = 0; i < n; ++i) { + array[i] = readFloat(input); + } + } else { + for (i = 0; i < n; ++i) { + array[i] = readFloat(input) * scale; + } + } +} + +void SkeletonBinary::readShortArray(DataInput *input, Vector &array) { + int n = readVarint(input, true); + array.setSize(n, 0); + + int i; + for (i = 0; i < n; ++i) { + array[i] = readByte(input) << 8; + array[i] |= readByte(input); + } +} + +void SkeletonBinary::setBezier(DataInput *input, CurveTimeline *timeline, int bezier, int frame, int value, float time1, + float time2, + float value1, float value2, float scale) { + float cx1 = readFloat(input); + float cy1 = readFloat(input); + float cx2 = readFloat(input); + float cy2 = readFloat(input); + timeline->setBezier(bezier, frame, value, time1, value1, cx1, cy1 * scale, cx2, cy2 * scale, time2, value2); +} + +Timeline *SkeletonBinary::readTimeline(DataInput *input, CurveTimeline1 *timeline, float scale) { + float time = readFloat(input); + float value = readFloat(input) * scale; + for (int frame = 0, bezier = 0, frameLast = (int) timeline->getFrameCount() - 1;; frame++) { + timeline->setFrame(frame, time, value); + if (frame == frameLast) break; + float time2 = readFloat(input); + float value2 = readFloat(input) * scale; + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale); + } + time = time2; + value = value2; + } + return timeline; +} + +Timeline *SkeletonBinary::readTimeline2(DataInput *input, CurveTimeline2 *timeline, float scale) { + float time = readFloat(input); + float value1 = readFloat(input) * scale; + float value2 = readFloat(input) * scale; + for (int frame = 0, bezier = 0, frameLast = (int) timeline->getFrameCount() - 1;; frame++) { + timeline->setFrame(frame, time, value1, value2); + if (frame == frameLast) break; + float time2 = readFloat(input); + float nvalue1 = readFloat(input) * scale; + float nvalue2 = readFloat(input) * scale; + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale); + setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + } + return timeline; +} + +Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, SkeletonData *skeletonData) { + Vector timelines; + float scale = _scale; + int numTimelines = readVarint(input, true); + SP_UNUSED(numTimelines); + // Slot timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int slotIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + unsigned char timelineType = readByte(input); + int frameCount = readVarint(input, true); + int frameLast = frameCount - 1; + switch (timelineType) { + case SLOT_ATTACHMENT: { + AttachmentTimeline *timeline = new (__FILE__, __LINE__) AttachmentTimeline(frameCount, slotIndex); + for (int frame = 0; frame < frameCount; ++frame) { + float time = readFloat(input); + String attachmentName(readStringRef(input, skeletonData)); + timeline->setFrame(frame, time, attachmentName); + } + timelines.add(timeline); + break; + } + case SLOT_RGBA: { + int bezierCount = readVarint(input, true); + RGBATimeline *timeline = new (__FILE__, __LINE__) RGBATimeline(frameCount, bezierCount, slotIndex); + + float time = readFloat(input); + float r = readByte(input) / 255.0; + float g = readByte(input) / 255.0; + float b = readByte(input) / 255.0; + float a = readByte(input) / 255.0; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b, a); + if (frame == frameLast) break; + + float time2 = readFloat(input); + float r2 = readByte(input) / 255.0; + float g2 = readByte(input) / 255.0; + float b2 = readByte(input) / 255.0; + float a2 = readByte(input) / 255.0; + + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + a = a2; + } + timelines.add(timeline); + break; + } + case SLOT_RGB: { + int bezierCount = readVarint(input, true); + RGBTimeline *timeline = new (__FILE__, __LINE__) RGBTimeline(frameCount, bezierCount, slotIndex); + + float time = readFloat(input); + float r = readByte(input) / 255.0; + float g = readByte(input) / 255.0; + float b = readByte(input) / 255.0; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b); + if (frame == frameLast) break; + + float time2 = readFloat(input); + float r2 = readByte(input) / 255.0; + float g2 = readByte(input) / 255.0; + float b2 = readByte(input) / 255.0; + + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + } + timelines.add(timeline); + break; + } + case SLOT_RGBA2: { + int bezierCount = readVarint(input, true); + RGBA2Timeline *timeline = new (__FILE__, __LINE__) RGBA2Timeline(frameCount, bezierCount, slotIndex); + + float time = readFloat(input); + float r = readByte(input) / 255.0; + float g = readByte(input) / 255.0; + float b = readByte(input) / 255.0; + float a = readByte(input) / 255.0; + float r2 = readByte(input) / 255.0; + float g2 = readByte(input) / 255.0; + float b2 = readByte(input) / 255.0; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b, a, r2, g2, b2); + if (frame == frameLast) break; + float time2 = readFloat(input); + float nr = readByte(input) / 255.0; + float ng = readByte(input) / 255.0; + float nb = readByte(input) / 255.0; + float na = readByte(input) / 255.0; + float nr2 = readByte(input) / 255.0; + float ng2 = readByte(input) / 255.0; + float nb2 = readByte(input) / 255.0; + + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + a = na; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.add(timeline); + break; + } + case SLOT_RGB2: { + int bezierCount = readVarint(input, true); + RGB2Timeline *timeline = new (__FILE__, __LINE__) RGB2Timeline(frameCount, bezierCount, slotIndex); + + float time = readFloat(input); + float r = readByte(input) / 255.0; + float g = readByte(input) / 255.0; + float b = readByte(input) / 255.0; + float r2 = readByte(input) / 255.0; + float g2 = readByte(input) / 255.0; + float b2 = readByte(input) / 255.0; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b, r2, g2, b2); + if (frame == frameLast) break; + float time2 = readFloat(input); + float nr = readByte(input) / 255.0; + float ng = readByte(input) / 255.0; + float nb = readByte(input) / 255.0; + float nr2 = readByte(input) / 255.0; + float ng2 = readByte(input) / 255.0; + float nb2 = readByte(input) / 255.0; + + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.add(timeline); + break; + } + case SLOT_ALPHA: { + int bezierCount = readVarint(input, true); + AlphaTimeline *timeline = new (__FILE__, __LINE__) AlphaTimeline(frameCount, bezierCount, slotIndex); + float time = readFloat(input); + float a = readByte(input) / 255.0; + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, a); + if (frame == frameLast) break; + float time2 = readFloat(input); + float a2 = readByte(input) / 255.0; + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1); + } + time = time2; + a = a2; + } + timelines.add(timeline); + break; + } + default: { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Invalid timeline type for a slot: ", skeletonData->_slots[slotIndex]->_name.buffer()); + return NULL; + } + } + } + } + + // Bone timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int boneIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + unsigned char timelineType = readByte(input); + int frameCount = readVarint(input, true); + int bezierCount = readVarint(input, true); + Timeline *timeline = NULL; + switch (timelineType) { + case BONE_ROTATE: + timeline = readTimeline(input, + new (__FILE__, __LINE__) RotateTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_TRANSLATE: + timeline = readTimeline2(input, new (__FILE__, __LINE__) TranslateTimeline(frameCount, bezierCount, boneIndex), scale); + break; + case BONE_TRANSLATEX: + timeline = readTimeline(input, new (__FILE__, __LINE__) TranslateXTimeline(frameCount, bezierCount, boneIndex), scale); + break; + case BONE_TRANSLATEY: + timeline = readTimeline(input, new (__FILE__, __LINE__) TranslateYTimeline(frameCount, bezierCount, boneIndex), scale); + break; + case BONE_SCALE: + timeline = readTimeline2(input, + new (__FILE__, __LINE__) ScaleTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SCALEX: + timeline = readTimeline(input, + new (__FILE__, __LINE__) ScaleXTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SCALEY: + timeline = readTimeline(input, + new (__FILE__, __LINE__) ScaleYTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SHEAR: + timeline = readTimeline2(input, + new (__FILE__, __LINE__) ShearTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SHEARX: + timeline = readTimeline(input, + new (__FILE__, __LINE__) ShearXTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SHEARY: + timeline = readTimeline(input, + new (__FILE__, __LINE__) ShearYTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + default: { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Invalid timeline type for a bone: ", skeletonData->_bones[boneIndex]->_name.buffer()); + return NULL; + } + } + timelines.add(timeline); + } + } + + // IK timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int index = readVarint(input, true); + int frameCount = readVarint(input, true); + int frameLast = frameCount - 1; + int bezierCount = readVarint(input, true); + IkConstraintTimeline *timeline = new (__FILE__, __LINE__) IkConstraintTimeline(frameCount, bezierCount, index); + float time = readFloat(input); + float mix = readFloat(input); + float softness = readFloat(input) * scale; + for (int frame = 0, bezier = 0;; frame++) { + int bendDirection = readSByte(input); + bool compress = readBoolean(input); + bool stretch = readBoolean(input); + timeline->setFrame(frame, time, mix, softness, bendDirection, compress, stretch); + if (frame == frameLast) break; + float time2 = readFloat(input); + float mix2 = readFloat(input); + float softness2 = readFloat(input) * scale; + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + } + timelines.add(timeline); + } + + // Transform constraint timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int index = readVarint(input, true); + int frameCount = readVarint(input, true); + int frameLast = frameCount - 1; + int bezierCount = readVarint(input, true); + TransformConstraintTimeline *timeline = new TransformConstraintTimeline(frameCount, bezierCount, index); + float time = readFloat(input); + float mixRotate = readFloat(input); + float mixX = readFloat(input); + float mixY = readFloat(input); + float mixScaleX = readFloat(input); + float mixScaleY = readFloat(input); + float mixShearY = readFloat(input); + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + if (frame == frameLast) break; + float time2 = readFloat(input); + float mixRotate2 = readFloat(input); + float mixX2 = readFloat(input); + float mixY2 = readFloat(input); + float mixScaleX2 = readFloat(input); + float mixScaleY2 = readFloat(input); + float mixShearY2 = readFloat(input); + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + } + timelines.add(timeline); + } + + // Path constraint timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int index = readVarint(input, true); + PathConstraintData *data = skeletonData->_pathConstraints[index]; + for (int ii = 0, nn = readVarint(input, true); ii < nn; ii++) { + int type = readSByte(input); + int frameCount = readVarint(input, true); + int bezierCount = readVarint(input, true); + switch (type) { + case PATH_POSITION: { + timelines + .add(readTimeline(input, new PathConstraintPositionTimeline(frameCount, bezierCount, index), + data->_positionMode == PositionMode_Fixed ? scale : 1)); + break; + } + case PATH_SPACING: { + timelines + .add(readTimeline(input, + new PathConstraintSpacingTimeline(frameCount, + bezierCount, + index), + data->_spacingMode == SpacingMode_Length || + data->_spacingMode == SpacingMode_Fixed + ? scale + : 1)); + break; + } + case PATH_MIX: + PathConstraintMixTimeline *timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index); + float time = readFloat(input); + float mixRotate = readFloat(input); + float mixX = readFloat(input); + float mixY = readFloat(input); + for (int frame = 0, bezier = 0, frameLast = (int) timeline->getFrameCount() - 1;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY); + if (frame == frameLast) break; + float time2 = readFloat(input); + float mixRotate2 = readFloat(input); + float mixX2 = readFloat(input); + float mixY2 = readFloat(input); + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + } + timelines.add(timeline); + } + } + } + + // Deform timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + Skin *skin = skeletonData->_skins[readVarint(input, true)]; + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + int slotIndex = readVarint(input, true); + for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) { + const char *attachmentName = readStringRef(input, skeletonData); + Attachment *baseAttachment = skin->getAttachment(slotIndex, String(attachmentName)); + if (!baseAttachment) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Attachment not found: ", attachmentName); + return NULL; + } + unsigned int timelineType = readByte(input); + int frameCount = readVarint(input, true); + int frameLast = frameCount - 1; + + switch (timelineType) { + case ATTACHMENT_DEFORM: { + VertexAttachment *attachment = static_cast(baseAttachment); + bool weighted = attachment->_bones.size() > 0; + Vector &vertices = attachment->_vertices; + int deformLength = weighted ? (int) vertices.size() / 3 * 2 : (int) vertices.size(); + + int bezierCount = readVarint(input, true); + DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frameCount, bezierCount, slotIndex, + attachment); + + float time = readFloat(input); + for (int frame = 0, bezier = 0;; ++frame) { + Vector deform; + size_t end = (size_t) readVarint(input, true); + if (end == 0) { + if (weighted) { + deform.setSize(deformLength, 0); + for (int iiii = 0; iiii < deformLength; ++iiii) + deform[iiii] = 0; + } else { + deform.clearAndAddAll(vertices); + } + } else { + deform.setSize(deformLength, 0); + size_t start = (size_t) readVarint(input, true); + end += start; + if (scale == 1) { + for (size_t v = start; v < end; ++v) + deform[v] = readFloat(input); + } else { + for (size_t v = start; v < end; ++v) + deform[v] = readFloat(input) * scale; + } + + if (!weighted) { + for (size_t v = 0, vn = deform.size(); v < vn; ++v) + deform[v] += vertices[v]; + } + } + + timeline->setFrame(frame, time, deform); + if (frame == frameLast) break; + float time2 = readFloat(input); + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1); + } + time = time2; + } + + timelines.add(timeline); + break; + } + case ATTACHMENT_SEQUENCE: { + SequenceTimeline *timeline = new (__FILE__, __LINE__) SequenceTimeline(frameCount, slotIndex, baseAttachment); + for (int frame = 0; frame < frameCount; frame++) { + float time = readFloat(input); + int modeAndIndex = readInt(input); + float delay = readFloat(input); + timeline->setFrame(frame, time, (spine::SequenceMode)(modeAndIndex & 0xf), modeAndIndex >> 4, delay); + } + timelines.add(timeline); + break; + } + } + } + } + } + + // Draw order timeline. + size_t drawOrderCount = (size_t) readVarint(input, true); + if (drawOrderCount > 0) { + DrawOrderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderTimeline(drawOrderCount); + + size_t slotCount = skeletonData->_slots.size(); + for (size_t i = 0; i < drawOrderCount; ++i) { + float time = readFloat(input); + size_t offsetCount = (size_t) readVarint(input, true); + + Vector drawOrder; + drawOrder.setSize(slotCount, 0); + for (int ii = (int) slotCount - 1; ii >= 0; --ii) + drawOrder[ii] = -1; + + Vector unchanged; + unchanged.setSize(slotCount - offsetCount, 0); + size_t originalIndex = 0, unchangedIndex = 0; + for (size_t ii = 0; ii < offsetCount; ++ii) { + size_t slotIndex = (size_t) readVarint(input, true); + // Collect unchanged items. + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = (int) originalIndex++; + // Set changed items. + size_t index = originalIndex; + drawOrder[index + (size_t) readVarint(input, true)] = (int) originalIndex++; + } + + // Collect remaining unchanged items. + while (originalIndex < slotCount) { + unchanged[unchangedIndex++] = (int) originalIndex++; + } + + // Fill in unchanged items. + for (int ii = (int) slotCount - 1; ii >= 0; --ii) + if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; + timeline->setFrame(i, time, drawOrder); + } + timelines.add(timeline); + } + + // Event timeline. + int eventCount = readVarint(input, true); + if (eventCount > 0) { + EventTimeline *timeline = new (__FILE__, __LINE__) EventTimeline(eventCount); + + for (int i = 0; i < eventCount; ++i) { + float time = readFloat(input); + EventData *eventData = skeletonData->_events[readVarint(input, true)]; + Event *event = new (__FILE__, __LINE__) Event(time, *eventData); + + event->_intValue = readVarint(input, false); + event->_floatValue = readFloat(input); + bool freeString = readBoolean(input); + const char *event_stringValue = freeString ? readString(input) : eventData->_stringValue.buffer(); + event->_stringValue = String(event_stringValue); + if (freeString) SpineExtension::free(event_stringValue, __FILE__, __LINE__); + + if (!eventData->_audioPath.isEmpty()) { + event->_volume = readFloat(input); + event->_balance = readFloat(input); + } + timeline->setFrame(i, event); + } + timelines.add(timeline); + } + + float duration = 0; + for (int i = 0, n = (int) timelines.size(); i < n; i++) { + duration = MathUtil::max(duration, (timelines[i])->getDuration()); + } + return new (__FILE__, __LINE__) Animation(String(name), timelines, duration); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp new file mode 100644 index 0000000..9f1e00c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp @@ -0,0 +1,231 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include + +using namespace spine; + +SkeletonBounds::SkeletonBounds() : _minX(0), _minY(0), _maxX(0), _maxY(0) { +} + +SkeletonBounds::~SkeletonBounds() { + for (size_t i = 0, n = _polygons.size(); i < n; i++) + _polygonPool.free(_polygons[i]); + _polygons.clear(); +} + +void SkeletonBounds::update(Skeleton &skeleton, bool updateAabb) { + Vector &slots = skeleton.getSlots(); + size_t slotCount = slots.size(); + + _boundingBoxes.clear(); + for (size_t i = 0, n = _polygons.size(); i < n; ++i) { + _polygonPool.free(_polygons[i]); + } + + _polygons.clear(); + + for (size_t i = 0; i < slotCount; i++) { + Slot *slot = slots[i]; + if (!slot->getBone().isActive()) continue; + + Attachment *attachment = slot->getAttachment(); + if (attachment == NULL || !attachment->getRTTI().instanceOf(BoundingBoxAttachment::rtti)) continue; + BoundingBoxAttachment *boundingBox = static_cast(attachment); + _boundingBoxes.add(boundingBox); + + spine::Polygon *polygonP = _polygonPool.obtain(); + _polygons.add(polygonP); + + Polygon &polygon = *polygonP; + + size_t count = boundingBox->getWorldVerticesLength(); + polygon._count = (int) count; + if (polygon._vertices.size() < count) { + polygon._vertices.setSize(count, 0); + } + boundingBox->computeWorldVertices(*slot, polygon._vertices); + } + + if (updateAabb) + aabbCompute(); + else { + _minX = FLT_MIN; + _minY = FLT_MIN; + _maxX = FLT_MAX; + _maxY = FLT_MAX; + } +} + +bool SkeletonBounds::aabbcontainsPoint(float x, float y) { + return x >= _minX && x <= _maxX && y >= _minY && y <= _maxY; +} + +bool SkeletonBounds::aabbintersectsSegment(float x1, float y1, float x2, float y2) { + float minX = _minX; + float minY = _minY; + float maxX = _maxX; + float maxY = _maxY; + + if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || + (y1 >= maxY && y2 >= maxY)) { + return false; + } + + float m = (y2 - y1) / (x2 - x1); + float y = m * (minX - x1) + y1; + if (y > minY && y < maxY) return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) return true; + float x = (minY - y1) / m + x1; + if (x > minX && x < maxX) return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) return true; + return false; +} + +bool SkeletonBounds::aabbIntersectsSkeleton(SkeletonBounds bounds) { + return _minX < bounds._maxX && _maxX > bounds._minX && _minY < bounds._maxY && _maxY > bounds._minY; +} + +bool SkeletonBounds::containsPoint(spine::Polygon *polygon, float x, float y) { + Vector &vertices = polygon->_vertices; + int nn = polygon->_count; + + int prevIndex = nn - 2; + bool inside = false; + for (int ii = 0; ii < nn; ii += 2) { + float vertexY = vertices[ii + 1]; + float prevY = vertices[prevIndex + 1]; + if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { + float vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) { + inside = !inside; + } + } + prevIndex = ii; + } + return inside; +} + +BoundingBoxAttachment *SkeletonBounds::containsPoint(float x, float y) { + for (size_t i = 0, n = _polygons.size(); i < n; ++i) + if (containsPoint(_polygons[i], x, y)) return _boundingBoxes[i]; + return NULL; +} + +BoundingBoxAttachment *SkeletonBounds::intersectsSegment(float x1, float y1, float x2, float y2) { + for (size_t i = 0, n = _polygons.size(); i < n; ++i) + if (intersectsSegment(_polygons[i], x1, y1, x2, y2)) return _boundingBoxes[i]; + return NULL; +} + +bool SkeletonBounds::intersectsSegment(spine::Polygon *polygon, float x1, float y1, float x2, float y2) { + Vector &vertices = polygon->_vertices; + size_t nn = polygon->_count; + + float width12 = x1 - x2, height12 = y1 - y2; + float det1 = x1 * y2 - y1 * x2; + float x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (size_t ii = 0; ii < nn; ii += 2) { + float x4 = vertices[ii], y4 = vertices[ii + 1]; + float det2 = x3 * y4 - y3 * x4; + float width34 = x3 - x4, height34 = y3 - y4; + float det3 = width12 * height34 - height12 * width34; + float x = (det1 * width34 - width12 * det2) / det3; + if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { + float y = (det1 * height34 - height12 * det2) / det3; + if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) { + return true; + } + } + x3 = x4; + y3 = y4; + } + + return false; +} + +spine::Polygon *SkeletonBounds::getPolygon(BoundingBoxAttachment *attachment) { + int index = _boundingBoxes.indexOf(attachment); + return index == -1 ? NULL : _polygons[index]; +} + +BoundingBoxAttachment *SkeletonBounds::getBoundingBox(Polygon *polygon) { + int index = _polygons.indexOf(polygon); + return index == -1 ? NULL : _boundingBoxes[index]; +} + +Vector &SkeletonBounds::getPolygons() { + return _polygons; +} + +Vector &SkeletonBounds::getBoundingBoxes() { + return _boundingBoxes; +} + +float SkeletonBounds::getWidth() { + return _maxX - _minX; +} + +float SkeletonBounds::getHeight() { + return _maxY - _minY; +} + +void SkeletonBounds::aabbCompute() { + float minX = FLT_MAX; + float minY = FLT_MAX; + float maxX = FLT_MIN; + float maxY = FLT_MIN; + + for (size_t i = 0, n = _polygons.size(); i < n; ++i) { + spine::Polygon *polygon = _polygons[i]; + Vector &vertices = polygon->_vertices; + for (int ii = 0, nn = polygon->_count; ii < nn; ii += 2) { + float x = vertices[ii]; + float y = vertices[ii + 1]; + minX = MathUtil::min(minX, x); + minY = MathUtil::min(minY, y); + maxX = MathUtil::max(maxX, x); + maxY = MathUtil::max(maxY, y); + } + } + _minX = minX; + _minY = minY; + _maxX = maxX; + _maxY = maxY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp new file mode 100644 index 0000000..b095547 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp @@ -0,0 +1,323 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +using namespace spine; + +SkeletonClipping::SkeletonClipping() : _clipAttachment(NULL) { + _clipOutput.ensureCapacity(128); + _clippedVertices.ensureCapacity(128); + _clippedTriangles.ensureCapacity(128); + _clippedUVs.ensureCapacity(128); +} + +size_t SkeletonClipping::clipStart(Slot &slot, ClippingAttachment *clip) { + if (_clipAttachment != NULL) { + return 0; + } + + _clipAttachment = clip; + + int n = (int) clip->getWorldVerticesLength(); + _clippingPolygon.setSize(n, 0); + clip->computeWorldVertices(slot, 0, n, _clippingPolygon, 0, 2); + makeClockwise(_clippingPolygon); + _clippingPolygons = &_triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon)); + + for (size_t i = 0; i < _clippingPolygons->size(); ++i) { + Vector *polygonP = (*_clippingPolygons)[i]; + Vector &polygon = *polygonP; + makeClockwise(polygon); + polygon.add(polygon[0]); + polygon.add(polygon[1]); + } + + return (*_clippingPolygons).size(); +} + +void SkeletonClipping::clipEnd(Slot &slot) { + if (_clipAttachment != NULL && _clipAttachment->_endSlot == &slot._data) { + clipEnd(); + } +} + +void SkeletonClipping::clipEnd() { + if (_clipAttachment == NULL) return; + + _clipAttachment = NULL; + _clippingPolygons = NULL; + _clippedVertices.clear(); + _clippedUVs.clear(); + _clippedTriangles.clear(); + _clippingPolygon.clear(); +} + +void SkeletonClipping::clipTriangles(Vector &vertices, Vector &triangles, Vector &uvs, + size_t stride) { + clipTriangles(vertices.buffer(), triangles.buffer(), triangles.size(), uvs.buffer(), stride); +} + +void SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, + size_t trianglesLength, float *uvs, size_t stride) { + Vector &clipOutput = _clipOutput; + Vector &clippedVertices = _clippedVertices; + Vector &clippedTriangles = _clippedTriangles; + Vector *> &polygons = *_clippingPolygons; + size_t polygonsCount = (*_clippingPolygons).size(); + + size_t index = 0; + clippedVertices.clear(); + _clippedUVs.clear(); + clippedTriangles.clear(); + + size_t i = 0; +continue_outer: + for (; i < trianglesLength; i += 3) { + int vertexOffset = triangles[i] * (int) stride; + float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + + vertexOffset = triangles[i + 1] * (int) stride; + float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + float u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + + vertexOffset = triangles[i + 2] * (int) stride; + float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + float u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + + for (size_t p = 0; p < polygonsCount; p++) { + size_t s = clippedVertices.size(); + if (clip(x1, y1, x2, y2, x3, y3, &(*polygons[p]), &clipOutput)) { + size_t clipOutputLength = clipOutput.size(); + if (clipOutputLength == 0) continue; + float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + float d = 1 / (d0 * d2 + d1 * (y1 - y3)); + + size_t clipOutputCount = clipOutputLength >> 1; + clippedVertices.setSize(s + clipOutputCount * 2, 0); + _clippedUVs.setSize(s + clipOutputCount * 2, 0); + for (size_t ii = 0; ii < clipOutputLength; ii += 2) { + float x = clipOutput[ii], y = clipOutput[ii + 1]; + clippedVertices[s] = x; + clippedVertices[s + 1] = y; + float c0 = x - x3, c1 = y - y3; + float a = (d0 * c0 + d1 * c1) * d; + float b = (d4 * c0 + d2 * c1) * d; + float c = 1 - a - b; + _clippedUVs[s] = u1 * a + u2 * b + u3 * c; + _clippedUVs[s + 1] = v1 * a + v2 * b + v3 * c; + s += 2; + } + + s = clippedTriangles.size(); + clippedTriangles.setSize(s + 3 * (clipOutputCount - 2), 0); + clipOutputCount--; + for (size_t ii = 1; ii < clipOutputCount; ii++) { + clippedTriangles[s] = (unsigned short) (index); + clippedTriangles[s + 1] = (unsigned short) (index + ii); + clippedTriangles[s + 2] = (unsigned short) (index + ii + 1); + s += 3; + } + index += clipOutputCount + 1; + } else { + clippedVertices.setSize(s + 3 * 2, 0); + _clippedUVs.setSize(s + 3 * 2, 0); + clippedVertices[s] = x1; + clippedVertices[s + 1] = y1; + clippedVertices[s + 2] = x2; + clippedVertices[s + 3] = y2; + clippedVertices[s + 4] = x3; + clippedVertices[s + 5] = y3; + + _clippedUVs[s] = u1; + _clippedUVs[s + 1] = v1; + _clippedUVs[s + 2] = u2; + _clippedUVs[s + 3] = v2; + _clippedUVs[s + 4] = u3; + _clippedUVs[s + 5] = v3; + + s = clippedTriangles.size(); + clippedTriangles.setSize(s + 3, 0); + clippedTriangles[s] = (unsigned short) index; + clippedTriangles[s + 1] = (unsigned short) (index + 1); + clippedTriangles[s + 2] = (unsigned short) (index + 2); + index += 3; + i += 3; + goto continue_outer; + } + } + } +} + +bool SkeletonClipping::isClipping() { + return _clipAttachment != NULL; +} + +Vector &SkeletonClipping::getClippedVertices() { + return _clippedVertices; +} + +Vector &SkeletonClipping::getClippedTriangles() { + return _clippedTriangles; +} + +Vector &SkeletonClipping::getClippedUVs() { + return _clippedUVs; +} + +bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector *clippingArea, + Vector *output) { + Vector *originalOutput = output; + bool clipped = false; + + // Avoid copy at the end. + Vector *input; + if (clippingArea->size() % 4 >= 2) { + input = output; + output = &_scratch; + } else + input = &_scratch; + + input->clear(); + input->add(x1); + input->add(y1); + input->add(x2); + input->add(y2); + input->add(x3); + input->add(y3); + input->add(x1); + input->add(y1); + output->clear(); + + Vector &clippingVertices = *clippingArea; + size_t clippingVerticesLast = clippingArea->size() - 4; + for (size_t i = 0;; i += 2) { + float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; + float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; + + Vector &inputVertices = *input; + size_t inputVerticesLength = input->size() - 2, outputStart = output->size(); + for (size_t ii = 0; ii < inputVerticesLength; ii += 2) { + float inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; + bool side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; + if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { + if (side2) { + // v1 inside, v2 inside + output->add(inputX2); + output->add(inputY2); + continue; + } + // v1 inside, v2 outside + float c0 = inputY2 - inputY, c2 = inputX2 - inputX; + float s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (MathUtil::abs(s) > 0.000001f) { + float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output->add(edgeX + (edgeX2 - edgeX) * ua); + output->add(edgeY + (edgeY2 - edgeY) * ua); + } else { + output->add(edgeX); + output->add(edgeY); + } + } else if (side2) { + // v1 outside, v2 inside + float c0 = inputY2 - inputY, c2 = inputX2 - inputX; + float s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (MathUtil::abs(s) > 0.000001f) { + float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output->add(edgeX + (edgeX2 - edgeX) * ua); + output->add(edgeY + (edgeY2 - edgeY) * ua); + } else { + output->add(edgeX); + output->add(edgeY); + } + output->add(inputX2); + output->add(inputY2); + } + clipped = true; + } + + if (outputStart == output->size()) { + // All edges outside. + originalOutput->clear(); + return true; + } + + output->add((*output)[0]); + output->add((*output)[1]); + + if (i == clippingVerticesLast) { + break; + } + Vector *temp = output; + output = input; + output->clear(); + input = temp; + } + + if (originalOutput != output) { + originalOutput->clear(); + for (size_t i = 0, n = output->size() - 2; i < n; ++i) + originalOutput->add((*output)[i]); + } else + originalOutput->setSize(originalOutput->size() - 2, 0); + + return clipped; +} + +void SkeletonClipping::makeClockwise(Vector &polygon) { + size_t verticeslength = polygon.size(); + + float area = polygon[verticeslength - 2] * polygon[1] - polygon[0] * polygon[verticeslength - 1]; + float p1x, p1y, p2x, p2y; + + for (size_t i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = polygon[i]; + p1y = polygon[i + 1]; + p2x = polygon[i + 2]; + p2y = polygon[i + 3]; + area += p1x * p2y - p2x * p1y; + } + + if (area < 0) return; + + for (size_t i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + float x = polygon[i], y = polygon[i + 1]; + int other = (int) (lastX - i); + polygon[i] = polygon[other]; + polygon[i + 1] = polygon[other + 1]; + polygon[other] = x; + polygon[other + 1] = y; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp new file mode 100644 index 0000000..6e38bc1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -0,0 +1,225 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +SkeletonData::SkeletonData() : _name(), + _defaultSkin(NULL), + _x(0), + _y(0), + _width(0), + _height(0), + _version(), + _hash(), + _fps(0), + _imagesPath() { +} + +SkeletonData::~SkeletonData() { + ContainerUtil::cleanUpVectorOfPointers(_bones); + ContainerUtil::cleanUpVectorOfPointers(_slots); + ContainerUtil::cleanUpVectorOfPointers(_skins); + + _defaultSkin = NULL; + + ContainerUtil::cleanUpVectorOfPointers(_events); + ContainerUtil::cleanUpVectorOfPointers(_animations); + ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); + ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); + ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); + for (size_t i = 0; i < _strings.size(); i++) { + SpineExtension::free(_strings[i], __FILE__, __LINE__); + } +} + +BoneData *SkeletonData::findBone(const String &boneName) { + return ContainerUtil::findWithName(_bones, boneName); +} + +SlotData *SkeletonData::findSlot(const String &slotName) { + return ContainerUtil::findWithName(_slots, slotName); +} + +Skin *SkeletonData::findSkin(const String &skinName) { + return ContainerUtil::findWithName(_skins, skinName); +} + +spine::EventData *SkeletonData::findEvent(const String &eventDataName) { + return ContainerUtil::findWithName(_events, eventDataName); +} + +Animation *SkeletonData::findAnimation(const String &animationName) { + return ContainerUtil::findWithName(_animations, animationName); +} + +IkConstraintData *SkeletonData::findIkConstraint(const String &constraintName) { + return ContainerUtil::findWithName(_ikConstraints, constraintName); +} + +TransformConstraintData *SkeletonData::findTransformConstraint(const String &constraintName) { + return ContainerUtil::findWithName(_transformConstraints, constraintName); +} + +PathConstraintData *SkeletonData::findPathConstraint(const String &constraintName) { + return ContainerUtil::findWithName(_pathConstraints, constraintName); +} + +const String &SkeletonData::getName() { + return _name; +} + +void SkeletonData::setName(const String &inValue) { + _name = inValue; +} + +Vector &SkeletonData::getBones() { + return _bones; +} + +Vector &SkeletonData::getSlots() { + return _slots; +} + +Vector &SkeletonData::getSkins() { + return _skins; +} + +Skin *SkeletonData::getDefaultSkin() { + return _defaultSkin; +} + +void SkeletonData::setDefaultSkin(Skin *inValue) { + _defaultSkin = inValue; +} + +Vector &SkeletonData::getEvents() { + return _events; +} + +Vector &SkeletonData::getAnimations() { + return _animations; +} + +Vector &SkeletonData::getIkConstraints() { + return _ikConstraints; +} + +Vector &SkeletonData::getTransformConstraints() { + return _transformConstraints; +} + +Vector &SkeletonData::getPathConstraints() { + return _pathConstraints; +} + +float SkeletonData::getX() { + return _x; +} + +void SkeletonData::setX(float inValue) { + _x = inValue; +} + +float SkeletonData::getY() { + return _y; +} + +void SkeletonData::setY(float inValue) { + _y = inValue; +} + +float SkeletonData::getWidth() { + return _width; +} + +void SkeletonData::setWidth(float inValue) { + _width = inValue; +} + +float SkeletonData::getHeight() { + return _height; +} + +void SkeletonData::setHeight(float inValue) { + _height = inValue; +} + +const String &SkeletonData::getVersion() { + return _version; +} + +void SkeletonData::setVersion(const String &inValue) { + _version = inValue; +} + +const String &SkeletonData::getHash() { + return _hash; +} + +void SkeletonData::setHash(const String &inValue) { + _hash = inValue; +} + +const String &SkeletonData::getImagesPath() { + return _imagesPath; +} + +void SkeletonData::setImagesPath(const String &inValue) { + _imagesPath = inValue; +} + + +const String &SkeletonData::getAudioPath() { + return _audioPath; +} + +void SkeletonData::setAudioPath(const String &inValue) { + _audioPath = inValue; +} + +float SkeletonData::getFps() { + return _fps; +} + +void SkeletonData::setFps(float inValue) { + _fps = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp new file mode 100644 index 0000000..ac21f0a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -0,0 +1,1476 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +static float toColor(const char *value, size_t index) { + char digits[3]; + char *error; + int color; + + if (index >= strlen(value) / 2) return -1; + + value += index * 2; + + digits[0] = *value; + digits[1] = *(value + 1); + digits[2] = '\0'; + color = (int) strtoul(digits, &error, 16); + if (*error != 0) return -1; + + return color / (float) 255; +} + +static void toColor(Color &color, const char *value, bool hasAlpha) { + color.r = toColor(value, 0); + color.g = toColor(value, 1); + color.b = toColor(value, 2); + if (hasAlpha) color.a = toColor(value, 3); +} + +SkeletonJson::SkeletonJson(Atlas *atlas) : _attachmentLoader(new (__FILE__, __LINE__) AtlasAttachmentLoader(atlas)), + _scale(1), _ownsLoader(true) {} + +SkeletonJson::SkeletonJson(AttachmentLoader *attachmentLoader, bool ownsLoader) : _attachmentLoader(attachmentLoader), + _scale(1), + _ownsLoader(ownsLoader) { + assert(_attachmentLoader != NULL); +} + +SkeletonJson::~SkeletonJson() { + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + + if (_ownsLoader) delete _attachmentLoader; +} + +SkeletonData *SkeletonJson::readSkeletonDataFile(const String &path) { + int length; + SkeletonData *skeletonData; + const char *json = SpineExtension::readFile(path, &length); + if (length == 0 || !json) { + setError(NULL, "Unable to read skeleton file: ", path); + return NULL; + } + + skeletonData = readSkeletonData(json); + + SpineExtension::free(json, __FILE__, __LINE__); + + return skeletonData; +} + +SkeletonData *SkeletonJson::readSkeletonData(const char *json) { + int i, ii; + SkeletonData *skeletonData; + Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *slots, *skins, *animations, *events; + + _error = ""; + _linkedMeshes.clear(); + + root = new (__FILE__, __LINE__) Json(json); + + if (!root) { + setError(NULL, "Invalid skeleton JSON: ", Json::getError()); + return NULL; + } + + skeletonData = new (__FILE__, __LINE__) SkeletonData(); + + skeleton = Json::getItem(root, "skeleton"); + if (skeleton) { + skeletonData->_hash = Json::getString(skeleton, "hash", 0); + skeletonData->_version = Json::getString(skeleton, "spine", 0); + if (!skeletonData->_version.startsWith(SPINE_VERSION_STRING)) { + char errorMsg[255]; + snprintf(errorMsg, 255, "Skeleton version %s does not match runtime version %s", skeletonData->_version.buffer(), SPINE_VERSION_STRING); + setError(NULL, errorMsg, ""); + return NULL; + } + skeletonData->_x = Json::getFloat(skeleton, "x", 0); + skeletonData->_y = Json::getFloat(skeleton, "y", 0); + skeletonData->_width = Json::getFloat(skeleton, "width", 0); + skeletonData->_height = Json::getFloat(skeleton, "height", 0); + skeletonData->_fps = Json::getFloat(skeleton, "fps", 30); + skeletonData->_audioPath = Json::getString(skeleton, "audio", 0); + skeletonData->_imagesPath = Json::getString(skeleton, "images", 0); + } + + /* Bones. */ + bones = Json::getItem(root, "bones"); + skeletonData->_bones.setSize(bones->_size, 0); + int bonesCount = 0; + for (boneMap = bones->_child, i = 0; boneMap; boneMap = boneMap->_next, ++i) { + BoneData *data; + const char *transformMode; + + BoneData *parent = 0; + const char *parentName = Json::getString(boneMap, "parent", 0); + if (parentName) { + parent = skeletonData->findBone(parentName); + if (!parent) { + delete skeletonData; + setError(root, "Parent bone not found: ", parentName); + return NULL; + } + } + + data = new (__FILE__, __LINE__) BoneData(bonesCount, Json::getString(boneMap, "name", 0), parent); + + data->_length = Json::getFloat(boneMap, "length", 0) * _scale; + data->_x = Json::getFloat(boneMap, "x", 0) * _scale; + data->_y = Json::getFloat(boneMap, "y", 0) * _scale; + data->_rotation = Json::getFloat(boneMap, "rotation", 0); + data->_scaleX = Json::getFloat(boneMap, "scaleX", 1); + data->_scaleY = Json::getFloat(boneMap, "scaleY", 1); + data->_shearX = Json::getFloat(boneMap, "shearX", 0); + data->_shearY = Json::getFloat(boneMap, "shearY", 0); + transformMode = Json::getString(boneMap, "transform", "normal"); + data->_transformMode = TransformMode_Normal; + if (strcmp(transformMode, "normal") == 0) data->_transformMode = TransformMode_Normal; + else if (strcmp(transformMode, "onlyTranslation") == 0) + data->_transformMode = TransformMode_OnlyTranslation; + else if (strcmp(transformMode, "noRotationOrReflection") == 0) + data->_transformMode = TransformMode_NoRotationOrReflection; + else if (strcmp(transformMode, "noScale") == 0) + data->_transformMode = TransformMode_NoScale; + else if (strcmp(transformMode, "noScaleOrReflection") == 0) + data->_transformMode = TransformMode_NoScaleOrReflection; + data->_skinRequired = Json::getBoolean(boneMap, "skin", false); + + const char *color = Json::getString(boneMap, "color", NULL); + if (color) toColor(data->getColor(), color, true); + + skeletonData->_bones[i] = data; + bonesCount++; + } + + /* Slots. */ + slots = Json::getItem(root, "slots"); + if (slots) { + Json *slotMap; + skeletonData->_slots.ensureCapacity(slots->_size); + skeletonData->_slots.setSize(slots->_size, 0); + for (slotMap = slots->_child, i = 0; slotMap; slotMap = slotMap->_next, ++i) { + SlotData *data; + const char *color; + const char *dark; + Json *item; + + const char *boneName = Json::getString(slotMap, "bone", 0); + BoneData *boneData = skeletonData->findBone(boneName); + if (!boneData) { + delete skeletonData; + setError(root, "Slot bone not found: ", boneName); + return NULL; + } + + data = new (__FILE__, __LINE__) SlotData(i, Json::getString(slotMap, "name", 0), *boneData); + + color = Json::getString(slotMap, "color", 0); + if (color) { + Color &c = data->getColor(); + c.r = toColor(color, 0); + c.g = toColor(color, 1); + c.b = toColor(color, 2); + c.a = toColor(color, 3); + } + + dark = Json::getString(slotMap, "dark", 0); + if (dark) { + Color &darkColor = data->getDarkColor(); + darkColor.r = toColor(dark, 0); + darkColor.g = toColor(dark, 1); + darkColor.b = toColor(dark, 2); + darkColor.a = 1; + data->setHasDarkColor(true); + } + + item = Json::getItem(slotMap, "attachment"); + if (item) data->setAttachmentName(item->_valueString); + + item = Json::getItem(slotMap, "blend"); + if (item) { + if (strcmp(item->_valueString, "additive") == 0) data->_blendMode = BlendMode_Additive; + else if (strcmp(item->_valueString, "multiply") == 0) + data->_blendMode = BlendMode_Multiply; + else if (strcmp(item->_valueString, "screen") == 0) + data->_blendMode = BlendMode_Screen; + } + + skeletonData->_slots[i] = data; + } + } + + /* IK constraints. */ + ik = Json::getItem(root, "ik"); + if (ik) { + Json *constraintMap; + skeletonData->_ikConstraints.ensureCapacity(ik->_size); + skeletonData->_ikConstraints.setSize(ik->_size, 0); + for (constraintMap = ik->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *targetName; + + IkConstraintData *data = new (__FILE__, __LINE__) IkConstraintData( + Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.ensureCapacity(boneMap->_size); + data->_bones.setSize(boneMap->_size, 0); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) { + delete skeletonData; + setError(root, "IK bone not found: ", boneMap->_valueString); + return NULL; + } + } + + targetName = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findBone(targetName); + if (!data->_target) { + delete skeletonData; + setError(root, "Target bone not found: ", targetName); + return NULL; + } + + data->_mix = Json::getFloat(constraintMap, "mix", 1); + data->_softness = Json::getFloat(constraintMap, "softness", 0) * _scale; + data->_bendDirection = Json::getInt(constraintMap, "bendPositive", 1) ? 1 : -1; + data->_compress = Json::getInt(constraintMap, "compress", 0) ? true : false; + data->_stretch = Json::getInt(constraintMap, "stretch", 0) ? true : false; + data->_uniform = Json::getInt(constraintMap, "uniform", 0) ? true : false; + + skeletonData->_ikConstraints[i] = data; + } + } + + /* Transform constraints. */ + transform = Json::getItem(root, "transform"); + if (transform) { + Json *constraintMap; + skeletonData->_transformConstraints.ensureCapacity(transform->_size); + skeletonData->_transformConstraints.setSize(transform->_size, 0); + for (constraintMap = transform->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *name; + + TransformConstraintData *data = new (__FILE__, __LINE__) TransformConstraintData( + Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.ensureCapacity(boneMap->_size); + data->_bones.setSize(boneMap->_size, 0); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) { + delete skeletonData; + setError(root, "Transform bone not found: ", boneMap->_valueString); + return NULL; + } + } + + name = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findBone(name); + if (!data->_target) { + delete skeletonData; + setError(root, "Target bone not found: ", name); + return NULL; + } + + data->_local = Json::getInt(constraintMap, "local", 0) ? true : false; + data->_relative = Json::getInt(constraintMap, "relative", 0) ? true : false; + data->_offsetRotation = Json::getFloat(constraintMap, "rotation", 0); + data->_offsetX = Json::getFloat(constraintMap, "x", 0) * _scale; + data->_offsetY = Json::getFloat(constraintMap, "y", 0) * _scale; + data->_offsetScaleX = Json::getFloat(constraintMap, "scaleX", 0); + data->_offsetScaleY = Json::getFloat(constraintMap, "scaleY", 0); + data->_offsetShearY = Json::getFloat(constraintMap, "shearY", 0); + + data->_mixRotate = Json::getFloat(constraintMap, "mixRotate", 1); + data->_mixX = Json::getFloat(constraintMap, "mixX", 1); + data->_mixY = Json::getFloat(constraintMap, "mixY", data->_mixX); + data->_mixScaleX = Json::getFloat(constraintMap, "mixScaleX", 1); + data->_mixScaleY = Json::getFloat(constraintMap, "mixScaleY", data->_mixScaleX); + data->_mixShearY = Json::getFloat(constraintMap, "mixShearY", 1); + + skeletonData->_transformConstraints[i] = data; + } + } + + /* Path constraints */ + path = Json::getItem(root, "path"); + if (path) { + Json *constraintMap; + skeletonData->_pathConstraints.ensureCapacity(path->_size); + skeletonData->_pathConstraints.setSize(path->_size, 0); + for (constraintMap = path->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *name; + const char *item; + + PathConstraintData *data = new (__FILE__, __LINE__) PathConstraintData( + Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.ensureCapacity(boneMap->_size); + data->_bones.setSize(boneMap->_size, 0); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) { + delete skeletonData; + setError(root, "Path bone not found: ", boneMap->_valueString); + return NULL; + } + } + + name = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findSlot(name); + if (!data->_target) { + delete skeletonData; + setError(root, "Target slot not found: ", name); + return NULL; + } + + item = Json::getString(constraintMap, "positionMode", "percent"); + if (strcmp(item, "fixed") == 0) { + data->_positionMode = PositionMode_Fixed; + } else if (strcmp(item, "percent") == 0) { + data->_positionMode = PositionMode_Percent; + } + + item = Json::getString(constraintMap, "spacingMode", "length"); + if (strcmp(item, "length") == 0) data->_spacingMode = SpacingMode_Length; + else if (strcmp(item, "fixed") == 0) + data->_spacingMode = SpacingMode_Fixed; + else if (strcmp(item, "percent") == 0) + data->_spacingMode = SpacingMode_Percent; + else + data->_spacingMode = SpacingMode_Proportional; + + item = Json::getString(constraintMap, "rotateMode", "tangent"); + if (strcmp(item, "tangent") == 0) data->_rotateMode = RotateMode_Tangent; + else if (strcmp(item, "chain") == 0) + data->_rotateMode = RotateMode_Chain; + else if (strcmp(item, "chainScale") == 0) + data->_rotateMode = RotateMode_ChainScale; + + data->_offsetRotation = Json::getFloat(constraintMap, "rotation", 0); + data->_position = Json::getFloat(constraintMap, "position", 0); + if (data->_positionMode == PositionMode_Fixed) data->_position *= _scale; + data->_spacing = Json::getFloat(constraintMap, "spacing", 0); + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) + data->_spacing *= _scale; + data->_mixRotate = Json::getFloat(constraintMap, "mixRotate", 1); + data->_mixX = Json::getFloat(constraintMap, "mixX", 1); + data->_mixY = Json::getFloat(constraintMap, "mixY", data->_mixX); + + skeletonData->_pathConstraints[i] = data; + } + } + + /* Skins. */ + skins = Json::getItem(root, "skins"); + if (skins) { + Json *skinMap; + skeletonData->_skins.ensureCapacity(skins->_size); + skeletonData->_skins.setSize(skins->_size, 0); + int skinsIndex = 0; + for (skinMap = skins->_child, i = 0; skinMap; skinMap = skinMap->_next, ++i) { + Json *attachmentsMap; + Json *curves; + + Skin *skin = new (__FILE__, __LINE__) Skin(Json::getString(skinMap, "name", "")); + + Json *item = Json::getItem(skinMap, "bones"); + if (item) { + for (item = item->_child; item; item = item->_next) { + BoneData *data = skeletonData->findBone(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin bone not found: "), item->_valueString); + return NULL; + } + skin->getBones().add(data); + } + } + + item = Json::getItem(skinMap, "ik"); + if (item) { + for (item = item->_child; item; item = item->_next) { + IkConstraintData *data = skeletonData->findIkConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin IK constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + item = Json::getItem(skinMap, "transform"); + if (item) { + for (item = item->_child; item; item = item->_next) { + TransformConstraintData *data = skeletonData->findTransformConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin transform constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + item = Json::getItem(skinMap, "path"); + if (item) { + for (item = item->_child; item; item = item->_next) { + PathConstraintData *data = skeletonData->findPathConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin path constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + skeletonData->_skins[skinsIndex++] = skin; + if (strcmp(Json::getString(skinMap, "name", ""), "default") == 0) { + skeletonData->_defaultSkin = skin; + } + + Json *attachments = Json::getItem(skinMap, "attachments"); + if (attachments) + for (attachmentsMap = attachments->_child; + attachmentsMap; attachmentsMap = attachmentsMap->_next) { + SlotData *slot = skeletonData->findSlot(attachmentsMap->_name); + Json *attachmentMap; + + for (attachmentMap = attachmentsMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) { + Attachment *attachment = NULL; + const char *skinAttachmentName = attachmentMap->_name; + const char *attachmentName = Json::getString(attachmentMap, "name", skinAttachmentName); + const char *attachmentPath = Json::getString(attachmentMap, "path", attachmentName); + const char *color; + Json *entry; + + const char *typeString = Json::getString(attachmentMap, "type", "region"); + AttachmentType type; + if (strcmp(typeString, "region") == 0) type = AttachmentType_Region; + else if (strcmp(typeString, "mesh") == 0) + type = AttachmentType_Mesh; + else if (strcmp(typeString, "linkedmesh") == 0) + type = AttachmentType_Linkedmesh; + else if (strcmp(typeString, "boundingbox") == 0) + type = AttachmentType_Boundingbox; + else if (strcmp(typeString, "path") == 0) + type = AttachmentType_Path; + else if (strcmp(typeString, "clipping") == 0) + type = AttachmentType_Clipping; + else if (strcmp(typeString, "point") == 0) + type = AttachmentType_Point; + else { + delete skeletonData; + setError(root, "Unknown attachment type: ", typeString); + return NULL; + } + + switch (type) { + case AttachmentType_Region: { + Sequence *sequence = readSequence(Json::getItem(attachmentMap, "sequence")); + attachment = _attachmentLoader->newRegionAttachment(*skin, attachmentName, attachmentPath, sequence); + if (!attachment) { + delete skeletonData; + setError(root, "Error reading attachment: ", skinAttachmentName); + return NULL; + } + + RegionAttachment *region = static_cast(attachment); + region->_path = attachmentPath; + + region->_x = Json::getFloat(attachmentMap, "x", 0) * _scale; + region->_y = Json::getFloat(attachmentMap, "y", 0) * _scale; + region->_scaleX = Json::getFloat(attachmentMap, "scaleX", 1); + region->_scaleY = Json::getFloat(attachmentMap, "scaleY", 1); + region->_rotation = Json::getFloat(attachmentMap, "rotation", 0); + region->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; + region->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; + region->_sequence = sequence; + + color = Json::getString(attachmentMap, "color", 0); + if (color) toColor(region->getColor(), color, true); + + if (region->_region != NULL) region->updateRegion(); + _attachmentLoader->configureAttachment(region); + break; + } + case AttachmentType_Mesh: + case AttachmentType_Linkedmesh: { + Sequence *sequence = readSequence(Json::getItem(attachmentMap, "sequence")); + attachment = _attachmentLoader->newMeshAttachment(*skin, attachmentName, attachmentPath, sequence); + + if (!attachment) { + delete skeletonData; + setError(root, "Error reading attachment: ", skinAttachmentName); + return NULL; + } + + MeshAttachment *mesh = static_cast(attachment); + mesh->_path = attachmentPath; + + color = Json::getString(attachmentMap, "color", 0); + if (color) toColor(mesh->getColor(), color, true); + + mesh->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; + mesh->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; + mesh->_sequence = sequence; + + entry = Json::getItem(attachmentMap, "parent"); + if (!entry) { + int verticesLength; + entry = Json::getItem(attachmentMap, "triangles"); + mesh->_triangles.ensureCapacity(entry->_size); + mesh->_triangles.setSize(entry->_size, 0); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + mesh->_triangles[ii] = (unsigned short) entry->_valueInt; + + entry = Json::getItem(attachmentMap, "uvs"); + verticesLength = entry->_size; + mesh->_regionUVs.ensureCapacity(verticesLength); + mesh->_regionUVs.setSize(verticesLength, 0); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + mesh->_regionUVs[ii] = entry->_valueFloat; + + readVertices(attachmentMap, mesh, verticesLength); + + if (mesh->_region != NULL) mesh->updateRegion(); + + mesh->_hullLength = Json::getInt(attachmentMap, "hull", 0); + + entry = Json::getItem(attachmentMap, "edges"); + if (entry) { + mesh->_edges.ensureCapacity(entry->_size); + mesh->_edges.setSize(entry->_size, 0); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + mesh->_edges[ii] = entry->_valueInt; + } + _attachmentLoader->configureAttachment(mesh); + } else { + bool inheritTimelines = Json::getInt(attachmentMap, "timelines", 1) ? true : false; + LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, + String(Json::getString( + attachmentMap, + "skin", 0)), + slot->getIndex(), + String(entry->_valueString), + inheritTimelines); + _linkedMeshes.add(linkedMesh); + } + break; + } + case AttachmentType_Boundingbox: { + attachment = _attachmentLoader->newBoundingBoxAttachment(*skin, attachmentName); + + BoundingBoxAttachment *box = static_cast(attachment); + + int vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; + readVertices(attachmentMap, box, vertexCount); + color = Json::getString(attachmentMap, "color", NULL); + if (color) toColor(box->getColor(), color, true); + _attachmentLoader->configureAttachment(attachment); + break; + } + case AttachmentType_Path: { + attachment = _attachmentLoader->newPathAttachment(*skin, attachmentName); + + PathAttachment *pathAttatchment = static_cast(attachment); + + int vertexCount = 0; + pathAttatchment->_closed = Json::getInt(attachmentMap, "closed", 0) ? true : false; + pathAttatchment->_constantSpeed = Json::getInt(attachmentMap, "constantSpeed", 1) ? true + : false; + vertexCount = Json::getInt(attachmentMap, "vertexCount", 0); + readVertices(attachmentMap, pathAttatchment, vertexCount << 1); + + pathAttatchment->_lengths.ensureCapacity(vertexCount / 3); + pathAttatchment->_lengths.setSize(vertexCount / 3, 0); + + curves = Json::getItem(attachmentMap, "lengths"); + for (curves = curves->_child, ii = 0; curves; curves = curves->_next, ++ii) + pathAttatchment->_lengths[ii] = curves->_valueFloat * _scale; + color = Json::getString(attachmentMap, "color", NULL); + if (color) toColor(pathAttatchment->getColor(), color, true); + _attachmentLoader->configureAttachment(attachment); + break; + } + case AttachmentType_Point: { + attachment = _attachmentLoader->newPointAttachment(*skin, attachmentName); + + PointAttachment *point = static_cast(attachment); + + point->_x = Json::getFloat(attachmentMap, "x", 0) * _scale; + point->_y = Json::getFloat(attachmentMap, "y", 0) * _scale; + point->_rotation = Json::getFloat(attachmentMap, "rotation", 0); + color = Json::getString(attachmentMap, "color", NULL); + if (color) toColor(point->getColor(), color, true); + _attachmentLoader->configureAttachment(attachment); + break; + } + case AttachmentType_Clipping: { + attachment = _attachmentLoader->newClippingAttachment(*skin, attachmentName); + + ClippingAttachment *clip = static_cast(attachment); + + int vertexCount = 0; + const char *end = Json::getString(attachmentMap, "end", 0); + if (end) clip->_endSlot = skeletonData->findSlot(end); + vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; + readVertices(attachmentMap, clip, vertexCount); + color = Json::getString(attachmentMap, "color", NULL); + if (color) toColor(clip->getColor(), color, true); + _attachmentLoader->configureAttachment(attachment); + break; + } + } + + skin->setAttachment(slot->getIndex(), skinAttachmentName, attachment); + } + } + } + } + + /* Linked meshes. */ + int n = (int) _linkedMeshes.size(); + for (i = 0; i < n; ++i) { + LinkedMesh *linkedMesh = _linkedMeshes[i]; + Skin *skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin(linkedMesh->_skin); + if (skin == NULL) { + delete skeletonData; + setError(root, "Skin not found: ", linkedMesh->_skin.buffer()); + return NULL; + } + Attachment *parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); + if (parent == NULL) { + delete skeletonData; + setError(root, "Parent mesh not found: ", linkedMesh->_parent.buffer()); + return NULL; + } + linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritTimeline ? static_cast(parent) + : linkedMesh->_mesh; + linkedMesh->_mesh->setParentMesh(static_cast(parent)); + if (linkedMesh->_mesh->_region != NULL) linkedMesh->_mesh->updateRegion(); + _attachmentLoader->configureAttachment(linkedMesh->_mesh); + } + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + /* Events. */ + events = Json::getItem(root, "events"); + if (events) { + Json *eventMap; + skeletonData->_events.ensureCapacity(events->_size); + skeletonData->_events.setSize(events->_size, 0); + for (eventMap = events->_child, i = 0; eventMap; eventMap = eventMap->_next, ++i) { + EventData *eventData = new (__FILE__, __LINE__) EventData(String(eventMap->_name)); + + eventData->_intValue = Json::getInt(eventMap, "int", 0); + eventData->_floatValue = Json::getFloat(eventMap, "float", 0); + const char *stringValue = Json::getString(eventMap, "string", 0); + eventData->_stringValue = stringValue; + const char *audioPath = Json::getString(eventMap, "audio", 0); + eventData->_audioPath = audioPath; + if (audioPath) { + eventData->_volume = Json::getFloat(eventMap, "volume", 1); + eventData->_balance = Json::getFloat(eventMap, "balance", 0); + } + skeletonData->_events[i] = eventData; + } + } + + /* Animations. */ + animations = Json::getItem(root, "animations"); + if (animations) { + Json *animationMap; + skeletonData->_animations.ensureCapacity(animations->_size); + skeletonData->_animations.setSize(animations->_size, 0); + int animationsIndex = 0; + for (animationMap = animations->_child; animationMap; animationMap = animationMap->_next) { + Animation *animation = readAnimation(animationMap, skeletonData); + if (!animation) { + delete skeletonData; + delete root; + return NULL; + } + skeletonData->_animations[animationsIndex++] = animation; + } + } + + delete root; + + return skeletonData; +} + +Sequence *SkeletonJson::readSequence(Json *item) { + if (item == NULL) return NULL; + Sequence *sequence = new Sequence(Json::getInt(item, "count", 0)); + sequence->_start = Json::getInt(item, "start", 1); + sequence->_digits = Json::getInt(item, "digits", 0); + sequence->_setupIndex = Json::getInt(item, "setupIndex", 0); + return sequence; +} + +void SkeletonJson::setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1, + float cy1, + float cx2, float cy2, float time2, float value2) { + timeline->setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2); +} + +int SkeletonJson::readCurve(Json *curve, CurveTimeline *timeline, int bezier, int frame, int value, float time1, + float time2, + float value1, float value2, float scale) { + if (curve->_type == Json::JSON_STRING && strcmp(curve->_valueString, "stepped") == 0) { + timeline->setStepped(frame); + return bezier; + } + curve = Json::getItem(curve, value << 2); + float cx1 = curve->_valueFloat; + curve = curve->_next; + float cy1 = curve->_valueFloat * scale; + curve = curve->_next; + float cx2 = curve->_valueFloat; + curve = curve->_next; + float cy2 = curve->_valueFloat * scale; + setBezier(timeline, frame, value, bezier, time1, value1, cx1, cy1, cx2, cy2, time2, value2); + return bezier + 1; +} + +Timeline *SkeletonJson::readTimeline(Json *keyMap, CurveTimeline1 *timeline, float defaultValue, float scale) { + float time = Json::getFloat(keyMap, "time", 0); + float value = Json::getFloat(keyMap, "value", defaultValue) * scale; + int bezier = 0; + for (int frame = 0;; frame++) { + timeline->setFrame(frame, time, value); + Json *nextMap = keyMap->_next; + if (!nextMap) break; + float time2 = Json::getFloat(nextMap, "time", 0); + float value2 = Json::getFloat(nextMap, "value", defaultValue) * scale; + Json *curve = Json::getItem(keyMap, "curve"); + if (curve != NULL) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value, value2, scale); + time = time2; + value = value2; + keyMap = nextMap; + } + // timeline.shrink(); // BOZO + return timeline; +} + +Timeline *SkeletonJson::readTimeline(Json *keyMap, CurveTimeline2 *timeline, const char *name1, const char *name2, + float defaultValue, float scale) { + float time = Json::getFloat(keyMap, "time", 0); + float value1 = Json::getFloat(keyMap, name1, defaultValue) * scale; + float value2 = Json::getFloat(keyMap, name2, defaultValue) * scale; + int bezier = 0; + for (int frame = 0;; frame++) { + timeline->setFrame(frame, time, value1, value2); + Json *nextMap = keyMap->_next; + if (!nextMap) break; + float time2 = Json::getFloat(nextMap, "time", 0); + float nvalue1 = Json::getFloat(nextMap, name1, defaultValue) * scale; + float nvalue2 = Json::getFloat(nextMap, name2, defaultValue) * scale; + Json *curve = Json::getItem(keyMap, "curve"); + if (curve != NULL) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + keyMap = nextMap; + } + // timeline.shrink(); // BOZO + return timeline; +} + +int SkeletonJson::findSlotIndex(SkeletonData *skeletonData, const String &slotName, Vector timelines) { + int slotIndex = ContainerUtil::findIndexWithName(skeletonData->getSlots(), slotName); + if (slotIndex == -1) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Slot not found: ", slotName); + } + return slotIndex; +} + +Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) { + Vector timelines; + Json *bones = Json::getItem(root, "bones"); + Json *slots = Json::getItem(root, "slots"); + Json *ik = Json::getItem(root, "ik"); + Json *transform = Json::getItem(root, "transform"); + Json *paths = Json::getItem(root, "path"); + Json *attachments = Json::getItem(root, "attachments"); + Json *drawOrder = Json::getItem(root, "drawOrder"); + Json *events = Json::getItem(root, "events"); + Json *boneMap, *slotMap, *keyMap, *nextMap, *curve; + int frame, bezier; + Color color, color2, newColor, newColor2; + + /** Slot timelines. */ + for (slotMap = slots ? slots->_child : 0; slotMap; slotMap = slotMap->_next) { + int slotIndex = findSlotIndex(skeletonData, slotMap->_name, timelines); + if (slotIndex == -1) return NULL; + + for (Json *timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) { + int frames = timelineMap->_size; + if (strcmp(timelineMap->_name, "attachment") == 0) { + AttachmentTimeline *timeline = new (__FILE__, __LINE__) AttachmentTimeline(frames, slotIndex); + for (keyMap = timelineMap->_child, frame = 0; keyMap; keyMap = keyMap->_next, ++frame) { + timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0), + Json::getItem(keyMap, "name") ? Json::getItem(keyMap, "name")->_valueString : NULL); + } + timelines.add(timeline); + + } else if (strcmp(timelineMap->_name, "rgba") == 0) { + RGBATimeline *timeline = new (__FILE__, __LINE__) RGBATimeline(frames, frames << 2, slotIndex); + keyMap = timelineMap->_child; + float time = Json::getFloat(keyMap, "time", 0); + toColor(color, Json::getString(keyMap, "color", 0), true); + + for (frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b, color.a); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + toColor(newColor, Json::getString(nextMap, "color", 0), true); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (strcmp(timelineMap->_name, "rgb") == 0) { + RGBTimeline *timeline = new (__FILE__, __LINE__) RGBTimeline(frames, frames * 3, slotIndex); + keyMap = timelineMap->_child; + float time = Json::getFloat(keyMap, "time", 0); + toColor(color, Json::getString(keyMap, "color", 0), false); + + for (frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + toColor(newColor, Json::getString(nextMap, "color", 0), false); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (strcmp(timelineMap->_name, "alpha") == 0) { + timelines.add(readTimeline(timelineMap->_child, + new (__FILE__, __LINE__) AlphaTimeline(frames, frames, slotIndex), + 0, 1)); + } else if (strcmp(timelineMap->_name, "rgba2") == 0) { + RGBA2Timeline *timeline = new (__FILE__, __LINE__) RGBA2Timeline(frames, frames * 7, slotIndex); + keyMap = timelineMap->_child; + float time = Json::getFloat(keyMap, "time", 0); + toColor(color, Json::getString(keyMap, "light", 0), true); + toColor(color2, Json::getString(keyMap, "dark", 0), false); + + for (frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + toColor(newColor, Json::getString(nextMap, "light", 0), true); + toColor(newColor2, Json::getString(nextMap, "dark", 0), false); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (strcmp(timelineMap->_name, "rgb2") == 0) { + RGBA2Timeline *timeline = new (__FILE__, __LINE__) RGBA2Timeline(frames, frames * 6, slotIndex); + keyMap = timelineMap->_child; + float time = Json::getFloat(keyMap, "time", 0); + toColor(color, Json::getString(keyMap, "light", 0), false); + toColor(color2, Json::getString(keyMap, "dark", 0), false); + + for (frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + toColor(newColor, Json::getString(nextMap, "light", 0), false); + toColor(newColor2, Json::getString(nextMap, "dark", 0), false); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.add(timeline); + } else { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Invalid timeline type for a slot: ", timelineMap->_name); + return NULL; + } + } + } + + /** Bone timelines. */ + for (boneMap = bones ? bones->_child : 0; boneMap; boneMap = boneMap->_next) { + int boneIndex = ContainerUtil::findIndexWithName(skeletonData->_bones, boneMap->_name); + if (boneIndex == -1) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Bone not found: ", boneMap->_name); + return NULL; + } + + for (Json *timelineMap = boneMap->_child; timelineMap; timelineMap = timelineMap->_next) { + int frames = timelineMap->_size; + if (frames == 0) continue; + + if (strcmp(timelineMap->_name, "rotate") == 0) { + timelines.add(readTimeline(timelineMap->_child, + new RotateTimeline(frames, frames, boneIndex), 0, + 1)); + } else if (strcmp(timelineMap->_name, "translate") == 0) { + TranslateTimeline *timeline = new TranslateTimeline(frames, frames << 1, + boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, "x", "y", 0, _scale)); + } else if (strcmp(timelineMap->_name, "translatex") == 0) { + TranslateXTimeline *timeline = new TranslateXTimeline(frames, frames, + boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 0, _scale)); + } else if (strcmp(timelineMap->_name, "translatey") == 0) { + TranslateYTimeline *timeline = new TranslateYTimeline(frames, frames, + boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 0, _scale)); + } else if (strcmp(timelineMap->_name, "scale") == 0) { + ScaleTimeline *timeline = new (__FILE__, __LINE__) ScaleTimeline(frames, + frames << 1, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, "x", "y", 1, 1)); + } else if (strcmp(timelineMap->_name, "scalex") == 0) { + ScaleXTimeline *timeline = new (__FILE__, __LINE__) ScaleXTimeline(frames, + frames, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 1, 1)); + } else if (strcmp(timelineMap->_name, "scaley") == 0) { + ScaleYTimeline *timeline = new (__FILE__, __LINE__) ScaleYTimeline(frames, + frames, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 1, 1)); + } else if (strcmp(timelineMap->_name, "shear") == 0) { + ShearTimeline *timeline = new (__FILE__, __LINE__) ShearTimeline(frames, + frames << 1, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, "x", "y", 0, 1)); + } else if (strcmp(timelineMap->_name, "shearx") == 0) { + ShearXTimeline *timeline = new (__FILE__, __LINE__) ShearXTimeline(frames, + frames, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 0, 1)); + } else if (strcmp(timelineMap->_name, "sheary") == 0) { + ShearYTimeline *timeline = new (__FILE__, __LINE__) ShearYTimeline(frames, + frames, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 0, 1)); + } else { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Invalid timeline type for a bone: ", timelineMap->_name); + return NULL; + } + } + } + + /** IK constraint timelines. */ + for (Json *constraintMap = ik ? ik->_child : 0; constraintMap; constraintMap = constraintMap->_next) { + keyMap = constraintMap->_child; + if (keyMap == NULL) continue; + + IkConstraintData *constraint = skeletonData->findIkConstraint(constraintMap->_name); + int constraintIndex = skeletonData->_ikConstraints.indexOf(constraint); + IkConstraintTimeline *timeline = new (__FILE__, __LINE__) IkConstraintTimeline(constraintMap->_size, + constraintMap->_size << 1, + constraintIndex); + + float time = Json::getFloat(keyMap, "time", 0); + float mix = Json::getFloat(keyMap, "mix", 1); + float softness = Json::getFloat(keyMap, "softness", 0) * _scale; + + for (frame = 0, bezier = 0;; frame++) { + int bendDirection = Json::getBoolean(keyMap, "bendPositive", true) ? 1 : -1; + timeline->setFrame(frame, time, mix, softness, bendDirection, Json::getBoolean(keyMap, "compress", false), + Json::getBoolean(keyMap, "stretch", false)); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + + float time2 = Json::getFloat(nextMap, "time", 0); + float mix2 = Json::getFloat(nextMap, "mix", 1); + float softness2 = Json::getFloat(nextMap, "softness", 0) * _scale; + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, _scale); + } + + time = time2; + mix = mix2; + softness = softness2; + keyMap = nextMap; + } + + timelines.add(timeline); + } + + /** Transform constraint timelines. */ + for (Json *constraintMap = transform ? transform->_child : 0; constraintMap; constraintMap = constraintMap->_next) { + keyMap = constraintMap->_child; + if (keyMap == NULL) continue; + + TransformConstraintData *constraint = skeletonData->findTransformConstraint(constraintMap->_name); + int constraintIndex = skeletonData->_transformConstraints.indexOf(constraint); + TransformConstraintTimeline *timeline = new (__FILE__, __LINE__) TransformConstraintTimeline( + constraintMap->_size, constraintMap->_size * 6, constraintIndex); + + float time = Json::getFloat(keyMap, "time", 0); + float mixRotate = Json::getFloat(keyMap, "mixRotate", 1); + float mixShearY = Json::getFloat(keyMap, "mixShearY", 1); + float mixX = Json::getFloat(keyMap, "mixX", 1); + float mixY = Json::getFloat(keyMap, "mixY", mixX); + float mixScaleX = Json::getFloat(keyMap, "mixScaleX", 1); + float mixScaleY = Json::getFloat(keyMap, "mixScaleY", mixScaleX); + + for (frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + + float time2 = Json::getFloat(nextMap, "time", 0); + float mixRotate2 = Json::getFloat(nextMap, "mixRotate", 1); + float mixShearY2 = Json::getFloat(nextMap, "mixShearY", 1); + float mixX2 = Json::getFloat(nextMap, "mixX", 1); + float mixY2 = Json::getFloat(nextMap, "mixY", mixX2); + float mixScaleX2 = Json::getFloat(nextMap, "mixScaleX", 1); + float mixScaleY2 = Json::getFloat(nextMap, "mixScaleY", mixScaleX2); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixScaleX = mixScaleX2; + keyMap = nextMap; + } + + timelines.add(timeline); + } + + /** Path constraint timelines. */ + for (Json *constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) { + PathConstraintData *constraint = skeletonData->findPathConstraint(constraintMap->_name); + if (!constraint) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Path constraint not found: ", constraintMap->_name); + return NULL; + } + int constraintIndex = skeletonData->_pathConstraints.indexOf(constraint); + for (Json *timelineMap = constraintMap->_child; timelineMap; timelineMap = timelineMap->_next) { + keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + const char *timelineName = timelineMap->_name; + int frames = timelineMap->_size; + if (strcmp(timelineName, "position") == 0) { + PathConstraintPositionTimeline *timeline = new (__FILE__, __LINE__) PathConstraintPositionTimeline( + frames, frames, constraintIndex); + timelines.add( + readTimeline(keyMap, timeline, 0, constraint->_positionMode == PositionMode_Fixed ? _scale : 1)); + } else if (strcmp(timelineName, "spacing") == 0) { + CurveTimeline1 *timeline = new PathConstraintSpacingTimeline(frames, frames, + constraintIndex); + timelines.add(readTimeline(keyMap, timeline, 0, + constraint->_spacingMode == SpacingMode_Length || + constraint->_spacingMode == SpacingMode_Fixed + ? _scale + : 1)); + } else if (strcmp(timelineName, "mix") == 0) { + PathConstraintMixTimeline *timeline = new PathConstraintMixTimeline(frames, + frames * 3, constraintIndex); + float time = Json::getFloat(keyMap, "time", 0); + float mixRotate = Json::getFloat(keyMap, "mixRotate", 1); + float mixX = Json::getFloat(keyMap, "mixX", 1); + float mixY = Json::getFloat(keyMap, "mixY", mixX); + for (frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + float mixRotate2 = Json::getFloat(nextMap, "mixRotate", 1); + float mixX2 = Json::getFloat(nextMap, "mixX", 1); + float mixY2 = Json::getFloat(nextMap, "mixY", mixX2); + curve = Json::getItem(keyMap, "curve"); + if (curve != NULL) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + keyMap = nextMap; + } + timelines.add(timeline); + } + } + } + + /** Attachment timelines. */ + for (Json *attachmenstMap = attachments ? attachments->_child : NULL; attachmenstMap; attachmenstMap = attachmenstMap->_next) { + Skin *skin = skeletonData->findSkin(attachmenstMap->_name); + for (slotMap = attachmenstMap->_child; slotMap; slotMap = slotMap->_next) { + int slotIndex = findSlotIndex(skeletonData, slotMap->_name, timelines); + if (slotIndex == -1) return NULL; + + for (Json *attachmentMap = slotMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) { + Attachment *attachment = skin->getAttachment(slotIndex, attachmentMap->_name); + if (!attachment) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Attachment not found: ", attachmentMap->_name); + return NULL; + } + + for (Json *timelineMap = attachmentMap->_child; timelineMap; timelineMap = timelineMap->_next) { + keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + int frames = timelineMap->_size; + String timelineName = timelineMap->_name; + if (timelineName == "deform") { + VertexAttachment *vertexAttachment = static_cast(attachment); + bool weighted = vertexAttachment->_bones.size() != 0; + Vector &verts = vertexAttachment->_vertices; + int deformLength = weighted ? (int) verts.size() / 3 * 2 : (int) verts.size(); + + DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frames, + frames, slotIndex, vertexAttachment); + float time = Json::getFloat(keyMap, "time", 0); + for (frame = 0, bezier = 0;; frame++) { + Json *vertices = Json::getItem(keyMap, "vertices"); + Vector deformed; + if (!vertices) { + if (weighted) { + deformed.setSize(deformLength, 0); + } else { + deformed.clearAndAddAll(vertexAttachment->_vertices); + } + } else { + deformed.setSize(deformLength, 0); + int v, start = Json::getInt(keyMap, "offset", 0); + Json *vertex; + if (_scale == 1) { + for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { + deformed[v] = vertex->_valueFloat; + } + } else { + for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { + deformed[v] = vertex->_valueFloat * _scale; + } + } + if (!weighted) { + Vector &verticesAttachment = vertexAttachment->_vertices; + for (v = 0; v < deformLength; ++v) { + deformed[v] += verticesAttachment[v]; + } + } + } + timeline->setFrame(frame, time, deformed); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1); + } + time = time2; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (timelineName == "sequence") { + SequenceTimeline *timeline = new SequenceTimeline(frames, slotIndex, attachment); + float lastDelay = 0; + for (frame = 0; keyMap != NULL; keyMap = keyMap->_next, frame++) { + float delay = Json::getFloat(keyMap, "delay", lastDelay); + float time = Json::getFloat(keyMap, "time", 0); + String modeString = Json::getString(keyMap, "mode", "hold"); + int index = Json::getInt(keyMap, "index", 0); + SequenceMode mode = SequenceMode::hold; + if (modeString == "once") mode = SequenceMode::once; + if (modeString == "loop") mode = SequenceMode::loop; + if (modeString == "pingpong") mode = SequenceMode::pingpong; + if (modeString == "onceReverse") mode = SequenceMode::onceReverse; + if (modeString == "loopReverse") mode = SequenceMode::loopReverse; + if (modeString == "pingpongReverse") mode = SequenceMode::pingpongReverse; + timeline->setFrame(frame, time, mode, index, delay); + lastDelay = delay; + } + timelines.add(timeline); + } + } + } + } + } + + /** Draw order timeline. */ + if (drawOrder) { + DrawOrderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderTimeline(drawOrder->_size); + + for (keyMap = drawOrder->_child, frame = 0; keyMap; keyMap = keyMap->_next, ++frame) { + int ii; + Vector drawOrder2; + Json *offsets = Json::getItem(keyMap, "offsets"); + if (offsets) { + Json *offsetMap; + Vector unchanged; + unchanged.ensureCapacity(skeletonData->_slots.size() - offsets->_size); + unchanged.setSize(skeletonData->_slots.size() - offsets->_size, 0); + size_t originalIndex = 0, unchangedIndex = 0; + + drawOrder2.ensureCapacity(skeletonData->_slots.size()); + drawOrder2.setSize(skeletonData->_slots.size(), 0); + for (ii = (int) skeletonData->_slots.size() - 1; ii >= 0; --ii) + drawOrder2[ii] = -1; + + for (offsetMap = offsets->_child; offsetMap; offsetMap = offsetMap->_next) { + int slotIndex = findSlotIndex(skeletonData, Json::getString(offsetMap, "slot", 0), timelines); + if (slotIndex == -1) return NULL; + + /* Collect unchanged items. */ + while (originalIndex != (size_t) slotIndex) + unchanged[unchangedIndex++] = (int) originalIndex++; + /* Set changed items. */ + drawOrder2[originalIndex + Json::getInt(offsetMap, "offset", 0)] = (int) originalIndex; + originalIndex++; + } + /* Collect remaining unchanged items. */ + while ((int) originalIndex < (int) skeletonData->_slots.size()) + unchanged[unchangedIndex++] = (int) originalIndex++; + /* Fill in unchanged items. */ + for (ii = (int) skeletonData->_slots.size() - 1; ii >= 0; ii--) + if (drawOrder2[ii] == -1) drawOrder2[ii] = unchanged[--unchangedIndex]; + } + timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0), drawOrder2); + } + timelines.add(timeline); + } + + /** Event timeline. */ + if (events) { + EventTimeline *timeline = new (__FILE__, __LINE__) EventTimeline(events->_size); + + for (keyMap = events->_child, frame = 0; keyMap; keyMap = keyMap->_next, ++frame) { + Event *event; + EventData *eventData = skeletonData->findEvent(Json::getString(keyMap, "name", 0)); + if (!eventData) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Event not found: ", Json::getString(keyMap, "name", 0)); + return NULL; + } + + event = new (__FILE__, __LINE__) Event(Json::getFloat(keyMap, "time", 0), *eventData); + event->_intValue = Json::getInt(keyMap, "int", eventData->_intValue); + event->_floatValue = Json::getFloat(keyMap, "float", eventData->_floatValue); + event->_stringValue = Json::getString(keyMap, "string", eventData->_stringValue.buffer()); + if (!eventData->_audioPath.isEmpty()) { + event->_volume = Json::getFloat(keyMap, "volume", 1); + event->_balance = Json::getFloat(keyMap, "balance", 0); + } + timeline->setFrame(frame, event); + } + timelines.add(timeline); + } + + float duration = 0; + for (size_t i = 0; i < timelines.size(); i++) + duration = MathUtil::max(duration, timelines[i]->getDuration()); + return new (__FILE__, __LINE__) Animation(String(root->_name), timelines, duration); +} + +void SkeletonJson::readVertices(Json *attachmentMap, VertexAttachment *attachment, size_t verticesLength) { + Json *entry; + size_t i, n, nn, entrySize; + Vector vertices; + + attachment->setWorldVerticesLength(verticesLength); + + entry = Json::getItem(attachmentMap, "vertices"); + entrySize = entry->_size; + vertices.ensureCapacity(entrySize); + vertices.setSize(entrySize, 0); + for (entry = entry->_child, i = 0; entry; entry = entry->_next, ++i) + vertices[i] = entry->_valueFloat; + + if (verticesLength == entrySize) { + if (_scale != 1) { + for (i = 0; i < entrySize; ++i) + vertices[i] *= _scale; + } + + attachment->getVertices().clearAndAddAll(vertices); + return; + } + + Vertices bonesAndWeights; + bonesAndWeights._bones.ensureCapacity(verticesLength * 3); + bonesAndWeights._vertices.ensureCapacity(verticesLength * 3 * 3); + + for (i = 0, n = entrySize; i < n;) { + int boneCount = (int) vertices[i++]; + bonesAndWeights._bones.add(boneCount); + for (nn = i + boneCount * 4; i < nn; i += 4) { + bonesAndWeights._bones.add((int) vertices[i]); + bonesAndWeights._vertices.add(vertices[i + 1] * _scale); + bonesAndWeights._vertices.add(vertices[i + 2] * _scale); + bonesAndWeights._vertices.add(vertices[i + 3]); + } + } + + attachment->getVertices().clearAndAddAll(bonesAndWeights._vertices); + attachment->getBones().clearAndAddAll(bonesAndWeights._bones); +} + +void SkeletonJson::setError(Json *root, const String &value1, const String &value2) { + _error = String(value1).append(value2); + delete root; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Skin.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Skin.cpp new file mode 100644 index 0000000..57ec0e1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -0,0 +1,195 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include + +using namespace spine; + +Skin::AttachmentMap::AttachmentMap() { +} + +static void disposeAttachment(Attachment *attachment) { + if (!attachment) return; + attachment->dereference(); + if (attachment->getRefCount() == 0) delete attachment; +} + +void Skin::AttachmentMap::put(size_t slotIndex, const String &attachmentName, Attachment *attachment) { + if (slotIndex >= _buckets.size()) + _buckets.setSize(slotIndex + 1, Vector()); + Vector &bucket = _buckets[slotIndex]; + int existing = findInBucket(bucket, attachmentName); + attachment->reference(); + if (existing >= 0) { + disposeAttachment(bucket[existing]._attachment); + bucket[existing]._attachment = attachment; + } else { + bucket.add(Entry(slotIndex, attachmentName, attachment)); + } +} + +Attachment *Skin::AttachmentMap::get(size_t slotIndex, const String &attachmentName) { + if (slotIndex >= _buckets.size()) return NULL; + int existing = findInBucket(_buckets[slotIndex], attachmentName); + return existing >= 0 ? _buckets[slotIndex][existing]._attachment : NULL; +} + +void Skin::AttachmentMap::remove(size_t slotIndex, const String &attachmentName) { + if (slotIndex >= _buckets.size()) return; + int existing = findInBucket(_buckets[slotIndex], attachmentName); + if (existing >= 0) { + disposeAttachment(_buckets[slotIndex][existing]._attachment); + _buckets[slotIndex].removeAt(existing); + } +} + +int Skin::AttachmentMap::findInBucket(Vector &bucket, const String &attachmentName) { + for (size_t i = 0; i < bucket.size(); i++) + if (bucket[i]._name == attachmentName) return (int) i; + return -1; +} + +Skin::AttachmentMap::Entries Skin::AttachmentMap::getEntries() { + return Skin::AttachmentMap::Entries(_buckets); +} + +Skin::Skin(const String &name) : _name(name), _attachments() { + assert(_name.length() > 0); +} + +Skin::~Skin() { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry entry = entries.next(); + disposeAttachment(entry._attachment); + } +} + +void Skin::setAttachment(size_t slotIndex, const String &name, Attachment *attachment) { + assert(attachment); + _attachments.put(slotIndex, name, attachment); +} + +Attachment *Skin::getAttachment(size_t slotIndex, const String &name) { + return _attachments.get(slotIndex, name); +} + +void Skin::removeAttachment(size_t slotIndex, const String &name) { + _attachments.remove(slotIndex, name); +} + +void Skin::findNamesForSlot(size_t slotIndex, Vector &names) { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == slotIndex) { + names.add(entry._name); + } + } +} + +void Skin::findAttachmentsForSlot(size_t slotIndex, Vector &attachments) { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == slotIndex) attachments.add(entry._attachment); + } +} + +const String &Skin::getName() { + return _name; +} + +Skin::AttachmentMap::Entries Skin::getAttachments() { + return _attachments.getEntries(); +} + +void Skin::attachAll(Skeleton &skeleton, Skin &oldSkin) { + Vector &slots = skeleton.getSlots(); + Skin::AttachmentMap::Entries entries = oldSkin.getAttachments(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + int slotIndex = (int) entry._slotIndex; + Slot *slot = slots[slotIndex]; + + if (slot->getAttachment() == entry._attachment) { + Attachment *attachment = getAttachment(slotIndex, entry._name); + if (attachment) slot->setAttachment(attachment); + } + } +} + +void Skin::addSkin(Skin *other) { + for (size_t i = 0; i < other->getBones().size(); i++) + if (!_bones.contains(other->getBones()[i])) _bones.add(other->getBones()[i]); + + for (size_t i = 0; i < other->getConstraints().size(); i++) + if (!_constraints.contains(other->getConstraints()[i])) _constraints.add(other->getConstraints()[i]); + + AttachmentMap::Entries entries = other->getAttachments(); + while (entries.hasNext()) { + AttachmentMap::Entry &entry = entries.next(); + setAttachment(entry._slotIndex, entry._name, entry._attachment); + } +} + +void Skin::copySkin(Skin *other) { + for (size_t i = 0; i < other->getBones().size(); i++) + if (!_bones.contains(other->getBones()[i])) _bones.add(other->getBones()[i]); + + for (size_t i = 0; i < other->getConstraints().size(); i++) + if (!_constraints.contains(other->getConstraints()[i])) _constraints.add(other->getConstraints()[i]); + + AttachmentMap::Entries entries = other->getAttachments(); + while (entries.hasNext()) { + AttachmentMap::Entry &entry = entries.next(); + if (entry._attachment->getRTTI().isExactly(MeshAttachment::rtti)) + setAttachment(entry._slotIndex, entry._name, + static_cast(entry._attachment)->newLinkedMesh()); + else + setAttachment(entry._slotIndex, entry._name, entry._attachment->copy()); + } +} + +Vector &Skin::getConstraints() { + return _constraints; +} + +Vector &Skin::getBones() { + return _bones; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Slot.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Slot.cpp new file mode 100644 index 0000000..8501392 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -0,0 +1,129 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +Slot::Slot(SlotData &data, Bone &bone) : _data(data), + _bone(bone), + _skeleton(bone.getSkeleton()), + _color(1, 1, 1, 1), + _darkColor(0, 0, 0, 0), + _hasDarkColor(data.hasDarkColor()), + _attachment(NULL), + _attachmentState(0), + _sequenceIndex(0) { + setToSetupPose(); +} + +void Slot::setToSetupPose() { + _color.set(_data.getColor()); + if (_hasDarkColor) _darkColor.set(_data.getDarkColor()); + + const String &attachmentName = _data.getAttachmentName(); + if (attachmentName.length() > 0) { + _attachment = NULL; + setAttachment(_skeleton.getAttachment(_data.getIndex(), attachmentName)); + } else { + setAttachment(NULL); + } +} + +SlotData &Slot::getData() { + return _data; +} + +Bone &Slot::getBone() { + return _bone; +} + +Skeleton &Slot::getSkeleton() { + return _skeleton; +} + +Color &Slot::getColor() { + return _color; +} + +Color &Slot::getDarkColor() { + return _darkColor; +} + +bool Slot::hasDarkColor() { + return _hasDarkColor; +} + +Attachment *Slot::getAttachment() { + return _attachment; +} + +void Slot::setAttachment(Attachment *inValue) { + if (_attachment == inValue) { + return; + } + + if (!inValue || + !_attachment || + !inValue->getRTTI().instanceOf(VertexAttachment::rtti) || + !_attachment->getRTTI().instanceOf(VertexAttachment::rtti) || + static_cast(inValue)->getTimelineAttachment() != + static_cast(_attachment)->getTimelineAttachment()) { + _deform.clear(); + } + + _attachment = inValue; + _sequenceIndex = -1; +} + +int Slot::getAttachmentState() { + return _attachmentState; +} + +void Slot::setAttachmentState(int state) { + _attachmentState = state; +} + +Vector &Slot::getDeform() { + return _deform; +} + +int Slot::getSequenceIndex() { + return _sequenceIndex; +} + +void Slot::setSequenceIndex(int index) { + _sequenceIndex = index; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SlotData.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SlotData.cpp new file mode 100644 index 0000000..5def325 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SlotData.cpp @@ -0,0 +1,90 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +SlotData::SlotData(int index, const String &name, BoneData &boneData) : _index(index), + _name(name), + _boneData(boneData), + _color(1, 1, 1, 1), + _darkColor(0, 0, 0, 0), + _hasDarkColor(false), + _attachmentName(), + _blendMode(BlendMode_Normal) { + assert(_index >= 0); + assert(_name.length() > 0); +} + +int SlotData::getIndex() { + return _index; +} + +const String &SlotData::getName() { + return _name; +} + +BoneData &SlotData::getBoneData() { + return _boneData; +} + +Color &SlotData::getColor() { + return _color; +} + +Color &SlotData::getDarkColor() { + return _darkColor; +} + +bool SlotData::hasDarkColor() { + return _hasDarkColor; +} + +void SlotData::setHasDarkColor(bool inValue) { + _hasDarkColor = inValue; +} + +const String &SlotData::getAttachmentName() { + return _attachmentName; +} + +void SlotData::setAttachmentName(const String &inValue) { + _attachmentName = inValue; +} + +BlendMode SlotData::getBlendMode() { + return _blendMode; +} + +void SlotData::setBlendMode(BlendMode inValue) { + _blendMode = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SpineObject.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SpineObject.cpp new file mode 100644 index 0000000..1f0bb61 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/SpineObject.cpp @@ -0,0 +1,63 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +using namespace spine; + +void *SpineObject::operator new(size_t sz) { + return SpineExtension::getInstance()->_calloc(sz, __FILE__, __LINE__); +} + +void *SpineObject::operator new(size_t sz, const char *file, int line) { + return SpineExtension::getInstance()->_calloc(sz, file, line); +} + +void *SpineObject::operator new(size_t sz, void *ptr) { + SP_UNUSED(sz); + return ptr; +} + +void SpineObject::operator delete(void *p, const char *file, int line) { + SpineExtension::free(p, file, line); +} + +void SpineObject::operator delete(void *p, void *mem) { + SP_UNUSED(mem); + SpineExtension::free(p, __FILE__, __LINE__); +} + +void SpineObject::operator delete(void *p) { + SpineExtension::free(p, __FILE__, __LINE__); +} + +SpineObject::~SpineObject() { + SpineExtension::beforeFree(this); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp new file mode 100644 index 0000000..8275b2d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp @@ -0,0 +1,38 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +namespace spine { + TextureLoader::TextureLoader() { + } + + TextureLoader::~TextureLoader() { + } +}// namespace spine diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Timeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Timeline.cpp new file mode 100644 index 0000000..90a317e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Timeline.cpp @@ -0,0 +1,74 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +namespace spine { + RTTI_IMPL_NOPARENT(Timeline) + + Timeline::Timeline(size_t frameCount, size_t frameEntries) + : _propertyIds(), _frames(), _frameEntries(frameEntries) { + _frames.setSize(frameCount * frameEntries, 0); + } + + Timeline::~Timeline() { + } + + Vector &Timeline::getPropertyIds() { + return _propertyIds; + } + + void Timeline::setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount) { + _propertyIds.clear(); + _propertyIds.ensureCapacity(propertyIdsCount); + for (size_t i = 0; i < propertyIdsCount; i++) { + _propertyIds.add(propertyIds[i]); + } + } + + size_t Timeline::getFrameCount() { + return _frames.size() / _frameEntries; + } + + Vector &Timeline::getFrames() { + return _frames; + } + + size_t Timeline::getFrameEntries() { + return _frameEntries; + } + + float Timeline::getDuration() { + return _frames[_frames.size() - getFrameEntries()]; + } + +}// namespace spine diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp new file mode 100644 index 0000000..3d3ffc3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -0,0 +1,340 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(TransformConstraint, Updatable) + +TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : Updatable(), + _data(data), + _target(skeleton.findBone( + data.getTarget()->getName())), + _mixRotate( + data.getMixRotate()), + _mixX(data.getMixX()), + _mixY(data.getMixY()), + _mixScaleX( + data.getMixScaleX()), + _mixScaleY( + data.getMixScaleY()), + _mixShearY( + data.getMixShearY()), + _active(false) { + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); ++i) { + BoneData *boneData = _data.getBones()[i]; + _bones.add(skeleton.findBone(boneData->getName())); + } +} + +void TransformConstraint::update() { + if (_mixRotate == 0 && _mixX == 0 && _mixY == 0 && _mixScaleX == 0 && _mixScaleY == 0 && _mixShearY == 0) return; + + if (_data.isLocal()) { + if (_data.isRelative()) + applyRelativeLocal(); + else + applyAbsoluteLocal(); + } else { + if (_data.isRelative()) + applyRelativeWorld(); + else + applyAbsoluteWorld(); + } +} + +int TransformConstraint::getOrder() { + return (int) _data.getOrder(); +} + +TransformConstraintData &TransformConstraint::getData() { + return _data; +} + +Vector &TransformConstraint::getBones() { + return _bones; +} + +Bone *TransformConstraint::getTarget() { + return _target; +} + +void TransformConstraint::setTarget(Bone *inValue) { + _target = inValue; +} + +float TransformConstraint::getMixRotate() { + return _mixRotate; +} + +void TransformConstraint::setMixRotate(float inValue) { + _mixRotate = inValue; +} + +float TransformConstraint::getMixX() { + return _mixX; +} + +void TransformConstraint::setMixX(float inValue) { + _mixX = inValue; +} + +float TransformConstraint::getMixY() { + return _mixY; +} + +void TransformConstraint::setMixY(float inValue) { + _mixY = inValue; +} + +void TransformConstraint::setMixScaleX(float inValue) { + _mixScaleX = inValue; +} + +float TransformConstraint::getMixScaleX() { + return _mixScaleX; +} + +float TransformConstraint::getMixScaleY() { + return _mixScaleY; +} + +void TransformConstraint::setMixScaleY(float inValue) { + _mixScaleY = inValue; +} + +float TransformConstraint::getMixShearY() { + return _mixShearY; +} + +void TransformConstraint::setMixShearY(float inValue) { + _mixShearY = inValue; +} + +void TransformConstraint::applyAbsoluteWorld() { + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; + bool translate = mixX != 0 || mixY != 0; + Bone &target = *_target; + float ta = target._a, tb = target._b, tc = target._c, td = target._d; + float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; + float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; + + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + if (mixRotate != 0) { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + float r = MathUtil::atan2(tc, ta) - MathUtil::atan2(c, a) + offsetRotation; + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r *= mixRotate; + float cos = MathUtil::cos(r), sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + } + + if (translate) { + float tx, ty; + target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); + bone._worldX += (tx - bone._worldX) * mixX; + bone._worldY += (ty - bone._worldY) * mixY; + } + + if (mixScaleX > 0) { + float s = MathUtil::sqrt(bone._a * bone._a + bone._c * bone._c); + if (s != 0) s = (s + (MathUtil::sqrt(ta * ta + tc * tc) - s + _data._offsetScaleX) * mixScaleX) / s; + bone._a *= s; + bone._c *= s; + } + + if (mixScaleY > 0) { + float s = MathUtil::sqrt(bone._b * bone._b + bone._d * bone._d); + if (s != 0) s = (s + (MathUtil::sqrt(tb * tb + td * td) - s + _data._offsetScaleY) * mixScaleY) / s; + bone._b *= s; + bone._d *= s; + } + + if (mixShearY > 0) { + float b = bone._b, d = bone._d; + float by = MathUtil::atan2(d, b); + float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta) - (by - MathUtil::atan2(bone._c, bone._a)); + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r = by + (r + offsetShearY) * mixShearY; + float s = MathUtil::sqrt(b * b + d * d); + bone._b = MathUtil::cos(r) * s; + bone._d = MathUtil::sin(r) * s; + } + + bone.updateAppliedTransform(); + } +} + +void TransformConstraint::applyRelativeWorld() { + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; + bool translate = mixX != 0 || mixY != 0; + Bone &target = *_target; + float ta = target._a, tb = target._b, tc = target._c, td = target._d; + float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; + float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + if (mixRotate != 0) { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + float r = MathUtil::atan2(tc, ta) + offsetRotation; + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r *= mixRotate; + float cos = MathUtil::cos(r), sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + } + + if (translate) { + float tx, ty; + target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); + bone._worldX += tx * mixX; + bone._worldY += ty * mixY; + } + + if (mixScaleX != 0) { + float s = (MathUtil::sqrt(ta * ta + tc * tc) - 1 + _data._offsetScaleX) * mixScaleX + 1; + bone._a *= s; + bone._c *= s; + } + if (mixScaleY != 0) { + float s = (MathUtil::sqrt(tb * tb + td * td) - 1 + _data._offsetScaleY) * mixScaleY + 1; + bone._b *= s; + bone._d *= s; + } + + if (mixShearY > 0) { + float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta); + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + float b = bone._b, d = bone._d; + r = MathUtil::atan2(d, b) + (r - MathUtil::Pi / 2 + offsetShearY) * mixShearY; + float s = MathUtil::sqrt(b * b + d * d); + bone._b = MathUtil::cos(r) * s; + bone._d = MathUtil::sin(r) * s; + } + + bone.updateAppliedTransform(); + } +} + +void TransformConstraint::applyAbsoluteLocal() { + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; + Bone &target = *_target; + + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + float rotation = bone._arotation; + if (mixRotate != 0) { + float r = target._arotation - rotation + _data._offsetRotation; + r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360; + rotation += r * mixRotate; + } + + float x = bone._ax, y = bone._ay; + x += (target._ax - x + _data._offsetX) * mixX; + y += (target._ay - y + _data._offsetY) * mixY; + + float scaleX = bone._ascaleX, scaleY = bone._ascaleY; + if (mixScaleX != 0 && scaleX != 0) + scaleX = (scaleX + (target._ascaleX - scaleX + _data._offsetScaleX) * mixScaleX) / scaleX; + if (mixScaleY != 0 && scaleY != 0) + scaleY = (scaleY + (target._ascaleY - scaleY + _data._offsetScaleY) * mixScaleY) / scaleY; + + float shearY = bone._ashearY; + if (mixShearY != 0) { + float r = target._ashearY - shearY + _data._offsetShearY; + r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360; + bone._shearY += r * mixShearY; + } + + bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); + } +} + +void TransformConstraint::applyRelativeLocal() { + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; + Bone &target = *_target; + + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + float rotation = bone._arotation + (target._arotation + _data._offsetRotation) * mixRotate; + float x = bone._ax + (target._ax + _data._offsetX) * mixX; + float y = bone._ay + (target._ay + _data._offsetY) * mixY; + float scaleX = bone._ascaleX * (((target._ascaleX - 1 + _data._offsetScaleX) * mixScaleX) + 1); + float scaleY = bone._ascaleY * (((target._ascaleY - 1 + _data._offsetScaleY) * mixScaleY) + 1); + float shearY = bone._ashearY + (target._ashearY + _data._offsetShearY) * mixShearY; + + bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); + } +} + +bool TransformConstraint::isActive() { + return _active; +} + +void TransformConstraint::setActive(bool inValue) { + _active = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp new file mode 100644 index 0000000..5c02609 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -0,0 +1,180 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +#include + +using namespace spine; + +RTTI_IMPL(TransformConstraintData, ConstraintData) + +TransformConstraintData::TransformConstraintData(const String &name) : ConstraintData(name), + _target(NULL), + _mixRotate(0), + _mixX(0), + _mixY(0), + _mixScaleX(0), + _mixScaleY(0), + _mixShearY(0), + _offsetRotation(0), + _offsetX(0), + _offsetY(0), + _offsetScaleX(0), + _offsetScaleY(0), + _offsetShearY(0), + _relative(false), + _local(false) { +} + +Vector &TransformConstraintData::getBones() { + return _bones; +} + +BoneData *TransformConstraintData::getTarget() { + return _target; +} + +float TransformConstraintData::getMixRotate() { + return _mixRotate; +} + +float TransformConstraintData::getMixX() { + return _mixX; +} + +float TransformConstraintData::getMixY() { + return _mixY; +} + +float TransformConstraintData::getMixScaleX() { + return _mixScaleX; +} + +float TransformConstraintData::getMixScaleY() { + return _mixScaleY; +} + +float TransformConstraintData::getMixShearY() { + return _mixShearY; +} + +float TransformConstraintData::getOffsetRotation() { + return _offsetRotation; +} + +float TransformConstraintData::getOffsetX() { + return _offsetX; +} + +float TransformConstraintData::getOffsetY() { + return _offsetY; +} + +float TransformConstraintData::getOffsetScaleX() { + return _offsetScaleX; +} + +float TransformConstraintData::getOffsetScaleY() { + return _offsetScaleY; +} + +float TransformConstraintData::getOffsetShearY() { + return _offsetShearY; +} + +bool TransformConstraintData::isRelative() { + return _relative; +} + +bool TransformConstraintData::isLocal() { + return _local; +} + +void TransformConstraintData::setTarget(BoneData *target) { + _target = target; +} + +void TransformConstraintData::setMixRotate(float mixRotate) { + _mixRotate = mixRotate; +} + +void TransformConstraintData::setMixX(float mixX) { + _mixX = mixX; +} + +void TransformConstraintData::setMixY(float mixY) { + _mixY = mixY; +} + +void TransformConstraintData::setMixScaleX(float mixScaleX) { + _mixScaleX = mixScaleX; +} + +void TransformConstraintData::setMixScaleY(float mixScaleY) { + _mixScaleY = mixScaleY; +} + +void TransformConstraintData::setMixShearY(float mixShearY) { + _mixShearY = mixShearY; +} + +void TransformConstraintData::setOffsetRotation(float offsetRotation) { + _offsetRotation = offsetRotation; +} + +void TransformConstraintData::setOffsetX(float offsetX) { + _offsetX = offsetX; +} + +void TransformConstraintData::setOffsetY(float offsetY) { + _offsetY = offsetY; +} + +void TransformConstraintData::setOffsetScaleX(float offsetScaleX) { + _offsetScaleX = offsetScaleX; +} + +void TransformConstraintData::setOffsetScaleY(float offsetScaleY) { + _offsetScaleY = offsetScaleY; +} + +void TransformConstraintData::setOffsetShearY(float offsetShearY) { + _offsetShearY = offsetShearY; +} + +void TransformConstraintData::setRelative(bool isRelative) { + _relative = isRelative; +} + +void TransformConstraintData::setLocal(bool isLocal) { + _local = isLocal; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp new file mode 100644 index 0000000..69c41d9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -0,0 +1,157 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(TransformConstraintTimeline, CurveTimeline) + +TransformConstraintTimeline::TransformConstraintTimeline(size_t frameCount, size_t bezierCount, + int transformConstraintIndex) : CurveTimeline(frameCount, + TransformConstraintTimeline::ENTRIES, + bezierCount), + _transformConstraintIndex( + transformConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_TransformConstraint << 32) | transformConstraintIndex}; + setPropertyIds(ids, 1); +} + +void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + TransformConstraint *constraintP = skeleton._transformConstraints[_transformConstraintIndex]; + TransformConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + TransformConstraintData &data = constraint._data; + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._mixRotate = data._mixRotate; + constraint._mixX = data._mixX; + constraint._mixY = data._mixY; + constraint._mixScaleX = data._mixScaleX; + constraint._mixScaleY = data._mixScaleY; + constraint._mixShearY = data._mixShearY; + return; + case MixBlend_First: + constraint._mixRotate += (data._mixRotate - constraint._mixRotate) * alpha; + constraint._mixX += (data._mixX - constraint._mixX) * alpha; + constraint._mixY += (data._mixY - constraint._mixY) * alpha; + constraint._mixScaleX += (data._mixScaleX - constraint._mixScaleX) * alpha; + constraint._mixScaleY += (data._mixScaleY - constraint._mixScaleY) * alpha; + constraint._mixShearY += (data._mixShearY - constraint._mixShearY) * alpha; + return; + default: + return; + } + } + + float rotate, x, y, scaleX, scaleY, shearY; + int i = Animation::search(_frames, time, TransformConstraintTimeline::ENTRIES); + int curveType = (int) _curves[i / TransformConstraintTimeline::ENTRIES]; + switch (curveType) { + case TransformConstraintTimeline::LINEAR: { + float before = _frames[i]; + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + scaleX = _frames[i + SCALEX]; + scaleY = _frames[i + SCALEY]; + shearY = _frames[i + SHEARY]; + float t = (time - before) / (_frames[i + ENTRIES] - before); + rotate += (_frames[i + ENTRIES + ROTATE] - rotate) * t; + x += (_frames[i + ENTRIES + X] - x) * t; + y += (_frames[i + ENTRIES + Y] - y) * t; + scaleX += (_frames[i + ENTRIES + SCALEX] - scaleX) * t; + scaleY += (_frames[i + ENTRIES + SCALEY] - scaleY) * t; + shearY += (_frames[i + ENTRIES + SHEARY] - shearY) * t; + break; + } + case TransformConstraintTimeline::STEPPED: { + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + scaleX = _frames[i + SCALEX]; + scaleY = _frames[i + SCALEY]; + shearY = _frames[i + SHEARY]; + break; + } + default: { + rotate = getBezierValue(time, i, ROTATE, curveType - BEZIER); + x = getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER); + y = getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER); + scaleX = getBezierValue(time, i, SCALEX, curveType + BEZIER_SIZE * 3 - BEZIER); + scaleY = getBezierValue(time, i, SCALEY, curveType + BEZIER_SIZE * 4 - BEZIER); + shearY = getBezierValue(time, i, SHEARY, curveType + BEZIER_SIZE * 5 - BEZIER); + } + } + + if (blend == MixBlend_Setup) { + constraint._mixRotate = data._mixRotate + (rotate - data._mixRotate) * alpha; + constraint._mixX = data._mixX + (x - data._mixX) * alpha; + constraint._mixY = data._mixY + (y - data._mixY) * alpha; + constraint._mixScaleX = data._mixScaleX + (scaleX - data._mixScaleX) * alpha; + constraint._mixScaleY = data._mixScaleY + (scaleY - data._mixScaleY) * alpha; + constraint._mixShearY = data._mixShearY + (shearY - data._mixShearY) * alpha; + } else { + constraint._mixRotate += (rotate - constraint._mixRotate) * alpha; + constraint._mixX += (x - constraint._mixX) * alpha; + constraint._mixY += (y - constraint._mixY) * alpha; + constraint._mixScaleX += (scaleX - constraint._mixScaleX) * alpha; + constraint._mixScaleY += (scaleY - constraint._mixScaleY) * alpha; + constraint._mixShearY += (shearY - constraint._mixShearY) * alpha; + } +} + +void TransformConstraintTimeline::setFrame(size_t frame, float time, float mixRotate, float mixX, float mixY, + float mixScaleX, float mixScaleY, float mixShearY) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + ROTATE] = mixRotate; + _frames[frame + X] = mixX; + _frames[frame + Y] = mixY; + _frames[frame + SCALEX] = mixScaleX; + _frames[frame + SCALEY] = mixScaleY; + _frames[frame + SHEARY] = mixShearY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp new file mode 100644 index 0000000..66df9d7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -0,0 +1,214 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(TranslateTimeline, CurveTimeline2) + +TranslateTimeline::TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_X << 32) | boneIndex, + ((PropertyId) Property_Y << 32) | boneIndex}; + setPropertyIds(ids, 2); +} + +TranslateTimeline::~TranslateTimeline() { +} + +void TranslateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_x = bone->_data._x; + bone->_y = bone->_data._y; + return; + case MixBlend_First: + bone->_x += (bone->_data._x - bone->_x) * alpha; + bone->_y += (bone->_data._y - bone->_y) * alpha; + default: { + } + } + return; + } + + float x = 0, y = 0; + int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES); + int curveType = (int) _curves[i / CurveTimeline2::ENTRIES]; + switch (curveType) { + case CurveTimeline::LINEAR: { + float before = _frames[i]; + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before); + x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t; + y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t; + break; + } + case CurveTimeline::STEPPED: { + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + break; + } + default: { + x = getBezierValue(time, i, CurveTimeline2::VALUE1, curveType - CurveTimeline::BEZIER); + y = getBezierValue(time, i, CurveTimeline2::VALUE2, + curveType + CurveTimeline::BEZIER_SIZE - CurveTimeline::BEZIER); + } + } + + switch (blend) { + case MixBlend_Setup: + bone->_x = bone->_data._x + x * alpha; + bone->_y = bone->_data._y + y * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_x += (bone->_data._x + x - bone->_x) * alpha; + bone->_y += (bone->_data._y + y - bone->_y) * alpha; + break; + case MixBlend_Add: + bone->_x += x * alpha; + bone->_y += y * alpha; + } +} + +RTTI_IMPL(TranslateXTimeline, CurveTimeline1) + +TranslateXTimeline::TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1( + frameCount, bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_X << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +TranslateXTimeline::~TranslateXTimeline() { +} + +void TranslateXTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_x = bone->_data._x; + return; + case MixBlend_First: + bone->_x += (bone->_data._x - bone->_x) * alpha; + default: { + } + } + return; + } + + float x = getCurveValue(time); + switch (blend) { + case MixBlend_Setup: + bone->_x = bone->_data._x + x * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_x += (bone->_data._x + x - bone->_x) * alpha; + break; + case MixBlend_Add: + bone->_x += x * alpha; + } +} + +RTTI_IMPL(TranslateYTimeline, CurveTimeline1) + +TranslateYTimeline::TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1( + frameCount, bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_Y << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +TranslateYTimeline::~TranslateYTimeline() { +} + +void TranslateYTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_y = bone->_data._y; + return; + case MixBlend_First: + bone->_y += (bone->_data._y - bone->_y) * alpha; + default: { + } + } + return; + } + + float y = getCurveValue(time); + switch (blend) { + case MixBlend_Setup: + bone->_y = bone->_data._y + y * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_y += (bone->_data._y + y - bone->_y) * alpha; + break; + case MixBlend_Add: + bone->_y += y * alpha; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Triangulator.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Triangulator.cpp new file mode 100644 index 0000000..fdbdb04 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Triangulator.cpp @@ -0,0 +1,285 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +Triangulator::~Triangulator() { + ContainerUtil::cleanUpVectorOfPointers(_convexPolygons); + ContainerUtil::cleanUpVectorOfPointers(_convexPolygonsIndices); +} + +Vector &Triangulator::triangulate(Vector &vertices) { + size_t vertexCount = vertices.size() >> 1; + + Vector &indices = _indices; + indices.clear(); + indices.ensureCapacity(vertexCount); + indices.setSize(vertexCount, 0); + for (int i = 0; i < (int) vertexCount; ++i) { + indices[i] = i; + } + + Vector &isConcaveArray = _isConcaveArray; + isConcaveArray.ensureCapacity(vertexCount); + isConcaveArray.setSize(vertexCount, 0); + for (int i = 0, n = (int) vertexCount; i < n; ++i) { + isConcaveArray[i] = isConcave(i, (int) vertexCount, vertices, indices); + } + + Vector &triangles = _triangles; + triangles.clear(); + triangles.ensureCapacity(MathUtil::max((int) 0, (int) vertexCount - 2) << 2); + + while (vertexCount > 3) { + // Find ear tip. + size_t previous = vertexCount - 1, i = 0, next = 1; + + // outer: + while (true) { + if (!isConcaveArray[i]) { + int p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + float p1x = vertices[p1], p1y = vertices[p1 + 1]; + float p2x = vertices[p2], p2y = vertices[p2 + 1]; + float p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (size_t ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcaveArray[ii]) continue; + + int v = indices[ii] << 1; + float &vx = vertices[v], vy = vertices[v + 1]; + if (positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (positiveArea(p2x, p2y, p3x, p3y, vx, vy)) { + goto break_outer;// break outer; + } + } + } + } + break; + } + break_outer: + + if (next == 0) { + do { + if (!isConcaveArray[i]) break; + i--; + } while (i > 0); + break; + } + + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + + // Cut ear tip. + triangles.add(indices[(vertexCount + i - 1) % vertexCount]); + triangles.add(indices[i]); + triangles.add(indices[(i + 1) % vertexCount]); + indices.removeAt(i); + isConcaveArray.removeAt(i); + vertexCount--; + + int previousIndex = (int) ((vertexCount + i - 1) % vertexCount); + int nextIndex = (int) (i == vertexCount ? 0 : i); + isConcaveArray[previousIndex] = isConcave(previousIndex, (int) vertexCount, vertices, indices); + isConcaveArray[nextIndex] = isConcave(nextIndex, (int) vertexCount, vertices, indices); + } + + if (vertexCount == 3) { + triangles.add(indices[2]); + triangles.add(indices[0]); + triangles.add(indices[1]); + } + + return triangles; +} + +Vector *> &Triangulator::decompose(Vector &vertices, Vector &triangles) { + Vector *> &convexPolygons = _convexPolygons; + for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) + _polygonPool.free(convexPolygons[i]); + convexPolygons.clear(); + + Vector *> &convexPolygonsIndices = _convexPolygonsIndices; + for (size_t i = 0, n = convexPolygonsIndices.size(); i < n; ++i) + _polygonIndicesPool.free(convexPolygonsIndices[i]); + convexPolygonsIndices.clear(); + + Vector *polygonIndices = _polygonIndicesPool.obtain(); + polygonIndices->clear(); + + Vector *polygon = _polygonPool.obtain(); + polygon->clear(); + + // Merge subsequent triangles if they form a triangle fan. + int fanBaseIndex = -1, lastwinding = 0; + for (size_t i = 0, n = triangles.size(); i < n; i += 3) { + int t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + float x1 = vertices[t1], y1 = vertices[t1 + 1]; + float x2 = vertices[t2], y2 = vertices[t2 + 1]; + float x3 = vertices[t3], y3 = vertices[t3 + 1]; + + // If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan). + bool merged = false; + if (fanBaseIndex == t1) { + size_t o = polygon->size() - 4; + Vector &p = *polygon; + int winding1 = winding(p[o], p[o + 1], p[o + 2], p[o + 3], x3, y3); + int winding2 = winding(x3, y3, p[0], p[1], p[2], p[3]); + if (winding1 == lastwinding && winding2 == lastwinding) { + polygon->add(x3); + polygon->add(y3); + polygonIndices->add(t3); + merged = true; + } + } + + // Otherwise make this triangle the new base. + if (!merged) { + if (polygon->size() > 0) { + convexPolygons.add(polygon); + convexPolygonsIndices.add(polygonIndices); + } else { + _polygonPool.free(polygon); + _polygonIndicesPool.free(polygonIndices); + } + + polygon = _polygonPool.obtain(); + polygon->clear(); + polygon->add(x1); + polygon->add(y1); + polygon->add(x2); + polygon->add(y2); + polygon->add(x3); + polygon->add(y3); + polygonIndices = _polygonIndicesPool.obtain(); + polygonIndices->clear(); + polygonIndices->add(t1); + polygonIndices->add(t2); + polygonIndices->add(t3); + lastwinding = winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + + if (polygon->size() > 0) { + convexPolygons.add(polygon); + convexPolygonsIndices.add(polygonIndices); + } + + // Go through the list of polygons and try to merge the remaining triangles with the found triangle fans. + for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) { + polygonIndices = convexPolygonsIndices[i]; + + if (polygonIndices->size() == 0) continue; + int firstIndex = (*polygonIndices)[0]; + int lastIndex = (*polygonIndices)[polygonIndices->size() - 1]; + + polygon = convexPolygons[i]; + size_t o = polygon->size() - 4; + Vector &p = *polygon; + float prevPrevX = p[o], prevPrevY = p[o + 1]; + float prevX = p[o + 2], prevY = p[o + 3]; + float firstX = p[0], firstY = p[1]; + float secondX = p[2], secondY = p[3]; + int winding0 = winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + + for (size_t ii = 0; ii < n; ++ii) { + if (ii == i) continue; + + Vector *otherIndicesP = convexPolygonsIndices[ii]; + Vector &otherIndices = *otherIndicesP; + + if (otherIndices.size() != 3) continue; + + int otherFirstIndex = otherIndices[0]; + int otherSecondIndex = otherIndices[1]; + int otherLastIndex = otherIndices[2]; + + Vector *otherPolyP = convexPolygons[ii]; + Vector &otherPoly = *otherPolyP; + + float x3 = otherPoly[otherPoly.size() - 2], y3 = otherPoly[otherPoly.size() - 1]; + + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue; + + int winding1 = winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + int winding2 = winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding0 && winding2 == winding0) { + otherPoly.clear(); + otherIndices.clear(); + polygon->add(x3); + polygon->add(y3); + polygonIndices->add(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + + // Remove empty polygons that resulted from the merge step above. + for (int i = (int) convexPolygons.size() - 1; i >= 0; --i) { + polygon = convexPolygons[i]; + if (polygon->size() == 0) { + convexPolygons.removeAt(i); + _polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.removeAt(i); + _polygonIndicesPool.free(polygonIndices); + } + } + + return convexPolygons; +} + +bool Triangulator::isConcave(int index, int vertexCount, Vector &vertices, Vector &indices) { + int previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + int current = indices[index] << 1; + int next = indices[(index + 1) % vertexCount] << 1; + + return !positiveArea(vertices[previous], vertices[previous + 1], + vertices[current], vertices[current + 1], + vertices[next], vertices[next + 1]); +} + +bool Triangulator::positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; +} + +int Triangulator::winding(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) { + float px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Updatable.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Updatable.cpp new file mode 100644 index 0000000..9339118 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/Updatable.cpp @@ -0,0 +1,40 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(Updatable) + +Updatable::Updatable() { +} + +Updatable::~Updatable() { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp new file mode 100644 index 0000000..c888608 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.1/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -0,0 +1,167 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL(VertexAttachment, Attachment) + +VertexAttachment::VertexAttachment(const String &name) : Attachment(name), _worldVerticesLength(0), + _timelineAttachment(this), _id(getNextID()) { +} + +VertexAttachment::~VertexAttachment() { +} + +void VertexAttachment::computeWorldVertices(Slot &slot, Vector &worldVertices) { + computeWorldVertices(slot, 0, _worldVerticesLength, worldVertices, 0); +} + +void VertexAttachment::computeWorldVertices(Slot &slot, float *worldVertices) { + computeWorldVertices(slot, 0, _worldVerticesLength, worldVertices, 0); +} + +void VertexAttachment::computeWorldVertices(Slot &slot, size_t start, size_t count, Vector &worldVertices, + size_t offset, size_t stride) { + computeWorldVertices(slot, start, count, worldVertices.buffer(), offset, stride); +} + +void VertexAttachment::computeWorldVertices(Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride) { + count = offset + (count >> 1) * stride; + Skeleton &skeleton = slot._bone._skeleton; + Vector *deformArray = &slot.getDeform(); + Vector *vertices = &_vertices; + Vector &bones = _bones; + if (bones.size() == 0) { + if (deformArray->size() > 0) vertices = deformArray; + + Bone &bone = slot._bone; + float x = bone._worldX; + float y = bone._worldY; + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + for (size_t vv = start, w = offset; w < count; vv += 2, w += stride) { + float vx = (*vertices)[vv]; + float vy = (*vertices)[vv + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + + int v = 0, skip = 0; + for (size_t i = 0; i < start; i += 2) { + int n = (int) bones[v]; + v += n + 1; + skip += n; + } + + Vector &skeletonBones = skeleton.getBones(); + if (deformArray->size() == 0) { + for (size_t w = offset, b = skip * 3; w < count; w += stride) { + float wx = 0, wy = 0; + int n = (int) bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + Bone *boneP = skeletonBones[bones[v]]; + Bone &bone = *boneP; + float vx = (*vertices)[b]; + float vy = (*vertices)[b + 1]; + float weight = (*vertices)[b + 2]; + wx += (vx * bone._a + vy * bone._b + bone._worldX) * weight; + wy += (vx * bone._c + vy * bone._d + bone._worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } else { + for (size_t w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + float wx = 0, wy = 0; + int n = (int) bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + Bone *boneP = skeletonBones[bones[v]]; + Bone &bone = *boneP; + float vx = (*vertices)[b] + (*deformArray)[f]; + float vy = (*vertices)[b + 1] + (*deformArray)[f + 1]; + float weight = (*vertices)[b + 2]; + wx += (vx * bone._a + vy * bone._b + bone._worldX) * weight; + wy += (vx * bone._c + vy * bone._d + bone._worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } +} + +int VertexAttachment::getId() { + return _id; +} + +Vector &VertexAttachment::getBones() { + return _bones; +} + +Vector &VertexAttachment::getVertices() { + return _vertices; +} + +size_t VertexAttachment::getWorldVerticesLength() { + return _worldVerticesLength; +} + +void VertexAttachment::setWorldVerticesLength(size_t inValue) { + _worldVerticesLength = inValue; +} + +Attachment *VertexAttachment::getTimelineAttachment() { + return _timelineAttachment; +} + +void VertexAttachment::setTimelineAttachment(Attachment *attachment) { + _timelineAttachment = attachment; +} + +int VertexAttachment::getNextID() { + static int nextID = 0; + return nextID++; +} + +void VertexAttachment::copyTo(VertexAttachment *other) { + other->_bones.clearAndAddAll(this->_bones); + other->_vertices.clearAndAddAll(this->_vertices); + other->_worldVerticesLength = this->_worldVerticesLength; + other->_timelineAttachment = this->_timelineAttachment; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2 b/DateToSpine/third_party/spine-runtimes/4.2 deleted file mode 160000 index e7dc143..0000000 --- a/DateToSpine/third_party/spine-runtimes/4.2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e7dc1435fa4a0083ab431f1b28e083c14a1f5c68 diff --git a/DateToSpine/third_party/spine-runtimes/4.2/CHANGELOG.md b/DateToSpine/third_party/spine-runtimes/4.2/CHANGELOG.md new file mode 100644 index 0000000..720f3fe --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/CHANGELOG.md @@ -0,0 +1,1810 @@ +# 4.2 + +## C + +- **Additions** + - Added physics support + - Added `spPhysicsConstraintTimeline` and `spPhysicsConstraintResetTimeline` + - Added `spPhysics` to be passed to `spSkeleton_updateWorldTransform()` + - Added `spSkeletonData_findPhysicsConstraint()` to query a physics constraint by name + - Added `spSkeleton_findPhysicsConstraint()` to query a physics constraint by name + - Added `spSkeleton_physicsTranslate()` to translate all physics constraints by some distances in the skeleton coordinate system + - Added `spSkeleton_physicsRotate()` to rotate all physics constraints by some distances in the skeleton coordinate system + - Added `spSkeleton::time` to keep track of time for physics simulations + - See also breaking changes for `spSkeleton_updateWorldTransform()` and the requirement to call `spSkeleton_update()` to advance + pyhsics each frame. + - Added `spInheritTimeline` + - Added [`spTrackEntry::alphaAttachmentThreshold`](http://esotericsoftware.com/spine-api-reference#TrackEntry-alphaAttachmentThreshold) + - Removed `const` qualifiers where appropriate + - Added `spTrackEntry_setMixDuration()` to set the mix duration in conjunction with a delay + - Added `spTrackEntry_wasApplied()` to check if the entry has been applied + - Added `spBone_worldToParent()` to transform coordinates from world space to the parent space of a bone + - Added `spBone_localToParent()` to transform coordinates from a bone's local space to its parent space + - Added non essential fields `icon` and `visible` to `spBoneData` + - Added non essential fields `path` and `visible` to `spSlotData` +- **Breaking changes** + - Renamed `spTrackEntry::attachmentThreshold` to `spTrackEntry::mixAttachmentThreshold` + - Renamed `spTrackEntry::drawOrderThreshold` to `spTrackEntry::mixDrawOrdertThreshold` + - Renamed `spTransformMode` to `spInherit` and all `SP_TRANSFORMMODE_*` enums to `SP_INHERIT_*` + - Changed `spMeshAttachment::edges` from `int *` to `unsigned short *` + - You must call `spSkeleton_update(delta)` before calling `spSkeleton_updateWorldTransform()` if the frame time has advanced. This is needed to update physics accordingly + - `spSkeleton_updateWorldTransform()` takes an additional `spPhysics` parameter. See the `spPhysics` documentation for information on what the different enum values do + +### SFML + +- Added physics examples +- `SkeletonDrawable::update()` now takes an additional `spPhysics physics` parameter that specifies how physics should be updated + +### SDL + +- `spSkeletonDrawable_update()` now takes an additional `spPhysics physics` parameter that specifies how physics should be updated + +## C++ + +- Added physics support + - Added `PhysicsConstraintXXXTimeline` and `PhysicsConstraintResetTimeline` + - Added `Physics` to be passed to `Skeleton::updateWorldTransform()` + - Added `SkeletonData::findPhysicsConstraint()` and `SkeletonData::getPhysicsConstraints()` to query physics constraints + - Added `Skeleton::findPhysicsConstraint()` and `Skeleton::getPhysicsConstraints()` to query physics constraints + - Added `Skeleton::physicsTranslate()` to translate all physics constraints by some distances in the skeleton coordinate system + - Added `Skeleton::physicsRotate()` to rotate all physics constraints by some distances in the skeleton coordinate system + - Added `Skeleton::time` to keep track of time for physics simulations + - See also breaking changes for `Skeleton::updateWorldTransform()` and the requirement to call `Skeleton::update()` to advance + pyhsics each frame. +- Added `InheritTimeline` +- Added [`TrackEntry::_alphaAttachmentThreshold`](http://esotericsoftware.com/spine-api-reference#TrackEntry-alphaAttachmentThreshold) +- Added `TrackEntry::setMixDuration()` to set the mix duration in conjunction with a delay +- Added `TrackEntry::wasApplied()` to check if the entry has been applied +- Added `Bone::worldToParent()` to transform coordinates from world space to the parent space of a bone +- Added `Bone::localToParent()` to transform coordinates from a bone's local space to its parent space +- Added non essential fields `icon` and `visible` to `BoneData` +- Added non essential fields `path` and `visible` to `SlotData` +- Added `setToSetupPose()` to all contraint classes +- **Breaking changes** + - Renamed `TrackEntry::attachmentThreshold` to `TrackEntry::mixAttachmentThreshold` + - Renamed `TrackEntry::drawOrderThreshold` to `TrackEntry::mixDrawOrdertThreshold` + - Renamed `TransformMode` to `Inherit` and all `TransformMode_*` enums to `Inherit_*` + - You must call `Skeleton::update(delta)` before calling `Skeleton::updateWorldTransform()` if the frame time has advanced. This is needed to update physics accordingly + - `Skeleton::updateWorldTransform()` takes an additional `Physics` parameter. See the `Physics` documentation for information on what the different enum values do + - All `Updatable` sub-classes like `Bone` and constraints now take an additional `Physics` parameter for their `update()` methods + +### Cocos2d-x + +- Added physics example +- Improved build system and build documentation + +### SFML + +- `SkeletonDrawable::update()` now takes an additional `Physics physics` parameter that specifies how physics should be updated + +### SDL + +- `SkeletonDrawable::update()` now takes an additional `Physics physics` parameter that specifies how physics should be updated + +### UE4 + +- **Breaking**: Renamed runtime folder from `spine-ue4` to `spine-ue` +- **Breaking**: Renamed plugin `SpinePlugin`. You must update your project's `Build.cs` file accordingly +- **Breaking**: Starting with Unreal Engine 5.3 imported `.skel`/`.json` and `.atlas` files in the same folder must NOT have a common prefix. E.g. `skeleton.json` and `skeleton.atlas` will not work. Make sure to rename at least one of the two files so there is no prefix collision, e.g. `skeleton-data.json` and `skeleton.atlas`. +- Added compatibility with UE 5.3 +- Added more example maps +- Added blueprint-callable methods `PhysicsTranslate()`, `PhysicsRotate()` and `ResetPhysicsConstraints()` (which will reset all physics constraints in the skeleton) to `SpineSkeletonComponent` and `SpineWidget`. + +### Godot + +- **Breaking**: Renamed `TrackEntry.set_attachment_threshold` and `TrackEntry.get_attachment_threshold` to `TrackEntry.set_mix_attachment_threshold` and `TrackEntry.get_mix_attachment_threshold` +- **Breaking**: Renamed `TrackEntry.set_draw_order_threshold` and `TrackEntry.get_draw_order_threshold` to `TrackEntry.set_mix_draw_order_threshold` and `TrackEntry.get_mix_draw_order_threshold` +- **BReaking**: `SpineSkeleton.update_world_transform` takes an additional `physics` parameter that specifies how physics should be updated +- Added compatibility for Godot 4.1, 4.2 and C#, see builds at [https://esotericsoftware.com/spine-godot](https://esotericsoftware.com/spine-godot) +- Added physics examples +- Added `SpineBone.world_to_parent` to transform coordinates from world space to the parent space of a bone +- Added `SpineBone.local_to_parent` to transform coordinates from a bone's local space to its parent space +- Physics support + - Added `SpineBone.get_inherit`/`SpineBone.set_inherit` + - Added `SpinePhysicsConstraint` and `SpinePhysicsConstraintData` + - Added `SpineSkeleton.update()` to advance the physics time + - ADded `SpineSkeleton.get_time`/`SpineSkeleton.set_time` to access the physics time + - Added `SpineSkeleton.physics_translate()` to translate all physics constraints by some distances in the skeleton coordinate system + - Added `SpineSkeleton.physics_rotate()` to rotate all physics constraints by some distances in the skeleton coordinate system + - Added `SpineSkeleotnDataResource.set_reference_scale`/`SpineSkeletonDataResource.get_reference_scale` to access the reference scale of the loaded skeleton data +- Added [`TrackEntry.set_alpha_attachment_threshold`](http://esotericsoftware.com/spine-api-reference#TrackEntry-alphaAttachmentThreshold) +- Added `TrackEntry.set_mix_duration_and_delay()` to set the mix duration in conjunction with a delay +- Added `TrackEntry::was_applied()` to check if the entry has been applied + +## C# + +- **Additions** + + - Added [`TrackEntry.AlphaAttachmentThreshold`](http://esotericsoftware.com/spine-api-reference#TrackEntry-alphaAttachmentThreshold). + +- **Breaking changes** + - Renamed `TrackEntry` `AttachmentThreshold` to `MixAttachmentThreshold`, renamed `DrawOrderThreshold` to `MixDrawOrderThreshold`. + - Changed signature of `Skeleton.UpdateWorldTransform()` to `UpdateWorldTransform(Skeleton.Physics physics)`. The default replacement for `skeleton.UpdateWorldTransform()` calls is `skeleton.UpdateWorldTransform(Skeleton.Physics.Update)`. If you are certain that a subsequent call to `skeleton.UpdateWorldTransform(Skeleton.Physics.Update)` follows in the same frame, you can pass `Skeleton.Physics.Pose` as argument instead of `Skeleton.Physics.Update`. + +### Unity + +- **Officially supported Unity versions are 2017.1-6000.3**. + +- **Additions** + + - `OnPostProcessVertices` callback parameter `MeshGeneratorBuffers` now provides access to `uv2Buffer` and `uv3Buffer` properties of `MeshGenerator`, automatically allocating buffers upon access if `tintBlack` is disabled. This allows for passing own vertex data to a shader on second and third uv channels. + - Added `Spine/SkeletonGraphic Grayscale` shader to provide a basic grayscale shader for SkeletonGraphic as well. SkeletonGraphic Material `SkeletonGraphicDefaultGrayscale` uses this shader and can be assigned at `SkeletonGraphic` components as usual. + - `SkeletonGraphic` now supports automatic scaling based on its `RectTransform` bounds. Automatic scaling can be enabled by setting the added `Layout Scale Mode` Inspector property to either `Width Controls Height`, `Height Controls Width`, `FitInParent` or `EnvelopeParent`. It is set to `None` by default to keep previous behaviour and avoid breaking existing projects. To modify the reference layout bounds, hit the additional `Edit Layout Bounds` toggle button to switch into edit mode, adjust the bounds or hit `Match RectTransform with Mesh`, and hit the button again when done adjusting. The skeleton will now be scaled accordingly to fit the reference layout bounds to the object's `RectTransform`. + - Added previously missing unlit URP 2D shader variant, available under `Universal Render Pipeline/2D/Spine/Skeleton`. + - Added support for light cookies at `Universal Render Pipeline/Spine/Sprite` shader. + - Timeline extension package: An additional Spine preferences parameter `Timeline` - `Default Mix Duration` has been added, setting newly added `SpineAnimationStateClip` clips accordingly, defaults to false. This Spine preferences parameter can be enabled to default to the previous behaviour before this update. + - Tint Black: Added support for [Tint Black](http://en.esotericsoftware.com/spine-slots#Tint-black) functionality at all Spine URP shaders (2D and 3D shaders) and at all standard pipeline `Spine/Sprite` shaders. This feature can be enabled via the `Tint Black` material parameter in the Inspector. Note: The URP Sprite shaders provided in the Spine URP Shaders extension UPM package require the latest version of the spine-unity runtime (package version 4.1.12, 2023-05-31 or newer) to display the added material parameters in the Inspector GUI. + - Added `SkeletonGraphic.MeshScale` property to allow access to calculated mesh scale. `MeshScale` is based on (1) Canvas pixels per unit, and (2) `RectTransform` bounds when using `Layout Scale Mode` other than `None` at `SkeletonGraphic` which scales the skeleton mesh to fit the parent `RectTransform` bounds accordingly. + - Added `updateSeparatorPartScale` property to `SkeletonGraphic` to let render separator parts follow the scale (lossy scale) of the `SkeletonGraphic` GameObject. Defaults to `false` to maintain existing behaviour. + - Added experimental `EditorSkeletonPlayer` component to allow Editor playback of the initial animation set at `SkeletonAnimation` or `SkeletonGraphic` components. Add this component to your skeleton GameObject to enable the in-editor animation preview. Allows configurations for continuous playback when selected, deselected, and alternative single-frame preview by setting `Fixed Track Time` to any value other than 0. Limitations: At skeletons with variable material count the Inspector preview may be too unresponsive. It is then recommended to disable the `EditorSkeletonPlayer` component (at the top of the Inspector) to make it responsive again, then you can disable `Play When Selected` and re-enable the component to preview playback only when deselected. + - Added example component `RenderCombinedMesh` to render a combined mesh of multiple meshes or submeshes. This is required by `OutlineOnly` shaders to render a combined outline when using `SkeletonRenderSeparator` or multiple atlas pages which would normally lead to outlines around individual parts. To add a combined outline to your SkeletenRenderer: + 1. Add a child GameObject and move it a bit back (e.g. position Z = 0.01). + 2. Add a `RenderCombinedMesh` component, provided in the `Spine Examples/Scripts/Sample Components` directory. + 3. Copy the original material, add _\_Outline_ to its name and set the shader to your outline-only shader like `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly` or `Spine/Outline/OutlineOnly-ZWrite`. + 4. Assign this _\_Outline_ material at the new child GameObject's `MeshRenderer` component. + If you are using `SkeletonRenderSeparator` and need to enable and disable the `SkeletonRenderSeparator` component at runtime, you can increase the `RenderCombinedMesh` `Reference Renderers` array by one and assign the `SkeletonRenderer` itself at the last entry after the parts renderers. Disabled `MeshRenderer` components will be skipped when combining the final mesh, so the combined mesh is automatically filled from the desired active renderers. + - Timeline extension package: Added static `EditorEvent` callback to allow editor scripts to react to animation events outside of play-mode. Register to the events via `Spine.Unity.Playables.SpineAnimationStateMixerBehaviour.EditorEvent += YourCallback;`. + - URP Shaders: Added `Depth Write` property to shaders `Universal Render Pipeline/Spine/Skeleton` and `Universal Render Pipeline/Spine/Skeleton Lit`. Defaults to false to maintain existing behaviour. + - Added `Animation Update` mode (called `UpdateTiming` in code) `In Late Update` for `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic`. This allows you to update the `SkeletonMecanim` skeleton in the same frame that the Mecanim Animator updated its state, which happens between `Update` and `LateUpdate`. + - URP Shaders: Added URP "Blend Mode" shader variants for both URP 3D and URP 2D renderers. They are listed under shader name "Universal Render Pipeline/Spine/Blend Modes/" and "Universal Render Pipeline/2D/Spine/Blend Modes/" respectively. + - URP Shaders: Added support for [Tint Black](http://en.esotericsoftware.com/spine-slots#Tint-black) functionality at "Blend Modes" Spine URP shaders (2D and 3D shaders). + - PhysicsConstraints: Skeleton GameObjects now automatically apply Transform translation and rotation to the skeleton's `PhysicsConstraints`. You can disable applying translation or rotation at the Skeleton component Inspector under `Advanced - Physics Inheritance` by setting `Position` to (0,0)and `Rotation` to 0, or by setting the properties `physicsPositionInheritanceFactor` to `Vector2.zero` and `physicsRotationInheritanceFactor` to `0` at the skeleton component via code. + - Added `Physics Constraints` example scene (located in `Spine Examples/Other Examples`) together with `celestial-circus` example skeleton assets. This scene demonstrates Transform movement automatically affecting physics constraints of a skeleton. + - PhysicsConstraints: Skeleton components now allow you to use relative instead of world-space Transform movement by assigning a Transform (typically the parent) to the new `Movement relative to` property. Leave this property at `null` (the default) to use world-space Transform movement for physics. + - PhysicsConstraints: Added Spine Preferences settings `Editor Instantiation` - `Physics Inheritance` - `Default Position` and `Default Rotation` to initialize skeletons physics settings with the desired Transform position and rotation inheritance factors when added to a scene via drag-and-drop. + - SkeletonGraphic: Added Tint Black blend mode shaders `Spine/SkeletonGraphic Tint Black Additive`, `Spine/SkeletonGraphic Tint Black Multiply` and `Spine/SkeletonGraphic Tint Black Screen`. + - SkeletonGraphic: Added pre-defined SkeletonGraphic material sets for main workflow parameters in folders `spine-unity/Materials` instead of requiring manual copies: + `SkeletonGraphic-PMATexture` containing materials for premultiplied-alpha texture workflow (`Straight Alpha Texture` disabled) and `SkeletonGraphic-StaightAlphaTexture` containing materials for straight alpha texture workflow (`Straight Alpha Texture` enabled). These directories contain a set of materials with `CanvasGroup Compatible` disabled for usage with `Advanced - PMA Vertex Color` enabled at the component. Each directory also provides a subdirectory `CanvasGroupCompatible` with materials with `CanvasGroup Compatible` enabled for usage with `CanvasGroup` alpha (requiring `Advanced - PMA Vertex Color` disabled at the component). + - SkeletonGraphic: Added auto-detect functionality for parameters `Advanced` - `Tint Black`, `CanvasGroup Compatible` and `PMA Vertex Color`. If unsure which settings are correct, hit the `Detect` button next to each parameter, in top to bottom order, or the `Detect Settings` to detect all three. Also added automatic material assignment via a `Detect Material` button in the `Advanced` section and a `Detect` button next to the `Material` property at the top of the component Inspector, as well as next to the `Blend Mode Materials` section when using multiple canvas renderers with blend modes. The suitable material is selected based on these three settings, combined with texture settings (PMA or straight alpha texture settings). If you receive incorrect results, likely your texture settings are incorrectly setup for your PMA or Straight alpha texture export settings. + - `SkeletonRenderTexture` example components now provide a `shaderPasses` parameter to customize which passes are rendered to the `RenderTexture`. It defaults to `-1` for all passes to keep the existing behaviour. You might want to set it to `0` to only render the first pass e.g. to avoid issues when using a URP shader at the original skeleton. + - `SkeletonGraphicRenderTexture` example component now also received a `quadMaterial` property, defaulting to the newly added Material asset `RenderQuadGraphicMaterial` which applies proper premultiplied-alpha blending of the render texture. The `quadMaterial` member variable was moved from `SkeletonRenderTexture` to the common base class `SkeletonRenderTextureBase`. + - All Spine Outline shaders, including the URP outline shader, now provide an additional parameter `Width in Screen Space`. Enable it to keep the outline width constant in screen space instead of texture space. Requires more expensive computations, so enable only where necessary. Defaults to `disabled` to maintain existing behaviour. + - Added support for BlendModeMaterials at runtime instantiation from files via an additional method `SkeletonDataAsset.SetupRuntimeBlendModeMaterials`. See example scene `Spine Examples/Other Examples/Instantiate from Script` for a usage example. + - SkeletonGraphic: You can now offset the skeleton mesh relative to the pivot via a newly added green circle handle. This allows you to e.g. frame only the face of a skeleton inside a masked frame. Previously offsetting the pivot downwards fails when `Layout Scale Mode` scales the mesh smaller and towards the pivot (e.g. the feet) and thus out of the frame. Now you can keep the pivot in the center of the `RectTransform` while offsetting only the mesh downwards, keeping the desired skeleton area (e.g. the face) centered while resizing. Moving the new larger green circle handle moves the mesh offset, while moving the blue pivot circle handle moves the pivot as usual. + - `Universal Render Pipeline/Spine/Skeleton` shader now performs proper alpha-testing when `Depth Write` is enabled, using the existing `Shadow alpha cutoff` parameter. + - `SkeletonRootMotion` components now provide a public `Initialize()` method which is automatically called when calling `skeletonAnimation.Initialize(true)` to update the necessary skeleton references. If a different root bone shall be used, be sure to set `skeletonRootMotion.rootMotionBoneName` before calling `skeletonAnimation.Initialize(true)`. + - Skeleton Mecanim: Added new `Mix Mode` `Match`. When selected, Spine animation weights are calculated to best match the provided Mecanim clip weights. This mix mode is recommended on any layer using blend tree nodes. + - URP Shaders: Added `ZWrite` variant of outline shader `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly ZWrite`. Suitable for e.g. depth of field (DoF) effect where writing to the depth buffer is required. Note that for DoF effect, `Render Queue` needs to be set to `Alpha Test`. + - SkeletonGraphic: Exposed `SetScaledPivotOffset` as public method outside of the editor to support programatically moving mesh offsets at runtime based on mesh bounds. + - SkeletonMecanim: Added `Scene Preview` option to preview an Animation Clip for e.g. easier event placement. When enabled, the Animation Clip selected in the Animation window is previewed in the Scene and Game views. Lock the `SkeletonMecanim` Inspector window, open the Animation window and select the Animation Clip. Then in the Animation window scrub through the timeline to see the current animation frame previewed. + - `Universal Render Pipeline/Spine/Skeleton Lit` shader now supports [Adaptive Probe Volumes (APV)](https://docs.unity3d.com/6000.0/Documentation/Manual/urp/probevolumes-concept.html) introduced in Unity 6. The shader also provides a new material property `APV per Pixel` to either calculate APV lighting contribution per pixel (the default) or per vertex. + - `Universal Render Pipeline/Spine/Sprite` shader now also supports [Adaptive Probe Volumes (APV)](https://docs.unity3d.com/6000.0/Documentation/Manual/urp/probevolumes-concept.html) introduced in Unity 6. APV lighting contribution is automatically calculated per pixel. + - All Spine Outline shaders, including the URP outline shaders, now provide an additional parameter `Fill`. Enable it to also fill the opaque area inside the outline with the outline color. Prevents a semi-transparent gap between outline and skeleton. Defaults to `disabled` to maintain existing behaviour. + - Added example component `RenderExistingMeshGraphic` (similar to `RenderExistingMesh`) to render a `SkeletonGraphic` mesh again with different materials. This might be required by e.g. URP and SkeletonGraphic outline shaders skipping additional render passes. To add a second outline variant of your SkeletonGraphic: + 1. Add a GameObject at the same hierarchy level as the reference SkeletonGraphic and move it before the reference SkeletonGraphic to render behind. + 2. Add a `RenderExistingMeshGraphic` component. + 3. In the `RenderExistingMeshGraphic` component Inspector at `Reference Skeleton Graphic` assign the original `SkeletonGraphic` object. + 4. At `Replacement Material` assign e.g. the included _SkeletonGraphicDefaultOutline_ material to replace all materials with this material. Alternatively, if `Multiple CanvasRenderers` is enabled at the reference SkeletonGraphic, you can add entries to the `Replacement Materials` list and at each entry assign the original SkeletonGraphic material (e.g. _SkeletonGraphicDefault_) to be replaced and the respective `Replacement Material` (e.g. _SkeletonGraphicDefaultOutline_). + - Added option for unsafe direct data loading when loading skeleton binary data to avoid some allocations, enabled via build define `SPINE_ALLOW_UNSAFE`. This define can be set via Spine Preferences, setting `Unsafe Build Defines - Direct data access`. The define is disabled by default to maintain existing behaviour. Changed asmdef setting for spine-unity assembly to allow unsafe code, has no effect other than allowing setting the `SPINE_ALLOW_UNSAFE` define. + - Added option to `BoneFollower` components to follow attachment Z spacing offset. The Inspector component property can be found under `Follow Z Position` - `Attachment Z Spacing`. Defaults to `false` to maintain existing behaviour. + - `SkeletonGraphic` now allows using separate additive Materials despite having `PMA Vertex Colors` enabled (as required for Spine shaders) via the new `Blend Modes` - `Force Additive Material` property in the `Advanced` Inspector section. + - Exposed `SpineVisualElement.Initialize` as `public`. + +- **Breaking changes** + + - Changed `SpineShaderWithOutlineGUI` outline related methods from `private` to `protected virtual` to allow for custom shader GUI subclasses to switch to different outline shaders. + - Changed `BoneFollower` and `BoneFollowerGraphic` methods `LateUpdate` and `Initialize` to `virtual` to allow easier overriding for e.g. positional offset in custom subclasses. + - `MeshGenerator` received a new optimization option to avoid rendering fully transparent attachments at slot alpha 0 by default. Comment out `#define SLOT_ALPHA_DISABLES_ATTACHMENT` in `MeshGenerator.cs` to revert to previous behaviour. You may only need this option disabled when utilizing a custom shader which uses vertex color alpha for purposes other than transparency. + - PhysicsConstraints: bool properties `ApplyTranslationToPhysics` and `ApplyRotationToPhysics` were changed to `Vector2 PhysicsPositionInheritanceFactor` and `float PhysicsRotationInheritanceFactor` to allow the Transform movement the be scaled by a factor before being applied to the skeleton. You can set the properties to `Vector2.zero` and `0` respectively to disable applying any Transform movement at all. The `Advanced` Inspector section `Physics Constraints` was renamed to `Physics Inheritance`, the properties in the section are now called `Position` and `Rotation`. + - SkeletonGraphic Materials: Since the addition of new material sets for the `CanvasGroupCompatible` parameters, the default SkeletonGraphic materials all have `CanvasGroup Compatible` disabled. Please assign the respective material from the `CanvasGroupCompatible` material subdirectory if you want `CanvasGroup Compatible` enabled at your SkeletonGraphic. + - SkeletonGraphic: The parameter `SkeletonGraphic.MeshGenerator.settings.canvasGroupTintBlack` was changed to `canvasGroupCompatible` to help with auto-detecting correct Vertex Data and Material settings. Set the parameter to true if the SkeletonGraphic component is located below a `CanvasGroup` component. The parameter value is automatically migrated from `canvasGroupTintBlack`. + - Inspector: String attribute `SpineSkin()` now allows to include `` in the list of parameters. Previously the `includeNone=true` parameter of the `SpineSkin()` attribute defaulted to `true` but was ignored. Now it defaults to `false` and has an effect on the list. Only the Inspector GUI is affected by this behaviour change. + - `SkeletonGraphicRenderTexture` example component: `protected RawImage quadRawImage` was changed to `protected SkeletonSubmeshGraphic quadMaskableGraphic` for a bugfix. This is only relevant for subclasses of `SkeletonGraphicRenderTexture` or when querying the `RawImage` component via e.g. `skeletonGraphicRenderTexture.quad.GetComponent()`. + - Fixed a bug where when Linear color space is used and `PMA vertex colors` enabled, additive slots add a too dark (too transparent) color value. If you want the old incorrect behaviour (darker additive slots) or are not using Linear but Gamma color space, you can comment-out the define `LINEAR_COLOR_SPACE_FIX_ADDITIVE_ALPHA` in `MeshGenerator.cs` to deactivate the fix or just to skip unnecessary instructions. + - Fixed SkeletonRootMotion components ignoring parent bone scale when set by transform constraints. Using applied scale of parent bone now. If you need the old behaviour, comment out the line `#define USE_APPLIED_PARENT_SCALE` in SkeletonRootMotionBase.cs. + - Fixed SkeletonUtility callback update order when used with SkeletonRootMotion components so that the position when following a bone is updated after SkeletonRootMotion clears root-bone position. The order of SkeletonUtilityBone callbacks is changed to be later to achieve this. This is a breaking change in the unlikely case that you are using SkeletonRootMotion together with SkeletonUtility and subscribed to `UpdateLocal`, `UpdateWorld` or `UpdateComplete` yourself and relied on a certain callback order. One solution is to then resubscribe your own callback events accordingly by calling + `.UpdateLocal -= Callback; .UpdateLocal += Callback;`. + +- **Changes of default values** + +- **Deprecated** + +- **Restructuring (Non-Breaking)** + +### XNA/MonoGame + +- **Additions** + - Apply external movement to physics: If you are not directly modifying `Skeleton.X` or `Skeleton.Y`, you can apply external game object movement to skeleton physics as follows: + Add a `Vector2 lastPosition;` member variable to your class interacting with the skeleton. Then call e.g. the following code each frame: + ``` + Vector2 currentPosition = ; + Vector2 externalPositionDelta = currentPosition - lastPosition; + skeleton.PhysicsTranslate(externalPositionDelta.x, externalPositionDelta.y); + lastPosition = currentPosition; + ``` + +## Java + +- Added physics support + - Added `PhysicsConstraintXXXTimeline` and `PhysicsConstraintResetTimeline` + - Added `Physics` to be passed to `Skeleton#updateWorldTransform()` + - Added `SkeletonData#findPhysicsConstraint()` and `SkeletonData#getPhysicsConstraints()` to query physics constraints + - Added `Skeleton#findPhysicsConstraint()` and `Skeleton#getPhysicsConstraints()` to query physics constraints + - Added `Skeleton#physicsTranslate()` to translate all physics constraints by some distances in the skeleton coordinate system + - Added `Skeleton#physicsRotate()` to rotate all physics constraints by some distances in the skeleton coordinate system + - Added `Skeleton#time` and respective setters/getters to keep track of time for physics simulations + - See also breaking changes for `Skeleton#updateWorldTransform()` and the requirement to call `Skeleton#update()` to advance + pyhsics each frame. +- Added `InheritTimeline` +- Added [`TrackEntry#alphaAttachmentThreshold`](http://esotericsoftware.com/spine-api-reference#TrackEntry-alphaAttachmentThreshold) +- Added `TrackEntry#setMixDuration()` to set the mix duration in conjunction with a delay +- Added `TrackEntry#wasApplied()` to check if the entry has been applied +- Added `Bone#worldToParent()` to transform coordinates from world space to the parent space of a bone +- Added `Bone#localToParent()` to transform coordinates from a bone's local space to its parent space +- Added non essential fields `icon` and `visible` to `BoneData` +- Added non essential fields `path` and `visible` to `SlotData` +- Added `setToSetupPose()` to all contraint classes +- **Breaking changes** + - Renamed `TrackEntry#attachmentThreshold` to `TrackEntry#mixAttachmentThreshold` along with respective getters/settesr + - Renamed `TrackEntry::drawOrderThreshold` to `TrackEntry#mixDrawOrdertThreshold` along with respective getters/settesr + - Renamed `TransformMode` to `Inherit` and all `TransformMode_*` enums to `Inherit_*` + - You must call `Skeleton#update(delta)` before calling `Skeleton#updateWorldTransform()` if the frame time has advanced. This is needed to update physics accordingly + - `Skeleton#updateWorldTransform()` takes an additional `Physics` parameter. See the `Physics` documentation for information on what the different enum values do + - All `Updatable` sub-classes like `Bone` and constraints now take an additional `Physics` parameter for their `update()` methods + +### libGDX + +- Added physics examples + +## Typescript/Javascript + +- Added physics support + - Added `PhysicsConstraintXXXTimeline` and `PhysicsConstraintResetTimeline` + - Added `Physics` to be passed to `Skeleton#updateWorldTransform()` + - Added `SkeletonData#findPhysicsConstraint()` and `SkeletonData#getPhysicsConstraints()` to query physics constraints + - Added `Skeleton#findPhysicsConstraint()` and `Skeleton#getPhysicsConstraints()` to query physics constraints + - Added `Skeleton#physicsTranslate()` to translate all physics constraints by some distances in the skeleton coordinate system + - Added `Skeleton#physicsRotate()` to rotate all physics constraints by some distances in the skeleton coordinate system + - Added `Skeleton#time` and respective setters/getters to keep track of time for physics simulations + - See also breaking changes for `Skeleton#updateWorldTransform()` and the requirement to call `Skeleton#update()` to advance + pyhsics each frame. +- Added `InheritTimeline` +- Added [`TrackEntry#alphaAttachmentThreshold`](http://esotericsoftware.com/spine-api-reference#TrackEntry-alphaAttachmentThreshold) +- Added `TrackEntry#setMixDuration()` to set the mix duration in conjunction with a delay +- Added `TrackEntry#wasApplied()` to check if the entry has been applied +- Added `Bone#worldToParent()` to transform coordinates from world space to the parent space of a bone +- Added `Bone#localToParent()` to transform coordinates from a bone's local space to its parent space +- Added non essential fields `icon` and `visible` to `BoneData` +- Added non essential fields `path` and `visible` to `SlotData` +- Added `setToSetupPose()` to all contraint classes +- **Breaking changes** + - Renamed `TrackEntry#attachmentThreshold` to `TrackEntry#mixAttachmentThreshold` along with respective getters/settesr + - Renamed `TrackEntry::drawOrderThreshold` to `TrackEntry#mixDrawOrdertThreshold` along with respective getters/settesr + - Renamed `TransformMode` to `Inherit` and all `TransformMode_*` enums to `Inherit_*` + - You must call `Skeleton#update(delta)` before calling `Skeleton#updateWorldTransform()` if the frame time has advanced. This is needed to update physics accordingly + - `Skeleton#updateWorldTransform()` takes an additional `Physics` parameter. See the `Physics` documentation for information on what the different enum values do + - All `Updatable` sub-classes like `Bone` and constraints now take an additional `Physics` parameter for their `update()` methods + +### WebGL backend + +- Added physics examples + +### Canvas backend + +### CanvasKit backend + +- Added spine-canvaskit runtime. See https://esotericsoftware.com/spine-canvaskit + +### Three.js backend + +- Added physics support + +### Player + +- Added physics support +- Added `scale` field to configuration which defines the scale to load the skeleton at +- Added `updateWorldTransform` field to configuration which expects a function that updates the skeleton. Defaults to player.skeleton.updateWorldTransform(spine.Physics.update) +- Added `skeleton` to `SpinePlayerConfig` to specify the URL of the skeleton .json or .skel file. Deprecated `jsonURL` and `binaryURL`. The old fields can still be used, but will be removed in Spine 4.3 +- Added `atlas` to `SpinePlayerConfig` to specify the URL of the .atlas file. Deprecated `atlasURL`. The old field can still be used, but will be removed in Spine 4.3. + +### Pixi + +- Added spine-pixi runtime, also backported to Spine 4.1. See https://esotericsoftware.com/spine-pixi + +### Phaser + +- Added spine-phaser runtime, also backported to Spine 4.1. See https://esotericsoftware.com/spine-phaser + +## Haxe + +- Added spine-haxe runtime, also backported to Spine 4.1. See https://esotericsoftware.com/spine-haxe + +## Flutter + +- Added spine-flutter runtime, also backported to Spine 4.1. See https://esotericsoftware.com/spine-flutter + +# 4.1 + +## C + +- **Additions** + - Support for sequences. + - Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + - Added CMake parameter `SPINE_SANITIZE` which will enable sanitizers on macOS and Linux. + - Added `SPINE_MAJOR_VERSION`, `SPINE_MINOR_VERSION`, and `SPINE_VERSION_STRING`. Parsing skeleton .JSON and .skel files will report an error if the skeleton version does not match the runtime version. +- **Breaking changes** + - `spRegionAttachment` and `spMeshAttachment` now contain a `spTextureRegion*` instead of encoding region fields directly. + - `sp_AttachmentLoader_newRegionAttachment()` and `spAttachmentLoader_newMeshAttachment()` now take an additional `Sequence*` parameter. + - `spMeshAttachment_updateUVs()` was renamed to `spMeshAttachment_updateRegion()`. + - `spRegionAttachment_updateOffset()` was renamed to `spRegionAttachment_updateRegion()`, `spRegionAttachment_setUVs()` was merged into `spRegionAttachment_updateRegion()`. + - `spSlot_getAttachmentTime()` and `spSlot_setAttachmentTime()` have been removed. + - `spVertexAttachment->deformAttachment` was renamed to `spVertexAttachment->timelineAttachment`. + - `spSkeleton_update()` has been removed. + - `spSkeleton->time` has been removed. + - `spVertexEffect` has been removed. + +### SFML + +- Updated example to use SFML 2.5.1. +- Added dragon example. + +## C++ + +- **Additions** + - Support for sequences. + - Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + - Added CMake parameter `SPINE_SANITIZE` which will enable sanitizers on macOS and Linux. + - Added `SPINE_MAJOR_VERSION`, `SPINE_MINOR_VERSION`, and `SPINE_VERSION_STRING`. Parsing skeleton .JSON and .skel files will report an error if the skeleton version does not match the runtime version. + - Added `SkeletonBounds::getBoundingBox()`, `SkeletonBounds::getPolygons()`, and `SkeletonBounds::getBoundingBoxes()`. +- **Breaking changes** + - `RegionAttachment` and `MeshAttachment` no longer implement `HasRendererObject`. + - `RegionAttachment` and `MeshAttachment` now contain a `TextureRegion*` instead of encoding region fields directly. + - `AttachmentLoader::newRegionAttachment()` and `AttachmentLoader::newMeshAttachment()` now take an additional `Sequence*` parameter. + - `MeshAttachment::updateUVs()` was renamed to `MeshAttachment::updateRegion()`. + - `RegionAttachment::updateOffset()` was renamed to `RegionAttachment::updateRegion()`, `RegionAttachment::setUVs()` was merged into `updateRegion()`. + - `Slot::getAttachmentTime()` and `Slot::setAttachmentTime()` have been removed. + - `VertexAttachment::getDeformAttachment()` was renamed to `VertexAttachment::getTimelineAttachment()`. + - `Skeleton::update()` has been removed. + - `Skeleton::getTime()` has been removed. + - `VertexEffect` has been removed. + +### Cocos2d-x +- Renamed `SkeletonRenderer` to `SkeletonRendererCocos2dX` to avoid name clash with spine-cpp class. + +### SFML + +- Updated example to use SFML 2.5.1. +- Added dragon example. + +### UE4 + +- Updated example project to UE 4.27 + +## C# + +- **Additions** + + - Full support for sequences. + - Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + - `RegionAttachment` and `MeshAttachment` now provide a `Region` property. Use this property instead of the removed `RendererObject` property (see section _Breaking Changes_ below). + +- **Breaking changes** + - Removed `RendererObject` property from `RegionAttachment` and `MeshAttachment`. Use `attachment.Region` property instead. Removed removed `IHasRendererObject` interface. Use `IHasTextureRegion` instead. + - Replaced `RegionAttachment.UpdateOffset` and `MeshAttachment.UpdateUVs` with `Attachment.UpdateRegion`. The caller must ensure that the attachment's region is not `null`. + - Removed `AttachmentRegionExtensions` methods `Attachment.SetRegion`, `MeshAttachment.SetRegion` and `RegionAttachment.SetRegion(region, update)`. Use `attachment.Region = region; if (update) attachment.UpdateRegion()` instead. + - `AttachmentLoader.NewRegionAttachment()` and `AttachmentLoader.NewMeshAttachment()` take an additional `Sequence` parameter. + - `VertexAttachment.DeformAttachment` property has been replaced with `VertexAttachment.TimelineAttachment`. + - `RegionAttachment.ComputeWorldVertices()` takes a `Slot` instead of a `Bone` as the first argument. + - Removed `Skeleton.Update(float deltaTime)` method. + - Removed `Slot.AttachmentTime` property. + - Removed extension method `AtlasRegion.GetSpineAtlasRect()` parameter `includeRotate` (with default value `true`). Most likely this method was never used with `includeRotate=false` in user code so no changes are required. + - `AtlasRegion.PackedWidth` and `AtlasRegion.PackedHeight` are swapped compared to 4.0 when packing rotation is equal to 90 degrees. Most likely this property was never accessed in user code so no changes are required. + +### Unity + +- **Officially supported Unity versions are 2017.1-2023.1**. + +- **Additions** + + - `SpineAtlasAsset.CreateRuntimeInstance` methods now provide an optional `newCustomTextureLoader` parameter (defaults to `null`) which can be set to e.g. `(a) => new YourCustomTextureLoader(a)` to use your own `TextureLoader` subclass instead of `MaterialsTextureLoader`. + - `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic` now provide an Inspector parameter `Advanced` - `Animation Update` with modes `In Update` **(previous behaviour, the default)**, `In FixedUpdate` and `Manual Update`. This allows to update animation in `FixedUpdate` when using the `SkeletonRootMotion` component (which is the recommended combination now, issuing a warning otherwise). The reason is that when root motion leads to a collision with a physics collider, it can introduce jittery excess movement when updating animation in `Update` due to more `Update` calls following a single `FixedUpdate` call. + - Added `SkeletonRootMotion` properties `PreviousRigidbodyRootMotion` and `AdditionalRigidbody2DMovement`. Setting or querying these movement vectors can be necessary when multiple scripts call `Rigidbody2D.MovePosition` on the same object where the last call overwrites the effect of preceding ones. + - `BoneFollower` and `BoneFollowerGraphic` now provide an additional `Follow Parent World Scale` parameter to allow following simple scale of parent bones (rotated/skewed scale can't be supported). + - Improved `Advanced - Fix Prefab Override MeshFilter` property for `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`), now providing an additional option to use a global value which can be set in `Edit - Preferences - Spine`. + - Timeline naming improvements: `Spine AnimationState Clip` Inspector parameter `Custom Duration` changed and inverted to `Default Mix Duration` for more clarity. Shortened all Timeline add track menu entries from: `Spine.Unity.Playables - ` to `Spine - `, `Spine Animation State Track` to `SkeletonAnimation Track`, `Spine AnimationState Graphic Track` to `SkeletonGraphic Track`, and `Spine Skeleton Flip Track` to `Skeleton Flip Track`. + - Timeline track appearance and Inspector: Tracks now show icons and track colors to make them easier to distinguish. When a Track is selected, the Inspector now shows an editable track name which was previously only editable at the Timeline asset. + - Added example component `SkeletonRenderTexture` to render a `SkeletonRenderer` to a `RenderTexture`, mainly for proper transparency. Added an example scene named `RenderTexture FadeOut Transparency` that demonstrates usage for a fadeout transparency effect. + - Added another fadeout example component named `SkeletonRenderTextureFadeout` which takes over transparency fadeout when enabled. You can use this component as-is, attach it in disabled state and enable it to start a fadeout effect. + - Timeline clips now offer an additional `Alpha` parameter for setting a custom constant mix alpha value other than 1.0, just as `TrackEntry.Alpha`. Defaults to 1.0. + - `GetRemappedClone` copying from `Sprite` now provides additional `pmaCloneTextureFormat` and `pmaCloneMipmaps` parameters to explicitly specify the texture format of a newly created PMA texture. + - Spine property Inspector fields (`Animation Name`, `Bone Name`, `Slot` and similar) now display the name in red when the respective animation/bone/etc no longer exists at the skeleton data. This may be helpful when such items have been renamed or deleted. + - Added `UnscaledTime` property at `SkeletonAnimation` as well, behaving like `SkeletonGraphic.UnscaledTime`. If enabled, AnimationState uses unscaled game time (`Time.unscaledDeltaTime`), running animations independent of e.g. game pause (`Time.timeScale`). + - `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic` now provide an additional `OnAnimationRebuild` callback delegate which is issued after both the skeleton and the animation state have been initialized. + - Timeline `SkeletonAnimation Track` and `SkeletonGraphic Track` now provide an `Unscaled Time` property. Whenever starting a new animation clip of this track, `SkeletonAnimation.UnscaledTime` or `SkeletonGraphic.UnscaledTime` will be set to this value. This allows you to play back Timeline clips either in normal game time or unscaled game time. Note that `PlayableDirector.UpdateMethod` is ignored and replaced by this property, which allows more fine-granular control per Timeline track. + - Added `SkeletonRootMotion` callback delegates `ProcessRootMotionOverride` and `PhysicsUpdateRootMotionOverride` to customize how root motion is applied. The new property `disableOnOverride` determines whether the callback will be issued in addition or instead of normally applying root motion. Added property `rootMotionScaleRotation` to allow scaling rotational root-motion to match e.g. a 90 degree rotation to a custom target angle. + - Added outline shader parameter `Advanced - Opaque Alpha` which can be used to exclude problematic semi-transparent areas, which may receive an undesired large outline color overlay otherwise. + - Added Spine Preferences setting `Prefabs` - `Optimize Preview Meshes`. When enabled, Spine prefab preview meshes will be removed in a pre-build step to reduce build size. This increases build time as all prefabs in the project will be processed. Defaults to false to not slow down builds substantially every time. + - Added Spine Preferences setting `Reload SkeletonData after Play`. When enabled, the shared `SkeletonData` of all skeletons in the active scene is reloaded (from the `.json` or `.skel.bytes` file) after exiting play-mode. You can disable this setting to avoid the reloading delay if you can ensure that there are no (accidental) modifications to the shared `SkeletonData` during play-mode (otherwise it would carry over its effect into subsequent plays). Defaults to `true` (the safe setting), which maintains existing behaviour. + - Added `SkeletonAnimationMulti` sample component methods `SetActiveSkeleton(int index)` and getter property `SkeletonAnimations` to more easily apply changes at all SkeletonAnimation instances instead of only the active one. + - PMA textures now have `sRGB (Color Texture)` disabled by default, the preset template `PMATexturePreset.preset` has been adjusted accordingly. As PMA textures are only allowed with Gamma color space, `sRGB (Color Texture)` shall be disabled to prevent border artifacts when mipmaps are enabled. In Gamma color space having this setting disabled has no drawbacks, only benefits. + - `SkeletonRenderTexture` and `SkeletonGraphicRenderTexture` components now support automatic down-scaling when required size on screen exceeds `Max Render Texture Size`. + - Added `Spine/SkeletonGraphic Fill` shader to provide functionality of `Spine/Skeleton Fill` shader for `SkeletonGraphic`. + - Lit Spine URP shaders (`Universal Render Pipeline/Spine/Sprite` and `Universal Render Pipeline/Spine/Skeleton Lit`) now support `Forward+` rendering path as introduced by Unity 2022.2 and URP version 14. + - `SkeletonGraphic` now supports automatic scaling based on its `RectTransform` bounds. Automatic scaling can be enabled by setting the added `Layout Scale Mode` Inspector property to either `Width Controls Height`, `Height Controls Width`, `FitInParent` or `EnvelopeParent`. It is set to `None` by default to keep previous behaviour and avoid breaking existing projects. To modify the reference layout bounds, hit the additional `Edit Layout Bounds` toggle button to switch into edit mode, adjust the bounds or hit `Match RectTransform with Mesh`, and hit the button again when done adjusting. The skeleton will now be scaled accordingly to fit the reference layout bounds to the object's `RectTransform`. + - Added previously missing unlit URP 2D shader variant, available under `Universal Render Pipeline/2D/Spine/Skeleton`. + - Added support for light cookies at `Universal Render Pipeline/Spine/Sprite` shader. + - Timeline extension package: An additional Spine preferences parameter `Timeline` - `Default Mix Duration` has been added, setting newly added `SpineAnimationStateClip` clips accordingly, defaults to false. This Spine preferences parameter can be enabled to default to the previous behaviour before this update. + - Tint Black: Added support for [Tint Black](http://en.esotericsoftware.com/spine-slots#Tint-black) functionality at all Spine URP shaders (2D and 3D shaders) and at all standard pipeline `Spine/Sprite` shaders. This feature can be enabled via the `Tint Black` material parameter in the Inspector. Note: The URP Sprite shaders provided in the Spine URP Shaders extension UPM package require the latest version of the spine-unity runtime (package version 4.1.12, 2023-05-31 or newer) to display the added material parameters in the Inspector GUI. + - Added `SkeletonGraphic.MeshScale` property to allow access to calculated mesh scale. `MeshScale` is based on (1) Canvas pixels per unit, and (2) `RectTransform` bounds when using `Layout Scale Mode` other than `None` at `SkeletonGraphic` which scales the skeleton mesh to fit the parent `RectTransform` bounds accordingly. + - Added `updateSeparatorPartScale` property to `SkeletonGraphic` to let render separator parts follow the scale (lossy scale) of the `SkeletonGraphic` GameObject. Defaults to `false` to maintain existing behaviour. + - Added experimental `EditorSkeletonPlayer` component to allow Editor playback of the initial animation set at `SkeletonAnimation` or `SkeletonGraphic` components. Add this component to your skeleton GameObject to enable the in-editor animation preview. Allows configurations for continuous playback when selected, deselected, and alternative single-frame preview by setting `Fixed Track Time` to any value other than 0. Limitations: At skeletons with variable material count the Inspector preview may be too unresponsive. It is then recommended to disable the `EditorSkeletonPlayer` component (at the top of the Inspector) to make it responsive again, then you can disable `Play When Selected` and re-enable the component to preview playback only when deselected. + - Added example component `RenderCombinedMesh` to render a combined mesh of multiple meshes or submeshes. This is required by `OutlineOnly` shaders to render a combined outline when using `SkeletonRenderSeparator` or multiple atlas pages which would normally lead to outlines around individual parts. To add a combined outline to your SkeletenRenderer: + 1. Add a child GameObject and move it a bit back (e.g. position Z = 0.01). + 2. Add a `RenderCombinedMesh` component, provided in the `Spine Examples/Scripts/Sample Components` directory. + 3. Copy the original material, add _\_Outline_ to its name and set the shader to your outline-only shader like `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly` or `Spine/Outline/OutlineOnly-ZWrite`. + 4. Assign this _\_Outline_ material at the new child GameObject's `MeshRenderer` component. + If you are using `SkeletonRenderSeparator` and need to enable and disable the `SkeletonRenderSeparator` component at runtime, you can increase the `RenderCombinedMesh` `Reference Renderers` array by one and assign the `SkeletonRenderer` itself at the last entry after the parts renderers. Disabled `MeshRenderer` components will be skipped when combining the final mesh, so the combined mesh is automatically filled from the desired active renderers. + - Timeline extension package: Added static `EditorEvent` callback to allow editor scripts to react to animation events outside of play-mode. Register to the events via `Spine.Unity.Playables.SpineAnimationStateMixerBehaviour.EditorEvent += YourCallback;`. + - URP Shaders: Added `Depth Write` property to shaders `Universal Render Pipeline/Spine/Skeleton` and `Universal Render Pipeline/Spine/Skeleton Lit`. Defaults to false to maintain existing behaviour. + - Added `Animation Update` mode (called `UpdateTiming` in code) `In Late Update` for `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic`. This allows you to update the `SkeletonMecanim` skeleton in the same frame that the Mecanim Animator updated its state, which happens between `Update` and `LateUpdate`. + - URP Shaders: Added URP "Blend Mode" shader variants for both URP 3D and URP 2D renderers. They are listed under shader name "Universal Render Pipeline/Spine/Blend Modes/" and "Universal Render Pipeline/2D/Spine/Blend Modes/" respectively. + - URP Shaders: Added support for [Tint Black](http://en.esotericsoftware.com/spine-slots#Tint-black) functionality at "Blend Modes" Spine URP shaders (2D and 3D shaders). + +- **Breaking changes** + + - Made `SkeletonGraphic.unscaledTime` parameter protected, use the new property `UnscaledTime` instead. + - `SkeletonGraphic` `OnRebuild` callback delegate is now issued after the skeleton has been initialized, before the `AnimationState` component is initialized. This makes behaviour consistent with `SkeletonAnimation` and `SkeletonMecanim` component behaviour. Use the new callback `OnAnimationRebuild` if you want to receive a callback after the `SkeletonGraphic` `AnimationState` has been initialized. + - Changed name of prefab skeleton meshes stored at prefabs from `Skeleton Prefab Mesh "name"` to `Skeleton Prefab Mesh [name]` to avoid issues with quotes in mesh asset names (see [this issue](https://github.com/EsotericSoftware/spine-runtimes/issues/2572)). Likely this change poses no problems at all, however if you are parsing the prefab's mesh name for whatever reason, be sure to adjust the pattern accordingly. + +- **Changes of default values** + +- **Deprecated** + + - Shader macro `RETURN_UNLIT_IF_ADDITIVE_SLOT` in `spine-unity/Shaders/Sprite/CGIncludes/ShaderShared.cginc` has been deprecated and will be removed in spine-unity 4.2. Use RETURN_UNLIT_IF_ADDITIVE_SLOT_TINT instead. + +- **Restructuring (Non-Breaking)** + - Moved Spine URP Shaders Examples directory from the main package directory to Samples which can be installed via the Unity Package Manager. To import, select the `Spine Universal RP Shaders` package in the Package Manager window, expand `Samples` at the bottom and hit `Import` next to `Examples`. This follows the standard [samples guideline](https://docs.unity3d.com/Manual/cus-samples.html) and prevents warning messages about unexpectedly altered immutable assets. + +### XNA/MonoGame + +- **Breaking change**: Removed spine-xna in favor of spine-monogame. See https://github.com/EsotericSoftware/spine-runtimes/issues/1949 +- Added new spine-monogame solution. See [spine-monogame/README.md](spine-monogame/README.md) for updated instructions on how to use spine-monogame. + +## Java + +- **Additions** + - Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + - Support for sequences. +- **Breaking changes** + - `AttachmentLoader#newRegionAttachment()` and `AttachmentLoader#newMeshAttachment()` take an additional `Sequence` parameter. + - `Slot#setAttachmentTime()` and `Slot#getAttachmentTime()` have been removed. + - `VertexAttachment#setDeformAttachment()` and `VertexAttachment#getDeformAttachment()` have been replaced with `VertexAttachment#setTimelineAttachment()` and `VertexAttachment#getTimelineAttachment()`. + - `RegionAttachment#updateOffset()` has been renamed to `RegionAttachment#updateRegion()`. The caller must ensure that the attachment's region is not `null`. + - `RegionAttachment#computeWorldVertices()` takes a `Slot` instead of a `Bone` as the first argument. + - `VertexEffect` has been removed. + +### libGDX + +- `spine-libgdx`, `spine-libgdx-tests`, and `spine-skeletonviewer` are now fully Gradle-ified. +- `spine-skeletonviewer` now supports quickly loading skeletons by dragging and dropping `.json` or `.skel` skeleton files onto the window. + +## Typescript/Javascript + +- **Additions** + - full support for sequences. + - Added `Promise` based `AssetManager.loadAll()`. Allows synchronous waiting via `await assetManager.loadAll()`, simplifying loader logic in applications. + - Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + - Full support for sequences. +- **Breaking changes** + - `AttachmentLoader#newRegionAttachment()` and `AttachmentLoader#newMeshAttachment()` take an additional `Sequence` parameter. + - `Slot#attachmentTime` and has been removed. + - `VertexAttachment#deformAttachment` has been replaced with `VertexAttachment#timelineAttachment`. + - `RegionAttachment#updateOffset()` has been renamed to `RegionAttachment#updateRegion()`. The caller must ensure that the attachment's region is not `null`. + - `RegionAttachment#computeWorldVertices()` takes a `Slot` instead of a `Bone` as the first argument. + - Removed `PlayerEditor`. + - `VertexEffect` has been removed. + - Removed `RegionAttachment.rendererObject`. + - Renamed `TextureRegion.renderObject` to `TextureRegion.texture`. + +### WebGL backend + +- `PolygonBatcher` can now disable culling automatically if the static variable `PolygonBatcher.disableCulling` is set to true. +- Added `SpineCanvas`, a simpler way to render a scene via spine-webgl. See `spine-ts/spine-webgl/examples/barebones.html` and `spine-ts/spine-webgl/examples/mix-and-match.html`. +- Added `SpineCanavs.dispose()` to halt the updating and rendering of the canvas. + +### Canvas backend + +- Improved example. + +### Three.js backend + +- Added orbital controls to THREJS example. +- `SkeletonMesh` takes an optional `SkeletonMeshMaterialCustomizer`, allowing modification of materials used by `SkeletonMesh`. +- Added `SkeletonMeshMaterial.alphaTest`, when > 0, alpha testing will be performed and fragments will not be written to the depth buffer, if depth writes are enabled. + +### Player + +- Added `SpinePlayer.dispose()` to explicitely dispose of all resources the player holds on to. + +# 4.0 + +## AS3 + +**NOTE: Spine 4.0 will be the last release supporting spine-as3. Starting from Spine 4.1, spine-as3 will no longer be supported or maintained.** + +- Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. +- Expose non-essential colors on bones, bounding box, clipping, and path attachments. +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +- Added support for reverse animation playback via `TrackEntry.reverse`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. + +### Starling + +**NOTE: Spine 4.0 will be the last release supporting spine-starling. Starting from Spine 4.1, spine-starling will no longer be supported or maintained.** + +- Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. +- Updated to Starling 2.6 and Air SDK 33. + +## C + +- **Breaking change:** Removed `SPINE_SHORT_NAMES` define and C++ constructors. +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `spAnimationState_clearNext()` which removes the given `spTrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `spAtlasRegion.keyValues`. +- Added support for reverse animation playback via `spTrackEntry.reverse`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. + +### Cocos2d-Objc + +**NOTE: Spine 4.0 will be the last release supporting spine-cocos2d-objc. Starting from Spine 4.1, spine-cocos2d-objc will no longer be supported or maintained.** + +### SFML + +- Added `ikDemo()` in `main.cpp`. to illustrate how to drive a bone and IK chain through mouse movement. + +## C++ + +- Removed dependency on STL throughout the code base, cutting down on the LOC that need parsing by 66%. +- Exposed `x` and `y` on `SkeletonData` through getters and setters. +- Expose non-essential colors on bones, bounding box, clipping, and path attachments. +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +- Added support for reverse animation playback via `TrackEntry.reverse`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. +- spine-cpp now requires C++11. + +### Cocos2d-x + +- Added `IKExample` scene to illustrate how to drive a bone and IK chain through mouse movement. +- Added `SkeletonAnimation::setPreUpdateWorldTransformsListener()` and `SkeletonAnimation::setPostUpdateWorldTransformsListener()`. This allows users to modify bone transforms and other skeleton properties before and after the world transforms of all bones are calculated. See the `IKExample` for a usage example. + +### SFML + +- Added `ikDemo()` in `main.cpp`. to illustrate how to drive a bone and IK chain through mouse movement. + +### UE4 + +- `SpineWidget` now supports the full widget transform, including rendering scale/shear. +- Materials on `SkeletonRendererComponent` are now blueprint read and writeable. This allows setting dynamic material instances at runtime. +- Added `InitialSkin` property to `USpineWidget`. This allows previewing different skins in the UMG Designer. Initial skins can still be overridden via blueprint events such as `On Initialized`. +- **Breaking change:** `SpineWidget` no longer has the `Scale` property. Instead the size x/y properties can be used. +- Added `SetSlotColor` on `USpineSkeletonComponent` to easily set the color of a slot via blueprints. +- Changed mixes set on an `SkeletonDataAsset` will now be applied to instances of `USpineSkeletonComponent`. +- Generated normals are now correctly flipped for back faces. +- Modifying parent materials updates material instances accordingly. +- Only `.json` files that are actually encoding Spine skeletons will be loaded. Other `.json` files will be left to other importers. +- Updated example project to UE 4.27. + +## C# + +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +- Added support for reverse animation playback via `TrackEntry.Reverse`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. +- **Breaking change:** Removed `SkeletonData` and `Skeleton` methods: `FindBoneIndex`, `FindSlotIndex`. Bones and slots have an `Index` field that should be used instead. Be sure to check for e.g. `bone == null` accordingly before accessing `bone.Index`. + +### Unity + +- **Officially supported Unity versions are 2017.1-2022.1**. +- **Breaking changes** + + - Removed all `Spine.Unity.AttachmentTools.SkinUtilities` Skin extension methods. These have become obsoleted and error-prone since the introduction of the new Skin API in 3.8. To fix any compile errors, replace any usage of `Skin` extension methods with their counterparts, e.g. replace occurrances of `skin.AddAttachments()` with `skin.AddSkin()`. Please see the example scene `Mix and Match Skins` on how to use the new Skin API to combine skins, or the updated old example scenes `Mix and Match` and `Mix and Match Equip` on how you can update an existing project using the old workflow. If you are using `skeletonAnimation.Skeleton.UnshareSkin()` in your code, you can replace it with `Skin customSkin = new Skin("custom skin"); customSkin.AddSkin(skeletonAnimation.Skeleton.Skin);`. + - `Skin.GetAttachments()` has been replaced by `Skin.Attachments`, returning an `ICollection`. This makes access more consistent and intuitive. To fix any compile errors, replace any occurrances of `Skin.GetAttachments()` by `Skin.Attachments`. + - Removed redundant `Spine.Unity.AttachmentTools.AttachmentCloneExtensions` extension methods `Attachment.GetCopy()` and `Attachment.GetLinkedMesh()`. To fix any compile errors, replace any occurrances with `Attachment.Copy()` and `Attachment.NewLinkedMesh()`. + - Removed `Spine.Unity.AttachmentTools.AttachmentRegionExtensions` extension methods `Attachment.GetRegion()`. Use `Attachment.RendererObject as AtlasRegion` instead. + - Removed redundant `Spine.SkeletonExtensions` extension methods: + Replace: + + - `Skeleton.SetPropertyToSetupPose()` + - `Skeleton.SetDrawOrderToSetupPose()` + - `Skeleton.SetSlotAttachmentsToSetupPose()` + - `Skeleton.SetSlotAttachmentToSetupPose()` + + with `Skeleton.SetSlotsToSetupPose()`. + Replace: + + - `Slot.SetColorToSetupPose()` + - `Slot.SetAttachmentToSetupPose()` + + with `Slot.SetToSetupPose()`. + + Also removed less commonly used extension methods: + `TrackEntry.AllowImmediateQueue()`, `Animation.SetKeyedItemsToSetupPose()` and `Attachment.IsRenderable()`. + + - **`SkeletonGraphic` now no longer uses a `RawImage` component at each submesh renderer** GameObject when `allowMultipleCanvasRenderers` is true. Instead, a new custom component `SkeletonSubmeshGraphic` is used which is more resource friendly. Replacement of these components will be performed automatically through editor scripting, saving scenes or prefabs will persist the upgrade. + - **Linear color space:** Previously Slot colors were not displayed the same in Unity as in the Spine Editor. This is now fixed at all shaders, including URP and LWRP shaders. See section _Additions_ below for more details. If you have tweaked Slot colors to look correct in `Linear` color space in Unity but incorrect in Spine, you might want to adjust the tweaked colors. Slot colors displayed in Unity should now match colors displayed in the Spine Editor when configured to display as `Linear` color space in the Spine Editor Settings. + - **Additive Slots have always been lit** before they were written to the target buffer. Now all lit shaders provide an additional parameter `Light Affects Additive` which defaults to `false`, as it is the more intuitive default value. You can enable the old behaviour by setting this parameter to `true`. + - **Corrected blending behaviour of all `Sprite` shaders** in `Premultiply Alpha` blend mode (including URP and LWRP packages). Previously vertex color alpha was premultiplied again, even though `Premultiply Alpha` blend mode assumes PMA texture and PMA vertex color input. Slot-alpha blending will thus be correctly lighter after upgrading to 4.0. If you have compensated this problem by disabling `Advanced - PMA Vertex Colors` you can now re-enable this parameter, also allowing for rendering Additive slots in a single pass. + - **Corrected all `Outline` shaders outline thickness** when `Advanced - Sample 8 Neighbourhood` is disabled (thus using `4 Neighbourhood`). Previously weighting was incorrectly thick (4x as thick) compared to 8 neighbourhood, now it is more consistent. This might require adjustment of all your outline materials where `Sample 8 Neighbourhood` is disabled to restore the previous outline thickness, by adjusting the `Outline Threshold` parameter through adding a `/4` to make the threshold 4 times smaller. + - Reverted changes: `BoneFollower` property `followLocalScale` has intermediately been renamed to `followScale` but was renamed back to `followLocalScale`. Serialized values (scenes and prefabs) will automatically be upgraded, only code accessing `followScale` needs to be adapted. + - Fixed Timeline not pausing (and resuming) clip playback on Director pause, this is now the default behaviour. If you require the old behaviour (e.g. to continue playing an idle animation during Director pause), there is now an additional parameter `Don't Pause with Director` provided that can be enabled for each Timeline clip. + - Fixed Timeline `Spine AnimationState Clips` ignoring empty space on the Timeline after a clip's end. Timeline clips now also offer `Don't End with Clip` and `Clip End Mix Out Duration` parameters if you prefer the old behaviour of previous versions. By default when empty space follows the clip on the timeline, the empty animation is set on the track with a MixDuration of `Clip End Mix Out Duration`. Set `Don't End with Clip` to `true` to continue playing the clip's animation instead and mimic the old 3.8 behaviour. If you prefer pausing the animation instead of mixing out to the empty animation, set `Clip End Mix Out Duration` to a value less than 0, then the animation is paused instead. + +- **Additions and Improvements** + + - Additional **Fix Draw Order** parameter at SkeletonRenderer, defaults to `disabled` (previous behaviour). + Applies only when 3+ submeshes are used (2+ materials with alternating order, e.g. "A B A"). + If `true`, MaterialPropertyBlocks are assigned at each material to prevent aggressive batching of submeshes + by e.g. the LWRP renderer, leading to incorrect draw order (e.g. "A1 B A2" changed to "A1A2 B"). + You can leave this parameter disabled when everything is drawn correctly to save the additional performance cost. + - **Additional Timeline features.** SpineAnimationStateClip now provides a `Speed Multiplier`, a start time offset parameter `Clip In`, support for blending successive animations by overlapping tracks. An additional `Use Blend Duration` parameter _(defaults to true)_ allows for automatic synchronisation of MixDuration with the current overlap blend duration. An additional Spine preferences parameter `Use Blend Duration` has been added which can be disabled to default to the previous behaviour before this update. + - Additional `SpriteMask and RectMask2D` example scene added for demonstration of mask setup and interaction. + - `Real physics hinge chains` for both 2D and 3D physics. The [SkeletonUtilityBone](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) Inspector provides an interface to create 2D and 3D hinge chains. Previously created chains have only been respecting gravity, but not momentum of the skeleton or parent bones. The new physics rig created when pressing `Create 3D Hinge Chain` and `Create 2D Hinge Chain` creates a more complex setup that also works when flipping the skeleton. Note that the chain root node is no longer parented to bones of the skeleton. This is a requirement in Unity to have momentum applied properly - do not reparent the chain root to bones of your skeleton, or you will loose any momentum applied by the skeleton's movement. + - `Outline rendering functionality for all shaders.` Every shader now provides an additional set of `Outline` parameters to enable custom outline rendering. When outline rendering is enabled via the `Material` inspector, it automatically switches the shader to the respective `Spine/Outline` shader variant. Outlines are generated by sampling neighbour pixels, so be sure to add enough transparent padding when exporting your atlas textures to fit the desired outline width. In order to enable outline rendering at a skeleton, it is recommended to first prepare an additional outline material copy and then switch the material of the target skeleton to this material. This prevents unnecessary additional runtime material copies and drawcalls. Material switching can be prepared via a [SkeletonRendererCustomMaterials](http://esotericsoftware.com/spine-unity#SkeletonRendererCustomMaterials) component and then enabled or disabled at runtime. Alternatively, you can also directly modify the `SkeletonRenderer.CustomMaterialOverride` property. + Outline rendering is fully supported on `SkeletonGraphic` shaders as well. + - Added `SkeletonRenderer.EditorSkipSkinSync` scripting API property to be able to set custom skins in editor scripts. Enable this property when overwriting the Skeleton's skin from an editor script. Without setting this parameter, changes will be overwritten by the next inspector update. Only affects Inspector synchronisation of skin with `initialSkinName`, not startup initialization. + - `AtlasUtilities.GetRepackedAttachments()` and `AtlasUtilities.GetRepackedSkin()` provide support for additional texture channels such as normal maps via the optional parameter `additionalTexturePropertyIDsToCopy `. See the spine-unity runtime documentation, section [Combining Skins - Advanced - Runtime Repacking with Normalmaps](http://esotericsoftware.com/spine-unity#Combining-Skins) for further info and example usage code. + - `BoneFollower` can now optionally follow (uniform) world scale of the reference bone. There is now a `Mode` dropdown selector in the Inspector which can be set to either `Local` or `World Uniform`. + - All `Spine/SkeletonGraphic` shaders now provide a parameter `CanvasGroup Compatible` which can be enabled to support `CanvasGroup` alpha blending. For correct results, you should then disable `Pma Vertex Colors` in the `SkeletonGraphic` Inspector, in section `Advanced` (otherwise Slot alpha will be applied twice). + - **Now supporting Universal Render Pipeline (URP), including the 2D Renderer pipeline, through an additional UPM package.** + + - **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + + - a) the `Packages` directory in your project where it will automatically be loaded, or + - b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + The Project panel should now show an entry `Spine Universal RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + + - **Usage:** The package provides two shaders specifically built for the universal render pipeline: + - `Universal Render Pipeline/Spine/Skeleton`, as a universal variant of the `Spine/Skeleton` shader, + - `Universal Render Pipeline/Spine/Skeleton Lit`, as a universal variant of the `Spine/Skeleton Lit` shader, + - `Universal Render Pipeline/Spine/Sprite`, as a universal variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the universal render pipeline, + - `Universal Render Pipeline/2D/Spine/Skeleton Lit`, as a universal 2D Renderer variant of the `Spine/Skeleton Lit` shader, and + - `Universal Render Pipeline/2D/Spine/Sprite`, as a universal 2D Renderer variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders. + The shaders can be assigned to materials as usual and will respect your settings of the assigned `UniversalRenderPipelineAsset` under `Project Settings - Graphics`. + - **Restrictions** As all Spine shaders, the URP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + - **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.urp-shaders-3.8/Examples/URP Shaders.unity` that demonstrates usage of the URP shaders. + + - Spine Preferences now provide an **`Atlas Texture Settings`** parameter for applying customizable texture import settings at all newly imported Spine atlas textures. + When exporting atlas textures from Spine with `Premultiply alpha` enabled (the default), you can leave it at `PMATexturePreset`. If you have disabled `Premultiply alpha`, set it to the included `StraightAlphaTexturePreset` asset. You can also create your own `TextureImporter` `Preset` asset and assign it here (include `PMA` or `Straight` in the name). In Unity versions before 2018.3 you can use `Texture2D` template assets instead of the newer `Preset` assets. Materials created for imported textures will also have the `Straight Alpha Texture` parameter configured accordingly. + - All `Sprite` shaders (including URP and LWRP extension packages) now provide an additional `Fixed Normal Space` option `World-Space`. PReviously options were limited to `View-Space` and `Model-Space`. + - `SkeletonGraphic` now fully supports [`SkeletonUtility`](http://esotericsoftware.com/spine-unity#SkeletonUtility) for generating a hierarchy of [`SkeletonUtilityBones`](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) in both modes `Follow` and `Override`. This also enables creating hinge chain physics rigs and using `SkeletonUtilityConstraints` such as `SkeletonUtilityGroundConstraint` and `SkeletonUtilityEyeConstraint` on `SkeletonGraphic`. + - Added **native support for slot blend modes** `Additive`, `Multiply` and `Screen` with automatic assignment at newly imported skeleton assets. `BlendModeMaterialAssets` are now obsolete and replaced by the native properties at `SkeletonDataAsset`. The `SkeletonDataAsset` Inspector provides a new `Blend Modes - Upgrade` button to upgrade an obsolete `BlendModeMaterialAsset` to the native blend modes properties. This upgrade will be performed automatically on imported and re-imported assets. + - `BoneFollower` and `BoneFollowerGraphic` components now provide better support for following bones when the skeleton's Transform is not the parent of the follower's Transform. Previously e.g. rotating a common parent Transform did not lead to the desired result, as well as negatively scaling a skeleton's Transform when it is not a parent of the follower's Transform. + - **Linear color space:** Previously Slot colors were not displayed the same in Unity as in the Spine Editor (when configured to display as `Linear` color space in Spine Editor Settings). This is now fixed at all shaders, including URP and LWRP shaders. + - All Spine shaders (also including URP and LWRP shaders) now support `PMA Vertex Colors` in combination with `Linear` color space. Thus when using Spine shaders, you should always enable `PMA Vertex Colors` at the `SkeletonRenderer` component. This allows using single pass `Additive` Slots rendering. Note that textures shall still be exported as `Straight alpha` when using `Linear` color space, so combine `PMA Vertex Colors` with `Straight Texture`. All `Sprite` shaders now provide an additional blend mode for this, named `PMA Vertex, Straight Texture` which shall be the preferred Sprite shader blend mode in `Linear` color space. + - Additive Slots have always been lit before they were written to the target buffer. Now all lit shaders provide an additional parameter `Light Affects Additive` which defaults to `false`, as it is the more intuitive default value. You can enable the old behaviour by setting this parameter to `true`. + - `SkeletonRootMotion` and `SkeletonMecanimRootMotion` components now support arbitrary bones in the hierarchy as `Root Motion Bone`. Previously there were problems when selecting a non-root bone as `Root Motion Bone`. `Skeleton.ScaleX` and `.ScaleY` and parent bone scale is now respected as well. + - URP and LWRP `Sprite` and `SkeletonLit` shaders no longer require `Advanced - Add Normals` enabled to properly cast and receive shadows. It is recommended to disable `Add Normals` if normals are otherwise not needed. + - Added an example component `RootMotionDeltaCompensation` located in `Spine Examples/Scripts/Sample Components` which can be used for applying simple delta compensation. You can enable and disable the component to toggle delta compensation of the currently playing animation on and off. + - `SkeletonRagdoll` and `SkeletonRagdoll2D` now support bone scale at any bone in the skeleton hierarchy. This includes negative scale and root bone scale. + - `Attachment.GetRemappedClone(Sprite)` method now provides an additional optional parameter `useOriginalRegionScale`. When set to `true`, the replaced attachment's scale is used instead of the Sprite's `Pixel per Unity` setting, allowing for more consistent scaling. _Note:_ When remapping Sprites, be sure to set the Sprite's `Mesh Type` to `Full Rect` and not `Tight`, otherwise the scale will be wrong. + - `SkeletonGraphic` now **supports all Slot blend modes** when `Advanced - Multiple Canvas Renderers` is enabled in the Inspector. The `SkeletonGraphic` Inspector now provides a `Blend Mode Materials` section where you can assign `SkeletonGraphic` materials for each blend mode, or use the new default materials. New `SkeletonGraphic` shaders and materials have been added for each blend mode. The `BlendModes.unity` example scene has been extended to demonstrate this new feature. For detailed information see the [`SkeletonGraphic documentation page`](http://esotericsoftware.com/spine-unity#Parameters). + - Timeline clips now also offer `Don't End with Clip` and `Clip End Mix Out Duration` parameters. By default when empty space follows the clip on the timeline, the empty animation is set on the track with a MixDuration of `Clip End Mix Out Duration`. Set `Don't End with Clip` to `true` to continue playing the clip's animation instead and mimic the old 3.8 behaviour. If you prefer pausing the animation instead of mixing out to the empty animation, set `Clip End Mix Out Duration` to a value less than 0, then the animation is paused instead. + - Prefabs containing `SkeletonRenderer`, `SkeletonAnimation` and `SkeletonMecanim` now provide a proper Editor preview, including the preview thumbnail. + - `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`) now provide a property `Advanced - Fix Prefab Override MeshFilter`, which when enabled fixes the prefab always being marked as changed. It sets the MeshFilter's hide flags to `DontSaveInEditor`. Unfortunately this comes at the cost of references to the `MeshFilter` by other components being lost, therefore this parameter defaults to `false` to keep the safe existing behaviour. + - `BoundingBoxFollower` and `BoundingBoxFollowerGraphic` now provide previously missing `usedByEffector` and `usedByComposite` parameters to be set at all generated colliders. + - `BoneFollower` and `BoneFollowerGraphic` now provide an additional `Follow Parent World Scale` parameter to allow following simple scale of parent bones (rotated/skewed scale can't be supported). + - Improved `Advanced - Fix Prefab Override MeshFilter` property for `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`), now providing an additional option to use a global value which can be set in `Edit - Preferences - Spine`. + - Timeline naming improvements: `Spine AnimationState Clip` Inspector parameter `Custom Duration` changed and inverted to `Default Mix Duration` for more clarity. Shortened all Timeline add track menu entries from: `Spine.Unity.Playables - ` to `Spine - `, `Spine Animation State Track` to `SkeletonAnimation Track`, `Spine AnimationState Graphic Track` to `SkeletonGraphic Track`, and `Spine Skeleton Flip Track` to `Skeleton Flip Track`. + - Timeline track appearance and Inspector: Tracks now show icons and track colors to make them easier to distinguish. When a Track is selected, the Inspector now shows an editable track name which was previously only editable at the Timeline asset. + - Added example component `SkeletonRenderTexture` to render a `SkeletonRenderer` to a `RenderTexture`, mainly for proper transparency. Added an example scene named `RenderTexture FadeOut Transparency` that demonstrates usage for a fadeout transparency effect. + - Added another fadeout example component named `SkeletonRenderTextureFadeout` which takes over transparency fadeout when enabled. You can use this component as-is, attach it in disabled state and enable it to start a fadeout effect. + - Timeline clips now offer an additional `Alpha` parameter for setting a custom constant mix alpha value other than 1.0, just as `TrackEntry.Alpha`. Defaults to 1.0. + - `SkeletonGraphic` now provides additional render callback delegates `OnInstructionsPrepared`, `AssignMeshOverrideSingleRenderer` and `AssignMeshOverrideMultipleRenderers`. `OnInstructionsPrepared` is raised at the end of LateUpdate after render instructions are done, target renderers are prepared, and the mesh is ready to be generated. The two `AssignMeshOverride` delegates allow separate code to take over mesh and material assignment of a `SkeletonGraphic` component. + - Added example component `SkeletonGraphicRenderTexture` to render a `SkeletonGraphic` to a `RenderTexture` (similar as `SkeletonRenderTexture`), mainly for proper transparency. Extended example scene `RenderTexture FadeOut Transparency` accordingly. + +- **Changes of default values** + +- **Deprecated** + +- **Restructuring (Non-Breaking)** + +### XNA/MonoGame + +- Added normalmap support via `SpineEffectNormalmap` and support for loading multiple texture layers following a suffix-pattern. Please see the example code on how to use them. +- Added `Z` property to `SkeletonRenderer` to provide a constant Z offset that's added to all vertices. +- Added `ZSpacing` property to `SkeletonRenderer` to allow specifying the distance on the z-axis between attachments. +- SkeletonDebugRenderer bone color attributes are now public and modifiable by user. + +## Java + +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `Region.names` and `Region.values`. +- Added support for reverse animation playback via `TrackEntry.getReverse()` and `TrackEntry.setReverse()`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. +- **Breaking change:** Removed `SkeletonData` and `Skeleton` methods: `findBoneIndex`, `findSlotIndex`. Bones and slots have an `index` field that should be used instead. + +### libGDX + +- Exposed colors in `SkeletonRendererDebug`. +- Updated to libGDX 1.10.0. + +## Lua + +- Expose non-essential colors on bones, bounding box, clipping, and path attachments. +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +- Added support for reverse animation playback via `TrackEntry.reverse`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. + +### Love2D + +### Corona + +- **Breaking change:** spine-corona has been renamed to spine-solar2d. Change your `require "spine-corona.spine"` statements to `require "spine-solar2d.spine"` + +## Typescript/Javascript + +- **Breaking change:** refactored to ECMAScript modules. See this [blog post](http://esotericsoftware.com/blog/spine-goes-npm) as well as the updated [README.md](spine-ts/README.md). +- **Breaking change:** the `build/` folder and compiled artifacts are no longer part of the repository. Instead, `npm run build` in `spine-ts/` to generate ECMAScript modules and IIFE modules in `spine-/dist`. +- **Breaking change:** the `.npmignore` and `package.json` files in the root directory have been deleted. Use the corresponding files in `spine-ts/` instead, or better, depend on the packages from the NPM registry. +- Updated runtime to be compatible with TypeScript 3.6.3. +- Added `AssetManager#setRawDataURI(path, data)`. Allows to set raw data URIs for a specific path, which in turn enables embedding assets into JavaScript/HTML. +- Expose non-essential colors on bones, bounding box, clipping, and path attachments. +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +- Added support for reverse animation playback via `TrackEntry.reverse`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. +- `AssetManager` constructor now takes an option `Downloader` instance. Used to download assets only once and share them between `AssetManager` instances. +- Added web worker support to `AssetManager`. +- Added various default parameters to `AnimationState` methods for ease of use. +- Added `SpineCanvas`, a simpler way to render a scene via spine-webgl. See `spine-ts/spine-webgl/examples/barebones.html` and `spine-ts/spine-webgl/examples/mix-and-match.html`. + +### WebGL backend + +- **Breaking change:** removed `SharedAssetManager`. Use `AssetManager` with a shared `Downloader` instance instead. +- **Breaking change:** the global object `spine.webgl` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.webgl.` in your source code with `spine.`. + +### Canvas backend + +- Renderer now accounts for whitespace stripping. +- **Breaking change:** the global object `spine.canvas` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.canvas.` in your source code with `spine.`. + +### Three.js backend + +- `SkeletonMesh` now takes an optional `SkeletonMeshMaterialParametersCustomizer` function that allows you to modify the `ShaderMaterialParameters` before the material is finalized. Use it to modify things like THREEJS' `Material.depthTest` etc. See #1590. +- **Breaking change:** the global object `spine.canvas` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.threejs.` in your source code with `spine.`. +- **Breaking change:** the default fragment shader of `SkeletonMeshMaterial` now explicitely discards fragments with alpha < 0.5. See https://github.com/EsotericSoftware/spine-runtimes/issues/1985 +- **Breaking change:** reversal of the previous breaking change: the default fragment shader of `SkeletonMeshMaterial` does no longer discard fragments with alpha < 0.5. Pass a `SkeletonMeshMaterialParametersCustomizer` to the `SkeletonMesh` constructor, and modify `parameters.alphaTest` to be > 0. + +### Player + +- Added `SpinePlayerConfig.rawDataURIs`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. See the example for a demonstration. +- Added `SpinePlayerConfig.frame`. If set, the callback is called each frame, before the skeleton is posed or drawn. +- Added `SpinePlayerConfig.update`. If set, the callback is called each frame, just after the skeleton is posed. +- Added `SpinePlayerConfig.draw`. If set, the callback is called each frame, just after the skeleton is drawn. +- Added `SpinePlayerConfig.downloader`. The `spine.Downloader` instance can be shared between players so assets are only downloaded once. +- If `SpinePlayerConfig.jsonURL` ends with an anchor, the anchor text is used to find the skeleton in the specified JSON file. +- Added `SpinePlayer.dispose()`, disposes all CPU and GPU side resources, removes all listeners, and removes the player DOM from the parent. + +# 3.8 + +## AS3 + +- **Breaking changes** + + - Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + - Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + - Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + - Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + - Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. + +- **Additions** + - Added `SkeletonBinary` to load binary `.skel` files. See `MixAndMatchExample.as` in `spine-startling-example`. + - Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `Skin#getAttachments()`. Returns all attachments in the skin. + - Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + - Added `Skin#addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `Skin#copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + +### Starling + +- Added `MixAndMatchExample.as` to demonstrate the new Skin API additions and how to load binary `.skel` files. +- Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. + +## C + +- **Breaking changes** + + - Renamed `spSlot#attachmentVertices` to `spSlot#deform`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `spSkin_addAttachment()` to `Skin#spSkin_addAttachment()`. + - Removed `spVertexAttachment_applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `spDeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `inheritDeform` field, getter, and setter from `spMeshAttachment`. + - Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + - Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +- **Additions** + - Added `x` and `y` coordinates for setup pose AABB in `spSkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `spSkin_getAttachments()`. Returns all attachments in the skin. + - Added `spSkin_getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + - Added `spSkin_addSkin(spSkin* skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `spSkin_copySkin(spSkin* skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `spVertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - All attachments inserted into skins are reference counted. When the last skin referencing an attachment is disposed, the attachment will also be disposed. + - Added `spAttachment_copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `spMeshAttachment_newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + +### Cocos2d-Objc + +- Added mix-and-match example to demonstrate the new Skin API. +- Added `IKExample`. +- Added `SkeletonAnimation preUpdateWorldTransformsListener` and `SkeletonAnimation postUpdateWorldTransformsListener`. When set, these callbacks will be invokved before and after the skeleton's `updateWorldTransforms()` method is called. See the `IKExample` how it can be used. + +### SFML + +- Added mix-and-match example to demonstrate the new Skin API. +- Added `IKExample`. + +## C++ + +- **Breaking Changes** + + - Renamed `Slot::getAttachmentVertices()` to `Slot::getDeform()`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `Skin::addAttachment()` to `Skin::setAttachment()`. + - Removed `VertexAttachment::applyDeform()` and replaced it with `VertexAttachment::getDeformAttachment()`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `_inheritDeform` field, getter, and setter from `MeshAttachment`. + - Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + - Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +- **Additions** + - `AnimationState` and `TrackEntry` now also accept a subclass of `AnimationStateListenerObject` as a listener for animation events in the overloaded `setListener()` method. + - `SkeletonBinary` and `SkeletonJson` now parse and set all non-essential data like audio path. + - Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `Skin#getAttachments()`. Returns all attachments in the skin. + - Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + - Added `Skin#addSkin(Skin &skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `Skin#copySkin(Skin &skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - All attachments inserted into skins are reference counted. When the last skin referencing an attachment is disposed, the attachment will also be disposed. + - Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + - Exposed `x` and `y` on `SkeletonData` through getters and setters. + +### Cocos2d-x + +- Updated to cocos2d-x 3.17.1 +- Added mix-and-match example to demonstrate the new Skin API. +- Exmaple project requires Visual Studio 2019 on Windows +- Added `IKExample`. +- Added `SkeletonAnimation::setPreUpdateWorldTransformsListener()` and `SkeletonAnimation::setPreUpdateWorldTransformsListener()`. When set, these callbacks will be invokved before and after the skeleton's `updateWorldTransforms()` method is called. See the `IKExample` how it can be used. + +### SFML + +- Added mix-and-match example to demonstrate the new Skin API. + +### UE4 + +- Added `bAutoPlaying` flag to `USpineSkeletonAnimationComponent`. When `false`, the component will not update the internal animation state and skeleton. +- Updated example project to UE 4.22. +- (Re-)Importing Spine assets will perform a version compatibility check and alert users about mismatches in editor mode. +- `USpineSkeletonRendererComponent` allows passing a `USpineSkeletonComponent` to update it. This way, the renderer component can be used without a skeleton component on the same actor. +- Added blueprint-callable methods to `SpineSkeletonComponent` and `SpineSkeletonAnimationComponent` to query and set skins, and enumerate bones, slots, and animations. +- Extended skeleton data editor preview. The preview now shows bones, slots, animations, and skins found in the skeleton data. See this [blog post](http://esotericsoftware.com/blog/Unreal-Engine-4-quality-of-life-improvements). +- Added preview animation and skin fields, allowing you to preview animations and skins right in the editor. See this [blog post](http://esotericsoftware.com/blog/Unreal-Engine-4-quality-of-life-improvements). +- Removed dependency on `RHI`, `RenderCore`, and `ShaderCore`. +- Re-importing atlases and their textures now works consistently in all situations. +- Added mix-and-match example to demonstrate the new Skin API. +- Materials on `SkeletonRendererComponent` are now blueprint read and writeable. This allows setting dynamic material instances at runtime. +- Added `InitialSkin` property to `USpineWidget`. This allows previewing different skins in the UMG Designer. Initial skins can still be overridden via blueprint events such as `On Initialized`. +- `USpineWidget` will now report its own desired size based on the setup pose dimensions of the skeleton. This is used when selecting `Size to content` on a `USpineWidget` in the designer. +- Updated example project to UE 5.2. + +## C# + +- **Breaking changes** + + - **Changed `IkConstraintData.Bones` type from `List` to `ExposedList`** for unification reasons. _Note: this modification will most likely not affect user code._ + - Renamed `Slot.AttachmentVertices` to `Slot.Deform`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `Skin.AddAttachment()` to `Skin.SetAttachment()`. + - Removed `FindAttachmentsForSlot(int slotIndex, List attachments)` and `FindNamesForSlot (int slotIndex, List names)` and replaced it with `Skin.GetAttachments(int slotIndex, List attachments)` which returns the combined `SkinEntry` object holding both name and attachment. + - Removed `VertexAttachment.ApplyDeform()` and replaced it with `VertexAttachment.DeformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + - Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + - Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +- **Additions** + - Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `Skin.GetAttachments()`. Returns all attachments in the skin. + - Added `Skin.GetAttachments(int slotIndex, List attachments)`. Returns all attachements in the skin for the given slot index. This method replaces `FindAttachmentsForSlot` and `FindNamesForSlot`. + - Added `Skin.AddSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `Skin.CopySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - Added `Attachment.Copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `MeshAttachment.NewLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + +### Unity + +- **Breaking changes** + + - **Officially supported Unity versions are 2017.1-2020.2**. + - **Spine `.asmdef` files are again active by default**. They have previously been deactivated to `.txt` extension which is now no longer necessary. + - **Removed PoseSkeleton() and PoseWithAnimation()** extension methods to prevent issues where animations are not mixed out. Problem was that these methods did not set AnimationState, leaving incorrect state at e.g. attachments enabled at slots when starting subsequent animations. As a replacement you can use `AnimationState.ClearTrack(0);` followed by `var entry = AnimationState.SetAnimation(0, animation, loop); entry.TrackTime = time` to achieve similar behaviour. + - **The `Shadow alpha cutoff` shader parameter is now respecting slot-color alpha** values at all Spine shaders. A fragment's texture color alpha is multiplied with slot-color alpha before the result is tested against the `Shadow alpha cutoff` threshold. + - **Removed redundant `Attachment.GetClone()` and `MeshAttachment.GetLinkedClone()` extension methods**. Use methods `Attachment.Copy` and `MeshAttachment.NewLinkedMesh()` instead. + - **Renamed extension method `Attachment.GetClone(bool cloneMeshesAsLinked)` to `Attachment.GetCopy(bool cloneMeshesAsLinked)`** to follow the naming scheme of the Spine API. + - `SkeletonDataAsset.atlasAssets` is now an array of the base class `AtlasAssetBase` instead of `SpineAtlasAsset`, which provides `IEnumerable<> Materials` instead of `List<> materials`. Replace any access via `atlasAsset.materials[0]` with `atlasAsset.Materials.First()` and add a `using System.Linq;` statement. + - **Changed `MeshAttachment.GetLinkedMesh()` method signatures:** removed optional parameters `bool inheritDeform = true, bool copyOriginalProperties = false`. + - Changed namespace `Spine.Unity.Modules` to `Spine.Unity` and `Spine.Unity.Examples` after restructuring (see section below) in respective classes: + - When receiving namespace related errors, replace using statements of `using Spine.Unity.Modules.AttachmentTools;` with `using Spine.Unity.AttachmentTools;`. You can remove `using Spine.Unity.Modules;` statements when a `using Spine.Unity` statement is already present in the file. + - `AttachmentTools`, `SkeletonPartsRenderer`, `SkeletonRenderSeparator`, `SkeletonRendererCustomMaterials` changed to namespace `Spine.Unity`. + - `SkeletonGhost`, `SkeletonGhostRenderer`, `AtlasRegionAttacher`, `SkeletonGraphicMirror`, `SkeletonRagdoll`, `SkeletonRagdoll2D`, `SkeletonUtilityEyeConstraint`, `SkeletonUtilityGroundConstraint`, `SkeletonUtilityKinematicShadow` changed to namespace `Spine.Unity.Examples`. + - Split `Editor/Utility/SpineEditorUtilities` class into multiple files with partial class qualifier. + - Nested classes `SpineEditorUtilities.AssetUtility` and `SpineEditorUtilities.EditorInstantiation` are now no longer nested. If you receive namespace related errors, replace any occurrance of + - `SpineEditorUtilities.AssetUtility` with `AssetUtility` and + - `SpineEditorUtilities.EditorInstantiation` with `EditorInstantiation`. + - **Timeline Support has been moved to a separate UPM Package** Previously the Spine Timeline integration was located in the `Modules/Timeline` directory and was deactivated by default, making it necessary to activate it via the Spine Preferences. Now the Timeline integration has been moved to an additional UPM package which can be found under `Modules/com.esotericsoftware.spine.timeline`. + - **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + a) the `Packages` directory in your project where it will automatically be loaded, or + b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + The Project panel should now show an entry `Spine Timeline Extensions` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + - `SkeletonMecanim`'s `Layer Mix Mode` enum name `MixMode.SpineStyle` has been renamed to `MixMode.Hard`. This is most likely not set via code and thus unlikely to be a problem. Serialized scenes and prefabs are unaffected. + - `SkeletonRootMotion` and `SkeletonMecanimRootMotion` components now support arbitrary bones in the hierarchy as `Root Motion Bone`. Previously there were problems when selecting a non-root bone as `Root Motion Bone`. `Skeleton.ScaleX` and `.ScaleY` and parent bone scale is now respected as well. + +- **Additions** + + - **Spine Preferences stored in Assets/Editor/SpineSettings.asset** Now Spine uses the new `SettingsProvider` API, storing settings in a SpineSettings.asset file which can be shared with team members. Your old preferences are automatically migrated to the new system. + - Added support for Unity's SpriteMask to `SkeletonAnimation` and `SkeletonMecanim`. All mask interaction modes are supported. See this [blog post](http://esotericsoftware.com/blog/Unity-SpriteMask-and-RectMask2D-support). + - Added support for Unity's RectMask2D to SkeletonGraphics. See this [blog post](http://esotericsoftware.com/blog/Unity-SpriteMask-and-RectMask2D-support). + - Added `Create 2D Hinge Chain` button at `SkeletonUtilityBone` inspector, previously only `Create 3D Hinge Chain` was available. + - **Now supporting Lightweight Render Pipeline (LWRP) through an additional UPM package.** + + - **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + + - a) the `Packages` directory in your project where it will automatically be loaded, or + - b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + > If you are using git and Unity 2019.2 or newer versions and receive an error that dependencies could not be resolved by the package manager (only higher versions of Unity's `Lightweight RP` package are available, e.g. `6.9.0` and up), please copy the prepared package-UNITYVERSION.json file for your Unity version (e.g. `package-2019.2.json`) over the existing package.json file to change the dependency accordingly. Unfortunately Unity's Package Manager does not provide a way to specify a version range for a dependency like "5.7.2 - 6.9.0" yet, so this manual step is necessary for git users. + + The Project panel should now show an entry `Spine Lightweight RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + + - **Usage:** The package provides two shaders specifically built for the lightweight render pipeline: + - `Lightweight Render Pipeline/Spine/Skeleton`, as a lightweight variant of the `Spine/Skeleton` shader, + - `Lightweight Render Pipeline/Spine/Skeleton Lit`, as a lightweight variant of the `Spine/Skeleton Lit` shader and + - `Lightweight Render Pipeline/Spine/Sprite`, as a lightweight variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the lightweight render pipeline. The shaders can be assigned to materials as usual and will respect your settings of the assigned `LightweightRenderPipelineAsset` under `Project Settings - Graphics`. + - **Restrictions** As all Spine shaders, the LWRP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + - **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.lwrp-shaders-3.8/Examples/LWRP Shaders.unity` that demonstrates usage of the LWRP shaders. + + - Added `Spine/Skeleton Lit ZWrite` shader. This variant of the `Spine/Skeleton Lit` shader writes to the depth buffer with configurable depth alpha threshold. Apart from that it is identical to `Spine/Skeleton Lit`. + - Additional yield instructions to wait for animation track events `End`, `Complete` and `Interrupt`. + - `WaitForSpineAnimationComplete` now proves an additional `bool includeEndEvent` parameter, defaults to `false` (previous behaviour). + - Added a new `WaitForSpineAnimationEnd` yield instruction. + - Added a new generic `WaitForSpineAnimation` yield instruction which can be configured to wait for any combination of animation track events. It is now used as base class for `WaitForSpineAnimationComplete` and `WaitForSpineAnimationEnd`. + - Additional **Fix Draw Order** parameter at SkeletonRenderer, defaults to `disabled` (previous behaviour). + Applies only when 3+ submeshes are used (2+ materials with alternating order, e.g. "A B A"). + If true, MaterialPropertyBlocks are assigned at each material to prevent aggressive batching of submeshes + by e.g. the LWRP renderer, leading to incorrect draw order (e.g. "A1 B A2" changed to "A1A2 B"). + You can leave this parameter disabled when everything is drawn correctly to save the additional performance cost. + - **Additional Timeline features.** SpineAnimationStateClip now provides a `Speed Multiplier`, a start time offset parameter `Clip In`, support for blending successive animations by overlapping tracks. An additional `Use Blend Duration` parameter _(defaults to true)_ allows for automatic synchronisation of MixDuration with the current overlap blend duration. An additional Spine preferences parameter `Use Blend Duration` has been added which can be disabled to default to the previous behaviour before this update. + - Additional `SpriteMask and RectMask2D` example scene added for demonstration of mask setup and interaction. + - `Real physics hinge chains` for both 2D and 3D physics. The [SkeletonUtilityBone](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) Inspector provides an interface to create 2D and 3D hinge chains. Previously created chains have only been respecting gravity, but not momentum of the skeleton or parent bones. The new physics rig created when pressing `Create 3D Hinge Chain` and `Create 2D Hinge Chain` creates a more complex setup that also works when flipping the skeleton. Note that the chain root node is no longer parented to bones of the skeleton. This is a requirement in Unity to have momentum applied properly - do not reparent the chain root to bones of your skeleton, or you will loose any momentum applied by the skeleton's movement. + - `Outline rendering functionality for all shaders.` Every shader now provides an additional set of `Outline` parameters to enable custom outline rendering. When outline rendering is enabled via the `Material` inspector, it automatically switches the shader to the respective `Spine/Outline` shader variant. Outlines are generated by sampling neighbour pixels, so be sure to add enough transparent padding when exporting your atlas textures to fit the desired outline width. In order to enable outline rendering at a skeleton, it is recommended to first prepare an additional outline material copy and then switch the material of the target skeleton to this material. This prevents unnecessary additional runtime material copies and drawcalls. Material switching can be prepared via a [SkeletonRendererCustomMaterials](http://esotericsoftware.com/spine-unity#SkeletonRendererCustomMaterials) component and then enabled or disabled at runtime. Alternatively, you can also directly modify the `SkeletonRenderer.CustomMaterialOverride` property. + Outline rendering is fully supported on `SkeletonGraphic` shaders as well. + - Added `SkeletonRenderer.EditorSkipSkinSync` scripting API property to be able to set custom skins in editor scripts. Enable this property when overwriting the Skeleton's skin from an editor script. Without setting this parameter, changes will be overwritten by the next inspector update. Only affects Inspector synchronisation of skin with `initialSkinName`, not startup initialization. + - All `Spine/SkeletonGraphic` shaders now provide a parameter `CanvasGroup Compatible` which can be enabled to support `CanvasGroup` alpha blending. For correct results, you should then disable `Pma Vertex Colors` in the `SkeletonGraphic` Inspector, in section `Advanced` (otherwise Slot alpha will be applied twice). + - **Now supporting Universal Render Pipeline (URP), including the 2D Renderer pipeline, through an additional UPM package.** + + - **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + + - a) the `Packages` directory in your project where it will automatically be loaded, or + - b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + The Project panel should now show an entry `Spine Universal RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + + - **Usage:** The package provides two shaders specifically built for the universal render pipeline: + - `Universal Render Pipeline/Spine/Skeleton`, as a universal variant of the `Spine/Skeleton` shader, + - `Universal Render Pipeline/Spine/Skeleton Lit`, as a universal variant of the `Spine/Skeleton Lit` shader, + - `Universal Render Pipeline/Spine/Sprite`, as a universal variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the universal render pipeline, + - `Universal Render Pipeline/2D/Spine/Skeleton Lit`, as a universal 2D Renderer variant of the `Spine/Skeleton Lit` shader, and + - `Universal Render Pipeline/2D/Spine/Sprite`, as a universal 2D Renderer variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders. + The shaders can be assigned to materials as usual and will respect your settings of the assigned `UniversalRenderPipelineAsset` under `Project Settings - Graphics`. + - **Restrictions** As all Spine shaders, the URP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + - **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.urp-shaders-3.8/Examples/URP Shaders.unity` that demonstrates usage of the URP shaders. + + - Spine Preferences now provide an **`Atlas Texture Settings`** parameter for applying customizable texture import settings at all newly imported Spine atlas textures. + When exporting atlas textures from Spine with `Premultiply alpha` enabled (the default), you can leave it at `PMATexturePreset`. If you have disabled `Premultiply alpha`, set it to the included `StraightAlphaTexturePreset` asset. You can also create your own `TextureImporter` `Preset` asset and assign it here (include `PMA` or `Straight` in the name). In Unity versions before 2018.3 you can use `Texture2D` template assets instead of the newer `Preset` assets. Materials created for imported textures will also have the `Straight Alpha Texture` parameter configured accordingly. + - All `Sprite` shaders (including URP and LWRP extension packages) now provide an additional `Fixed Normal Space` option `World-Space`. PReviously options were limited to `View-Space` and `Model-Space`. + - `SkeletonGraphic` now fully supports [`SkeletonUtility`](http://esotericsoftware.com/spine-unity#SkeletonUtility) for generating a hierarchy of [`SkeletonUtilityBones`](http://esotericsoftware.com/spine-unity#SkeletonUtilityBone) in both modes `Follow` and `Override`. This also enables creating hinge chain physics rigs and using `SkeletonUtilityConstraints` such as `SkeletonUtilityGroundConstraint` and `SkeletonUtilityEyeConstraint` on `SkeletonGraphic`. + - Added `OnMeshAndMaterialsUpdated` callback event to `SkeletonRenderer` and `SkeletonGraphic`. It is issued at the end of `LateUpdate`, before rendering. + - Added `Skeleton-OutlineOnly` single pass shader to LWRP and URP extension modules. It can be assigned to materials as `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly`. This allows for separate outline child _GameObjects_ that reference the existing Mesh of their parent, and re-draw the mesh using this outline shader. + - Added example component `RenderExistingMesh` to render a mesh again with different materials, as required by the new `Skeleton-OutlineOnly` shaders. + In URP the outline has to be rendered via a separate GameObject as URP does not allow multiple render passes. To add an outline to your SkeletenRenderer: + 1. Add a child GameObject and move it a bit back (e.g. position Z = 0.01). + 2. Add a `RenderExistingMesh` component, provided in the `Spine Examples/Scripts/Sample Components` directory. + 3. Copy the original material, add _\_Outline_ to its name and set the shader to `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly`. + 4. Assign this _\_Outline_ material at the `RenderExistingMesh` component under _Replacement Materials_. + - Added `Outline Shaders URP` example scene to URP extension module to demonstrate the above additions. + - Added support for Unity's [`SpriteAtlas`](https://docs.unity3d.com/Manual/class-SpriteAtlas.html) as atlas provider (as an alternative to `.atlas.txt` and `.png` files) alongside a skeleton data file. There is now an additional `Spine SpriteAtlas Import` tool window accessible via `Window - Spine - SpriteAtlas Import`. Additional information can be found in a new section on the [spine-unity documentation page](http://esotericsoftware.com/spine-unity#Advanced---Using-Unity-SpriteAtlas-as-Atlas-Provider). + - Added support for **multiple atlas textures at `SkeletonGraphic`**. You can enable this feature by enabling the parameter `Multiple CanvasRenders` in the `Advanced` section of the `SkeletonGraphic` Inspector. This automatically creates the required number of child `CanvasRenderer` GameObjects for each required draw call (submesh). + - Added support for **Render Separator Slots** at `SkeletonGraphic`. Render separation can be enabled directly in the `Advanced` section of the `SkeletonGraphic` Inspector, it does not require any additional components (like `SkeletonRenderSeparator` or `SkeletonPartsRenderer` for `SkeletonRenderer` components). When enabled, additional separator GameObjects will be created automatically for each separation part, and `CanvasRenderer` GameObjects re-parented to them accordingly. The separator GameObjects can be moved around and re-parented in the hierarchy according to your requirements to achieve the desired draw order within your `Canvas`. A usage example can be found in the updated `Spine Examples/Other Examples/SkeletonRenderSeparator` scene. + - Added `SkeletonGraphicCustomMaterials` component, providing functionality to override materials and textures of a `SkeletonGraphic`, similar to `SkeletonRendererCustomMaterials`. Note: overriding materials or textures per slot is not provided due to structural limitations. + - Added **Root Motion support** for `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic` via new components `SkeletonRootMotion` and `SkeletonMecanimRootMotion`. The `SkeletonAnimation` and `SkeletonGraphic` component Inspector now provides a line `Root Motion` with `Add Component` and `Remove Component` buttons to add/remove the new `SkeletonRootMotion` component to your GameObject. The `SkeletonMecanim` Inspector detects whether root motion is enabled at the `Animator` component and adds a `SkeletonMecanimRootMotion` component automatically. + - `SkeletonMecanim` now provides an additional `Custom MixMode` parameter under `Mecanim Translator`. It is enabled by default in version 3.8 to maintain current behaviour, using the set `Mix Mode` for each Mecanim layer. When disabled, `SkeletonMecanim` will use the recommended `MixMode` according to the layer blend mode. Additional information can be found in the [Mecanim Translator section](http://esotericsoftware.com/spine-unity#Parameters-for-animation-blending-control) on the spine-unity documentation pages. + - Added **SkeletonGraphic Timeline support**. Added supprot for multi-track Timeline preview in the Editor outside of play mode (multi-track scrubbing). See the [Timeline-Extension-UPM-Package](http://esotericsoftware.com/spine-unity#Timeline-Extension-UPM-Package) section of the spine-unity documentation for more information. + - Added support for double-sided lighting at all `SkeletonLit` shaders (including URP and LWRP packages). + - Added frustum culling update mode parameters `Update When Invisible` (Inspector parameter) and `UpdateMode` (available via code) to all Skeleton components. This provides a simple way to disable certain updates when the `Renderer` is no longer visible (outside all cameras, culled in frustum culling). The new `UpdateMode` property allows disabling updates at a finer granularity level than disabling the whole component. Available modes are: `Nothing`, `OnlyAnimationStatus`, `EverythingExceptMesh` and `FullUpdate`. + - Added a new `Spine/Outline/OutlineOnly-ZWrite` shader to provide correct outline-only rendering. Note: the shader requires two render passes and is therefore not compatible with URP. The `Spine Examples/Other Examples/Outline Shaders` example scene has been updated to demonstrate the new shader. + - Added `OnMeshAndMaterialsUpdated` callback event to `SkeletonRenderSeparator` and `SkeletonPartsRenderer`. It is issued at the end of `LateUpdate`, before rendering. + - Added `Root Motion Scale X/Y` parameters to `SkeletonRootMotionBase` subclasses (`SkeletonRootMotion` and `SkeletonMecanimRootMotion`). Also providing `AdjustRootMotionToDistance()` and other methods to allow for easy delta compensation. Delta compensation can be used to e.g. stretch a jump to a given distance. Root motion can be adjusted at the start of an animation or every frame via `skeletonRootMotion.AdjustRootMotionToDistance(targetPosition - transform.position, trackIndex);`. + - Now providing a `Canvas Group Tint Black` parameter at the `SkeletonGraphic` Inspector in the `Advanced` section. When using the `Spine/SkeletonGraphic Tint Black` shader you can enable this parameter to receive proper blending results when using `Additive` blend mode under a `CanvasGroup`. Be sure to also have the parameter `CanvasGroup Compatible` enabled at the shader. Note that the normal `Spine/SkeletonGraphic` does not support `Additive` blend mode at a `CanvasGroup`, as it requires additional shader channels to work. + - Added `Mix and Match Skins` example scene to demonstrate how the 3.8 Skin API and combining skins can be used for a wardrobe and equipment use case. + - Spine Timeline Extensions: Added `Hold Previous` parameter at `SpineAnimationStateClip`. + - Added more warning messages at incompatible SkeletonRenderer/SkeletonGraphic Component vs Material settings. They appear both as an info box in the Inspector as well as upon initialization in the Console log window. The Inspector box warnings can be disabled via `Edit - Preferences - Spine`. + - Now providing `BeforeApply` update callbacks at all skeleton animation components (`SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic`). + - Added `BoundingBoxFollowerGraphic` component. This class is a counterpart of `BoundingBoxFollower` that can be used with `SkeletonGraphic`. + - Added Inspector context menu functions `SkeletonRenderer - Add all BoundingBoxFollower GameObjects` and `SkeletonGraphic - Add all BoundingBoxFollowerGraphic GameObjects` that automatically generate bounding box follower GameObjects for every `BoundingBoxAttachment` for all skins of a skeleton. + - `GetRemappedClone()` now provides an additional parameter `pivotShiftsMeshUVCoords` for `MeshAttachment` to prevent uv shifts at a non-central Sprite pivot. This parameter defaults to `true` to maintain previous behaviour. + - `SkeletonRenderer` components now provide an additional update mode `Only Event Timelines` at the `Update When Invisible` property. This mode saves additional timeline updates compared to update mode `Everything Except Mesh`. + - Now all URP (Universal Render Pipeline) and LWRP (Lightweight Render Pipeline) shaders support SRP (Scriptable Render Pipeline) batching. See [Unity SRPBatcher documentation pages](https://docs.unity3d.com/Manual/SRPBatcher.html) for additional information. + - Sprite shaders now provide four `Diffuse Ramp` modes as an Inspector Material parameter: `Hard`, `Soft`, `Old Hard` and `Old Soft`. In spine-unity 3.8 it defaults to `Old Hard` to keep the behaviour of existing projects unchanged. From 4.0 on it defaults to `Hard` for newly created materials while existing ones remain unchanged. Note that `Old Hard` and `Old Soft` ramp versions were using only the right half of the ramp texture, and additionally multiplying the light intensity by 2, both leading to brighter lighting than without a ramp texture active. The new ramp modes `Hard` and `Soft` use the full ramp texture and do not modify light intensity, being consistent with lighting without a ramp texture active. + - Added **native support for slot blend modes** `Additive`, `Multiply` and `Screen` with automatic assignment at newly imported skeleton assets. `BlendModeMaterialAssets` are now obsolete and replaced by the native properties at `SkeletonDataAsset`. The `SkeletonDataAsset` Inspector provides a new `Blend Modes - Upgrade` button to upgrade an obsolete `BlendModeMaterialAsset` to the native blend modes properties. This upgrade will be performed automatically on imported and re-imported assets in Unity 2020.1 and newer to prevent reported `BlendModeMaterialAsset` issues in these Unity versions. spine-unity 4.0 and newer will automatically perform this upgrade regardless of the Unity version. + - `BoneFollower` and `BoneFollowerGraphic` components now provide better support for following bones when the skeleton's Transform is not the parent of the follower's Transform. Previously e.g. rotating a common parent Transform did not lead to the desired result, as well as negatively scaling a skeleton's Transform when it is not a parent of the follower's Transform. + - URP and LWRP `Sprite` and `SkeletonLit` shaders no longer require `Advanced - Add Normals` enabled to properly cast and receive shadows. It is recommended to disable `Add Normals` if normals are otherwise not needed. + - Added an example component `RootMotionDeltaCompensation` located in `Spine Examples/Scripts/Sample Components` which can be used for applying simple delta compensation. You can enable and disable the component to toggle delta compensation of the currently playing animation on and off. + - Root motion delta compensation now allows to only adjust X or Y components instead of both. Adds two parameters to `SkeletonRootMotionBase.AdjustRootMotionToDistance()` which default to adjusting both X and Y as before. The `RootMotionDeltaCompensation` example component exposes these parameters as public attributes. + - Root motion delta compensation now allows to also add translation root motion to e.g. adjust a horizontal jump upwards or downwards over time. This is necessary because a Y root motion of zero cannot be scaled to become non-zero. + - `Attachment.GetRemappedClone(Sprite)` method now provides an additional optional parameter `useOriginalRegionScale`. When set to `true`, the replaced attachment's scale is used instead of the Sprite's `Pixel per Unity` setting, allowing for more consistent scaling. _Note:_ When remapping Sprites, be sure to set the Sprite's `Mesh Type` to `Full Rect` and not `Tight`, otherwise the scale will be wrong. + +- **Changes of default values** + + - `SkeletonMecanim`'s `Layer Mix Mode` now defaults to `MixMode.MixNext` instead of `MixMode.MixAlways`. + - `BlendModeMaterialAsset` and it's instance `Default BlendModeMaterials.asset` now have `Apply Additive Material` set to `true` by default in order to apply all blend modes by default. + +- **Deprecated** + + - Deprecated `Modules/SlotBlendModes/SlotBlendModes` component. Changed namespace from `Spine.Unity.Modules` to `Spine.Unity.Deprecated`. Moved to `Deprecated/SlotBlendModes`. + +- **Restructuring (Non-Breaking)** + + Note: The following changes will most likely not affect users of the Spine-Unity runtime as the API remains unchanged and no references are invalidated. + + - Removed duplicates of `.cginc` files in `Modules/Shaders/Sprite` that were also present in the `Modules/Shaders/Sprite/CGIncludes` directory. + - Moved shaders from `Modules/Shaders` to `Shaders` directory. + - Moved shaders from `Modules/SkeletonGraphic/Shaders` to `Shaders/SkeletonGraphic`. + - Renamed shader `Shaders/Spine-SkeletonLit.shader` to `Shaders/Spine-Skeleton-Lit.shader`. + - Moved components from `SkeletonGraphic` to `Components` and `Components/Following` except for `SkeletonGraphicMirror` which was moved to `Spine Examples/Scripts/Sample Components`. + - Moved `BoneFollower`, `BoneFollowerGraphic` and `PointFollower` from `Components` directory to `Components/Following`. + - Moved `BoundingBoxFollower` component from `Modules/BoundingBoxFollower` to `Components/Following`. + - Moved `Modules/SkeletonRenderSeparator` directory to `Components/SkeletonRenderSeparator`. + - Moved `Modules/CustomMaterials` directory to `Components/SkeletonRendererCustomMaterials`. + - Moved `Asset Types/BlendModeMaterialsAsset.cs` class, `Shaders/BlendModes/Default BlendModeMaterials.asset` and materials from `Shaders/BlendModes` to `SkeletonDataModifierAssets/BlendModeMaterials` directory. + - Moved `Modules/Ghost` directory to `Spine Examples/Scripts/Sample Components/Ghost`. + - Moved `Modules/SkeletonUtility Modules` directory to `Spine Examples/Scripts/Sample Components/SkeletonUtility Modules`. + - Moved `Modules/AnimationMatchModifier` directory to `Spine Examples/Scripts/MecanimAnimationMatchModifier`. + - Moved `SkeletonRagdoll` and `SkeletonRagdoll2D` components from `Modules/Ragdoll` directory to `Spine Examples/Scripts/Sample Components/SkeletonUtility Modules`. + - Moved `AttachmentTools.cs` to `Utility` directory. + - Split the file `AttachmentTools` into 5 separate files for each contained class. No namespace or other API changes performed. + - Split the file `Mesh Generation/SpineMesh` into 4 separate files for each contained class. No namespace or other API changes performed. + - Moved `SkeletonExtensions.cs` to `Utility` directory. + - Moved `Modules/YieldInstructions` directory to `Utility/YieldInstructions`. + - Moved corresponding editor scripts of the above components to restructured directories as well. + - Renamed inspector editor class `PointFollowerEditor` to `PointFollowerInspector` for consistency reasons. + +### XNA/MonoGame + +- Updated to latest MonoGame version 3.7.1 +- Rewrote example project to be cleaner and better demonstrate basic Spine features. +- Added mix-and-match example to demonstrate the new Skin API. +- Added normalmap support via `SpineEffectNormalmap` and support for loading multiple texture layers following a suffix-pattern. Please see the example code on how to use them. + +## Java + +- **Breaking changes** + + - Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + - Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + - Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + - `JsonRollback` tool now converts from 3.8 JSON to 3.7. + - Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +- **Additions** + - Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `Skin#getAttachments()`. Returns all attachments in the skin. + - Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + - Added `Skin#addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `Skin#copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + +### libGDX + +- `SkeletonViewer` can load a skeleton by specifying it as the first argument on the command line. +- Added mix-and-match example to demonstrate the new Skin API. + +## Lua + +- **Breaking changes** + + - Renamed `Slot:getAttachmentVertices()` to `Slot#deform`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `Skin:addAttachment()` to `Skin#setAttachment()`. + - Removed `VertexAttachment:applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + - Changed the `.json` file format to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +- **Additions** + - Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `Skin:getAttachments()`. Returns all attachments in the skin. + - Added `Skin:getAttachments(slotIndex)`. Returns all attachements in the skin for the given slot index. + - Added `Skin:addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `Skin:copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - Added `Attachment:copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `MeshAttachment:newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + +### Love2D + +- Added support for 0-1 RGBA color component range change in Löve 0.11+. Older Löve versions using the 0-255 range are still supported! +- Added mix-and-match example to demonstrate the new Skin API. + +### Corona + +- Added mix-and-match example to demonstrate the new Skin API. + +## Typescript/Javascript + +- **Breaking changes** + + - Renamed `MixDirection.in/out` to `MixDirection.mixIn/mixOut` as it was crashing a JS compressor. + - Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + - Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + - Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + - Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + - Updated runtime to be compatible with TypeScript 3.6.3. + +- **Additions** + - Added support for loading binary data via `AssetManager#loadBinary()`. `AssetManager#get()` will return a `Uint8Array` for such assets. + - Added support for loading binaries via new `SkeletonBinary`. Parses a `Uint8Array`. + - Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `Skin#getAttachments()`. Returns all attachments in the skin. + - Added `Skin#getAttachments(slotIndex: number)`. Returns all attachements in the skin for the given slot index. + - Added `Skin#addSkin(skin: Skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `Skin#copySkin(skin: Skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + - Added `AssetManager.setRawDataURI(path, data)`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. + - Added `AssetManager.loadAll()` to allow Promise/async/await based waiting for completion of asset load. See the `spine-canvas` examples. + - Added `Skeleton.getBoundRect()` helper method to calculate the bouding rectangle of the current pose, returning the result as `{ x, y, width, height }`. Note that this method will create temporary objects which can add to garbage collection pressure. + +### WebGL backend + +- `Input` can now take a partially defined implementation of `InputListener`. +- Added mix-and-match example to demonstrate the new Skin API. + +### Canvas backend + +### Three.js backend + +- `SkeletonMesh` now takes an optional `SkeletonMeshMaterialParametersCustomizer` function that allows you to modify the `ShaderMaterialParameters` before the material is finalized. Use it to modify things like THREEJS' `Material.depthTest` etc. See #1590. + +### Player + +- `SpinePlayer#setAnimation()` can now be called directly to set the animation being displayed. +- The player supports loading `.skel` binary skeleton files by setting the `SpinePlayerConfig#skelUrl` field instead of `SpinePlayerConfig#jsonUrl`. +- Added `SpinePlayerConfig#rawDataURIs`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. See the example for a demonstration. + +# 3.7 + +## AS3 + +- **Breaking changes** + - The completion event will fire for looped 0 duration animations every frame. + - `MixPose` is now called `MixBlend` + - Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + - Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +- **Additions** + - Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + - Support for stretchy IK + - Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + - `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Starling + +- Added support for vertex effects. See `RaptorExample.as` +- Added 'getTexture()' method to 'StarlingTextureAtlasAttachmentLoader' +- Breaking change: if a skeleton requires two color tinting, you have to enable it via `SkeletonSprite.twoColorTint = true`. In this case the skeleton will use the `TwoColorMeshStyle`, which internally uses a different vertex layout and shader. This means that skeletons with two color tinting enabled will break batching and hence increase the number of draw calls in your app. +- Added `VertexEffect` and implementations `JitterEffect` and `SwirlEffect`. Allows you to modify vertices before they are submitted for drawing. See Starling changes. +- Fix issues with StarlingAtlasAttachmentLoader, see https://github.com/EsotericSoftware/spine-runtimes/issues/939 +- Fix issues with region trimming support, see https://github.com/EsotericSoftware/spine-runtimes/commit/262bc26c64d4111002d80e201cb1a3345e6727df +- Added support for overriding `StarlingAtlasAttachmentLoader#getTexture()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/ea7dbecb98edc74e439aa9ef90dcf6eed865f718 +- Texture atlas operations are no longer handled in `Starling#newRegionAttachment` and `Starling#newMeshAttachment` but delegated to the atlas. +- Added sample for additive animation blending, see https://github.com/EsotericSoftware/spine-runtimes/blob/6a556de01429878df47bb276a97959a8bdbbe32f/spine-starling/spine-starling-example/src/spine/examples/OwlExample.as +- Added sample on how to use bounding box attachment vertices https://github.com/EsotericSoftware/spine-runtimes/commit/e20428b02699226164fa73ba4b12f7d029ae6f4d +- Fully transparent meshes are not submitted for rendering. +- No hit-tests are performed when a skeleton is invisible. + +## C + +- **Breaking changes** + - Listeners on `spAnimationState` and `spTrackEntry` will now also be called if a track entry gets disposed as part of disposing an animation state. + - The completion event will fire for looped 0 duration animations every frame. + - The spine-cocos2dx and spine-ue4 runtimes are now based on spine-cpp. See below for changes. + - Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + - Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 + - `spMeshAttachment` has two new fields `regionTextureWith` and `regionTextureHeight`. These must be set in custom attachment loader. See `AtlasAttachmentLoader`. +- **Additions** + - Added support for local and relative transform constraint calculation, including additional fields in `spTransformConstraintData`. + - `Animation#apply` and ` Timeline#apply`` now take enums `MixPose`and`MixDirection` instead of booleans + - Added `spVertexEffect` and corresponding implementations `spJitterVertexEffect` and `spSwirlVertexEffect`. Create/dispose through the corresponding `spXXXVertexEffect_create()/dispose()` functions. Set on framework/engine specific renderer. + - Functions in `extension.h` are not prefixed with `_sp` instead of just `_` to avoid interference with other libraries. + - Introduced `SP_API` macro. Every spine-c function is prefixed with this macro. By default, it is an empty string. Can be used to markup spine-c functions with e.g. ``__declspec` when compiling to a dll or linking to that dll. + - Added `void *userData` to `spAnimationState`to be consumed in callbacks. + - Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `spTrackEntry->mixBlend = SP_MIXBLEND_ADD)` on each track. To specify the blend percentage, set `spTrackEntry->alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + - Optimized attachment lookup to give a 40x speed-up. See https://github.com/EsotericSoftware/spine-runtimes/commit/cab81276263890b65d07fa2329ace16db1e365ff + - Support for stretchy IK + - Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + - `spTrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Cocos2d-Objc + +- Added vertex effect support to modify vertices of skeletons on the CPU. See `RaptorExample.m`. +- Explanation how to handle ARC, see https://github.com/EsotericSoftware/spine-runtimes/commit/a4f122b08c5e2a51d6aad6fc5a947f7ec31f2eb8 +- The super class `::update()` method of `SkeletonRenderer` is now called, see https://github.com/EsotericSoftware/spine-runtimes/commit/f7bb98185236a6d8f35bfefc70afe4f31e9ec9d2 +- Added improved tint-black shader. + +### SFML + +- `spine-sfml.h` no longer defines `SPINE_SHORT_NAMES` to avoid collisions with other APIs. See #1058. +- Added support for vertex effects. See raptor example. +- Added premultiplied alpha support to `SkeletonDrawable`. Use `SkeletonDrawable::setUsePremultipliedAlpha()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/34086c1f41415309b2ecce86055f6656fcba2950 +- Added additive animation blending sample, see https://github.com/EsotericSoftware/spine-runtimes/blob/b7e712d3ca1d6be3ebcfe3254dc2cea9c44dda71/spine-sfml/example/main.cpp#L369 + +## C++ + +- ** Additions ** + - Added C++ Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. + - Added parsing of non-essential data (fps, images path, audio path) to for `.json`/`.skel` parsers. + +### Cocos2d-x + +- Added ETC1 alpha support, thanks @halx99! Does not work when two color tint is enabled. +- Added `spAtlasPage_setCustomTextureLoader()` which let's you do texture loading manually. Thanks @jareguo. +- Added `SkeletonRenderer:setSlotsRange()` and `SkeletonRenderer::createWithSkeleton()`. This allows you to split rendering of a skeleton up into multiple parts, and render other nodes in between. See `SkeletonRendererSeparatorExample.cpp` for an example. +- Fully transparent attachments will not be rendered, improving rendering performance. +- Added improved tint-black shader. +- Updated to cocos2d-x 3.16 +- The skeleton setup pose and world transform are now calculated on initialization to avoid flickering on start-up. +- Updated to cocos2d-x 3.17.1 +- **Breaking change**: Switched from [spine-c](spine-c) to [spine-cpp](spine-cpp) as the underlying Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. + - Added `Cocos2dAttachmentLoader` to be used when constructing an `Atlas`. Used by default by `SkeletonAnimation` and `SkeletonRenderer` when creating instances via the `createXXX` methods. + - All C structs and enums `spXXX` have been replaced with their C++ equivalents `spine::XXX` in all public interfaces. + - All instantiations via `new` of C++ classes from spine-cpp should contain `(__FILE__, __LINE__)`. This allows the tracking of instantations and detection of memory leaks via the `spine::DebugExtension`. + +### SFML + +- Create a second SFML backend using [spine-cpp](spine-cpp/). See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. +- Added support for vertex effects. See raptor example. +- Added premultiplied alpha support to `SkeletonDrawable`. Use `SkeletonDrawable::setUsePremultipliedAlpha()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/34086c1f41415309b2ecce86055f6656fcba2950 +- Added additive animation blending sample, see https://github.com/EsotericSoftware/spine-runtimes/blob/b7e712d3ca1d6be3ebcfe3254dc2cea9c44dda71/spine-sfml/example/main.cpp#L369 + +### UE4 + +- spine-c is now exposed from the plugin shared library on Windows via \_\_declspec. +- Updated to Unreal Engine 4.18 +- Added C++ example, see https://github.com/EsotericSoftware/spine-runtimes/commit/15011e81b7061495dba45e28b4d3f4efb10d7f40 +- `SkeletonRendererComponent` generates collision meshes by default. +- Disabled generation of collision meshes by `SkeletonRendererComponent`. Both `ProceduralMeshComponent` and `RuntimeMeshComponent` have a bug that generates a new PhysiX file every frame per component. Users are advised to add a separate collision shape to the root scene component of an actor instead. +- Using UE4 `FMemory` allocator by default. This should fix issues on some consoles. +- **Breaking change** moved away from `RuntimeMeshComponent`, as its maintainance has seized, back to `ProceduralMeshComponent`. Existing projects should just work. However, if you run into issues, you may have to remove the old `SpineSkeletonRendererComponent` and add a new one to your existing actors. +- **Breaking change** due to the removal of `RuntimeMeshComponent` and reversal to `ProceduralMeshComponent`, two color tinting is currently not supported. `ProceduralMeshComponent` does not support enough vertex attributes for us to encode the second color in the vertex stream. You can remove the `RuntimeMeshComponent/` directory from your plugins directory and remove the component from any `build.cs` files that may reference it. +- **Breaking change**: Switched from [spine-c](spine-c) to [spine-cpp](spine-cpp) as the underlying Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. +- All C structs and enums `spXXX` have been replaced with their C++ equivalents `spine::XXX` in all public interfaces. +- All instantiations via `new` of C++ classes from spine-cpp should contain `(__FILE__, __LINE__)`. This allows the tracking of instantations and detection of memory leaks via the `spine::DebugExtension`. +- Updated to Unreal Engine 4.20 (samples require 4.17+), see the `spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.build.cs` file on how to compile in 4.20 with the latest UBT API changes. +- Updated to Unreal Engine 4.21 (samples require 4.21). +- **Breaking change**: `UBoneDriverComponent` and `UBoneFollowerComponent` are now `USceneComponent` instead of `UActorComponent`. They either update only themselves, or also the owning `UActor`, depending on whether the new flag `UseComponentTransform` is set. See https://github.com/EsotericSoftware/spine-runtimes/pull/1175 +- Added query methods for slots, bones, skins and animations to `SpineSkeletonComponent` and `UTrackEntry`. These allow you to query these objects by name in both C++ and blueprints. +- Added `Preview Animation` and `Preview Skin` properties to `SpineSkeletonAnimationComponent`. Enter an animation or skin name to live-preview it in the editor. Enter an empty string to reset the animation or skin. + +## C# + +- **Breaking changes** + - The completion event will fire for looped 0 duration animations every frame. + - Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + - Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +- **Additions** + - Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#MixBlend = MixBlend.add` on each track. To specify the blend percentage, set `TrackEntry#Alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + - Support for stretchy IK + - Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + - `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Unity + +- **Runtime and Editor, and Assembly Definition** Files and folders have been reorganized into "Runtime" and "Editor". Each of these have an `.asmdef` file that defines these separately as their own assembly in Unity _(Note: Spine `.asmdef` files are currently deactivated to `.txt` extension, see below)_. For projects not using assembly definition, you may delete the `.asmdef` files. These assembly definitions will be ignored by older versions of Unity that don't support it. + - In this scheme, the entirety of the base spine-csharp runtime is inside the "Runtime" folder, to be compiled in the same assembly as spine-unity so they can continue to share internal members. +- **Spine `.asmdef` files are now deactivated (using `.txt` extension) by default** This prevents problems when updating Spine through unitypackages, overwriting the Timeline reference entry in `spine-unity.asmdef` (added automatically when enabling Unity 2019 Timeline support, see `Timeline Support for Unity 2019`), causing compile errors. In case you want to enable the `.asmdef` files, rename the files: + `Spine/Runtime/spine-unity.txt` to `Spine/Runtime/spine-unity.asmdef` and + `Spine/Editor/spine-unity-editor.txt` to `Spine/Editor/spine-unity-editor.asmdef`. +- **SkeletonAnimator is now SkeletonMecanim** The Spine-Unity Mecanim-driven component `SkeletonAnimator` has been renamed `SkeletonMecanim` to make it more autocomplete-friendly and more obvious at human-glance. The .meta files and guids should remain intact so existing projects and prefabs should not break. However, user code needs to be updated to use `SkeletonMecanim`. +- **SpineAtlasAsset** The existing `AtlasAsset` type has been renamed to `SpineAtlasAsset` to signify that it specifically uses a Spine/libGDX atlas as its source. Serialization should be intact but user code will need to be updated to refer to existing atlases as `SpineAtlasAsset`. + - **AtlasAssetBase** `SpineAtlasAsset` now has an abstract base class called `SpineAtlasAsset`. This is the base class to derive when using alternate atlas sources. Existing SkeletonDataAsset field "atlasAssets" now have the "AtlasAssetBase" type. Serialization should be intact, but user code will need to be updated to refer to the atlas assets accordingly. + - This change is in preparation for alternate atlas options such as Unity's SpriteAtlas. +- **Optional Straight Alpha for shaders** Spine-Unity's included Unity shaders now have a `_STRAIGHT_ALPHA_INPUT` shader_feature, toggled as a checkbox in the Material's inspector. This allows the Material to use a non-premultiplied alpha/straight alpha input texture. + - The following shaders now have the "Straight Alpha Texture" checkbox when used on a material: + - `Spine/Skeleton` + - `Spine/Skeleton Tint Black` + - `Spine/Skeleton Lit` + - `Spine/Skeleton Tint` + - `Spine/Skeleton Fill` + - `Spine/SkeletonGraphic (Premultiply Alpha)` was renamed to `Spine/SkeletonGraphic` + - `Spine/SkeletonGraphic Tint Black (Premultiply Alpha)` was renamed to `Spine/SkeletonGraphic Tint Black` + - `Spine/Skeleton PMA Multiply` + - `Spine/Skeleton PMA Screen` + - Dedicated straight alpha shaders were removed from the runtime. + - `Spine/Straight Alpha/Skeleton Fill` + - `Spine/Straight Alpha/Skeleton Tint` +- **Detection of Incorrect Texture Settings** Especially when atlas textures are exported with setting `Premultiply alpha` enabled, it is important to configure Unity's texture import settings correctly. By default, you will now receive warnings where texture settings are expected to cause incorrect rendering. + - The following rules apply: + - `sRGB (Color Texture)` shall be disabled when `Generate Mip Maps` is enabled, otherwise you will receive white border outlines. + - `Alpha Is Transparency` shall be disabled on `Premultiply alpha` textures, otherwise you will receive light ghosting artifacts in transparent areas. + - These warnings can be disabled in `Edit - Preferences - Spine`. +- **Sprite Mask Support for all Included Shaders** The `Skeleton Animation` and `Skeleton Mecanim` components now provide an additional `Mask Interaction` field in the Inspector, covering identical functionality as Unity's built in `Sprite Renderer` component: + - `Mask Interaction` modes: + - `None` - The sprite will not interact with the masking system. Default behavior. + - `Visible Inside Mask` - The sprite will be visible only in areas where a mask is present. + - `Visible Outside Mask` - The sprite will be visible only in areas where no mask is present. + - `Automatically Generated Materials` When switching `Mask Interaction` modes in the Inspector outside of Play mode, the required additional material assets are generated for the respective `Stencil Compare` parameters - with file suffixes `'_InsideMask'` and `'_OutsideMask'`, placed in the same folder as the original materials. By default all generated materials are kept as references by the `Skeleton Animation` component for switching at runtime. + These materials can be managed and optimized via the `SkeletonAnimation`'s `Advanced` section: + - Using the `Clear` button you can clear the reference to unneeded materials, + - Using the `Delete` button the respective assets are deleted as well as references cleared. Note that other `Skeleton Animation` GameObjects might still reference the materials, so use with caution! + - With the `Set` button you can again assign a link to the respective materials to prepare them for runtime use. If the materials were not present or have been deleted, they are generated again based on the default materials. + - When switching `Mask Interaction` mode at runtime, the previously prepared materials are switched active automatically. When the respective materials have not been prepared, material copies of the default materials are created on the fly. Note that these materials are not shared between similar `Skeleton Animation` GameObjects, so it is recommended to use the generated material assets where possible. + - **Every shader now exposes the `Stencil Compare` parameter** for further customization. This way you have maximum flexibility to use custom mechanisms to switch materials at runtime if you should ever need more than the three materials generated by `Skeleton Animation`'s `Mask Interaction` parameter. Reference `Stencil Compare` values are: + - `CompareFunction.Disabled` for `Mask Interaction - None` + - `CompareFunction.LessEqual` for `Mask Interaction - Visible Inside Mask` + - `CompareFunction.Greater` for `Mask Interaction - Visible Outside Mask` +- **RectMask2D Support for SkeletonGraphic** Both `SkeletonGraphic` shaders '`Spine/SkeletonGraphic`' and '`Spine/SkeletonGraphic Tint Black`' now respect masking areas defined via Unity's `RectMask2D` component. +- **Timeline Support for Unity 2019** using the existing Timeline components. By default, all Spine Timeline components are deactivated in Unity 2019 and **can be activated via the Spine Preferences menu**. This step became necessary because in Unity 2019, Timeline has been moved to a separate Package and is no longer included in the Unity core. Please visit `Edit - Preferences - Spine` and at `Timeline Package Support` hit `Enable` to automatically perform all necessary steps to activate the Timeline components. + This will automatically: + 1. download the Unity Timeline package + 2. activate the Spine Timeline components by setting the compile definition `SPINE_TIMELINE_PACKAGE_DOWNLOADED` for all platforms + 3. modify the `spine-unity.asmdef` file by adding the reference to the Unity Timeline library. +- Added `Create 2D Hinge Chain` functionality at `SkeletonUtilityBone` inspector, previously only `Create 3D Hinge Chain` was available. + +### XNA/MonoGame + +- Added support for any `Effect` to be used by `SkeletonRenderer` +- Added support for `IVertexEffect` to modify vertices of skeletons on the CPU. `IVertexEffect` instances can be set on the `SkeletonRenderer`. See example project. +- Added `SkeletonDebugRenderer` +- Made `MeshBatcher` of SkeletonRenderer accessible via a getter. Allows user to batch their own geometry together with skeleton meshes for maximum batching instead of using XNA SpriteBatcher. + +## Java + +- **Breaking changes** + - Skeleton attachments: Moved update of attached skeleton out of libGDX `SkeletonRenderer`, added overloaded method `Skeleton#updateWorldTransform(Bone)`, used for `SkeletonAttachment`. You now MUST call this new method with the bone of the parent skeleton to which the child skeleton is attached. See `SkeletonAttachmentTest` for and example. + - The completion event will fire for looped 0 duration animations every frame. + - `MixPose` is now called `MixBlend`. + - Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + - Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +- **Additions** + - Added `EventData#audioPath` field. This field contains the file name of the audio file used for the event. + - Added convenience method to add all attachments from one skin to another, see https://github.com/EsotericSoftware/spine-runtimes/commit/a0b7bb6c445efdfac12b0cdee2057afa3eff3ead + - Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + - Support for stretchy IK + - Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + - `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### libGDX + +- Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect` and `VertexEffectTest`. +- Added improved tint-black shader. +- Improved performance by avoiding batch flush when not switching between normal and additive rendering with PMA +- Improvements to skeleton viewer. +- `TwoColorPolygonBatch` implements the `Batch` interface, allowing to the be used with other libGDX classes that require a batcher for drawing, potentially improving performance. See https://github.com/EsotericSoftware/spine-runtimes/commit/a46b3d1d0c135d51f9bef9ca17a5f8e5dda69927 +- Added `SkeletonDrawable` to render skeletons in scene2d UI https://github.com/EsotericSoftware/spine-runtimes/commit/b93686c185e2c9d5466969a8e07eee573ebe4b97 + +## Lua + +- **Breaking changes** + - The completion event will fire for looped 0 duration animations every frame. + - Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + - Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +- **Additions** + - Added `JitterEffect` and `SwirlEffect` and support for vertex effects in Corona and Love + - Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry:setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry.alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + - Support for stretchy IK + - Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + - `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Love2D + +- Added support for vertex effects. Set an implementation like "JitterEffect" on `Skeleton.vertexEffect`. See `main.lua` for an example. + +### Corona + +- Added support for vertex effects. Set an implementation like "JitterEffect" on `SkeletonRenderer.vertexEffect`. See `main.lua` for an example + +## Typescript/Javascript + +- **Breaking changes** + - The completion event will fire for looped 0 duration animations every frame. + - Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + - Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +- **Additions** + - Added `AssetManager.loadTextureAtlas`. Instead of loading the `.atlas` and corresponding image files manually, you can simply specify the location of the `.atlas` file and AssetManager will load the atlas and all its images automatically. `AssetManager.get("atlasname.atlas")` will then return an instance of `spine.TextureAtlas`. + - Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. See https://github.com/EsotericSoftware/spine-runtimes/blob/f045d221836fa56191ccda73dd42ae884d4731b8/spine-ts/webgl/tests/test-additive-animation-blending.html for an example. + - Added work-around for iOS WebKit JIT bug, see https://github.com/EsotericSoftware/spine-runtimes/commit/c28bbebf804980f55cdd773fed9ff145e0e7e76c + - Support for stretchy IK + - Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + - `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + - Added `AssetManager#setRawDataURI(path, data)`. Allows to set raw data URIs for a specific path, which in turn enables embedding assets into JavaScript/HTML. + - `PolygonBatcher` will now disable `CULL_FACE` and restore the state as it was before rendering. + +### WebGL backend + +- Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`, and the example which allows to set effects. +- Added `slotRangeStart` and `slotRangeEnd` parameters to `SkeletonRenderer#draw` and `SceneRenderer#drawSkeleton`. This allows you to render only a range of slots in the draw order. See `spine-ts/webgl/tests/test-slot-range.html` for an example. +- Added improved tint-black shader. +- Added `SceneRenderer#drawTextureUV()`, allowing to draw a texture with manually specified texture coordinates. +- Exposed all renderers in `SceneRenderer`. + +### Canvas backend + +- Added support for shearing and non-uniform scaling inherited from parent bones. +- Added support for alpha tinting. + +### Three.js backend + +- Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`. +- Added support for multi-page atlases + +### Widget backend + +- Added fields `atlasContent`, `atlasPagesContent`, and `jsonContent` to `WidgetConfiguration` allowing you to directly pass the contents of the `.atlas`, atlas page `.png` files, and the `.json` file without having to do a request. See `README.md` and the example for details. +- `SpineWidget.setAnimation()` now takes an additional optional parameter for callbacks when animations are completed/interrupted/etc. + +# 3.6 + +## AS3 + +- **Breaking changes** + + - Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + - Made `Bone` fields `_a`, `_b`, `_c`, `_d`, `_worldX` and `_worldY` public, removed underscore prefix. + - Removed `VertexAttachment.computeWorldVertices` overload, changed `VertexAttachment.computeWorldVertices2` to `VertexAttachment.computeWorldVertices`, added `stride` parameter. + - Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + - Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + - Replaced `r`, `g`, `b`, `a` fields with instances of new `Color` class in `RegionAttachment`, `MeshAttachment`, `Skeleton`, `SkeletonData`, `Slot` and `SlotData`. + - The completion event will fire for looped 0 duration animations every frame. + +- **Additions** + - Added `Skeleton.getBounds` from reference implementation. + - Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + - Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + - Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + - Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + - Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + - `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + - `Animation#apply` and ` Timeline#apply`` now take enums `MixPose`and`MixDirection` instead of booleans + - Added `VertexEffect` and implementations `JitterEffect` and `SwirlEffect`. Allows you to modify vertices before they are submitted for drawing. See Starling changes. + +### Starling + +- Fixed renderer to work with 3.6 changes. +- Added support for two color tinting. +- Added support for clipping. +- Added support for rotated regions in texture atlas loaded via StarlingAtlasAttachmentLoader. +- Added support for vertex effects. See `RaptorExample.as` +- Added 'getTexture()' method to 'StarlingTextureAtlasAttachmentLoader' +- Breaking change: if a skeleton requires two color tinting, you have to enable it via `SkeletonSprite.twoColorTint = true`. In this case the skeleton will use the `TwoColorMeshStyle`, which internally uses a different vertex layout and shader. This means that skeletons with two color tinting enabled will break batching and hence increase the number of draw calls in your app. + +## C + +- **Breaking changes** + - `spVertexAttachment_computeWorldVertices` and `spRegionAttachment_computeWorldVerticeS` now take new parameters to make it possible to directly output the calculated vertex positions to a vertex buffer. Removes the need for additional copies in the backends' respective renderers. + - Removed `spBoundingBoxAttachment_computeWorldVertices`, superseded by `spVertexAttachment_computeWorldVertices`. + - Removed `spPathAttachment_computeWorldVertices` and `spPathAttachment_computeWorldVertices1`, superseded by `spVertexAttachment_computeWorldVertices`. + - Removed `sp_MeshAttachment_computeWorldVertices`, superseded by `spVertexAttachment_computeWorldVertices`. + - Removed `spBone_worldToLocalRotationX` and `spBone_worldToLocalRotationY`. Replaced by `spBone_worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + - Replaced `r`, `g`, `b`, `a` fields with instances of new `spColor` struct in `spRegionAttachment`, `spMeshAttachment`, `spSkeleton`, `spSkeletonData`, `spSlot` and `spSlotData`. + - Removed `spVertexIndex`from public API. + - Listeners on `spAnimationState` or `spTrackEntry` will now be also called in case a track entry is disposed as part of dispoing the `spAnimationState`. + - The completion event will fire for looped 0 duration animations every frame. +- **Additions** + - Added support for local and relative transform constraint calculation, including additional fields in `spTransformConstraintData`. + - Added `spPointAttachment`, additional method `spAtlasAttachmentLoadeR_newPointAttachment`. + - Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + - Added `spBone_localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + - Added two color tinting support, including `spTwoColorTimeline` and additional fields on `spSlot` and `spSlotData`. + - Added `userData` field to `spTrackEntry`, so users can expose data in `spAnimationState` callbacks. + - Modified kvec.h used by SkeletonBinary.c to use Spine's MALLOC/FREE macros. That way there's only one place to inject custom allocators ([extension.h](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-c/spine-c/include/spine/extension.h)) [commit](https://github.com/EsotericSoftware/spine-runtimes/commit/c2cfbc6cb8709daa082726222d558188d75a004f) + - Added macros to define typed dynamic arrays, see `Array.h/.c` + - Added `spClippingAttachment` and respective enum. + - Added `spSkeletonClipper` and `spTriangulator`, used to implement software clipping of attachments. + - `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + - `Animation#apply` and ` Timeline#apply`` now take enums `MixPose`and`MixDirection` instead of booleans + - Added `spVertexEffect` and corresponding implementations `spJitterVertexEffect` and `spSwirlVertexEffect`. Create/dispose through the corresponding `spXXXVertexEffect_create()/dispose()` functions. Set on framework/engine specific renderer. See changes for spine-c based frameworks/engines below. + - Functions in `extension.h` are not prefixed with `_sp` instead of just `_` to avoid interference with other libraries. + - Introduced `SP_API` macro. Every spine-c function is prefixed with this macro. By default, it is an empty string. Can be used to markup spine-c functions with e.g. ``__declspec` when compiling to a dll or linking to that dll. + +### Cocos2d-X + +- Fixed renderer to work with 3.6 changes +- Optimized rendering by removing all per-frame allocation in `SkeletonRenderer`, resulting in 15% performance increase for large numbers of skeletons being rendered per frame. +- Added support for two color tinting. Tinting is enabled/disabled per `SkeletonRenderer`/`SkeletonAnimation` instance. Use `SkeletonRenderer::setTwoColorTint()`. Note that two color tinting requires the use of a non-standard shader and vertex format. This means that skeletons rendered with two color tinting will break batching. However, skeletons with two color tinting enabled and rendered after each other will be batched. +- Updated example to use Cocos2d-x 3.14.1. +- Added mesh debug rendering. Enable/Disable via `SkeletonRenderer::setDebugMeshesEnabled()`. +- Added support for clipping. +- SkeletonRenderer now combines the displayed color of the Node (cascaded from all parents) with the skeleton color for tinting. +- Added support for vertex effects. See `RaptorExample.cpp`. +- Added ETC1 alpha support, thanks @halx99! Does not work when two color tint is enabled. +- Added `spAtlasPage_setCustomTextureLoader()` which let's you do texture loading manually. Thanks @jareguo. +- Added `SkeletonRenderer:setSlotsRange()` and `SkeletonRenderer::createWithSkeleton()`. This allows you to split rendering of a skeleton up into multiple parts, and render other nodes in between. See `SkeletonRendererSeparatorExample.cpp` for an example. + +### Cocos2d-Objc + +- Fixed renderer to work with 3.6 changes +- Added support for two color tinting. Tinting is enabled/disabled per `SkeletonRenderer/SkeletonAnimation.twoColorTint = true`. Note that two color tinted skeletons do not batch with other nodes. +- Added support for clipping. + +### SFML + +- Fixed renderer to work with 3.6 changes. Sadly, two color tinting does not work, as the vertex format in SFML is fixed. +- Added support for clipping. +- Added support for vertex effects. See raptor example. +- Added premultiplied alpha support to `SkeletonDrawable`. + +### Unreal Engine 4 + +- Fixed renderer to work with 3.6 changes +- Added new UPROPERTY to SpineSkeletonRendererComponent called `Color`. This allows to set the tint color of the skeleton in the editor, C++ and Blueprints. Under the hood, the `spSkeleton->color` will be set on every tick of the renderer component. +- Added support for clipping. +- Switched from built-in ProceduralMeshComponent to RuntimeMeshComponent by Koderz (https://github.com/Koderz/UE4RuntimeMeshComponent, MIT). Needed for more flexibility regarding vertex format, should not have an impact on existing code/assets. You need to copy the RuntimeMeshComponentPlugin from our repository in `spine-ue4\Plugins\` to your project as well! +- Added support for two color tinting. All base materials, e.g. SpineUnlitNormalMaterial, now do proper two color tinting. No material parameters have changed. +- Updated to Unreal Engine 4.16.1. Note that 4.16 has a regression which will make it impossible to compile plain .c files! +- spine-c is now exposed from the plugin shared library on Windows via \_\_declspec. + +## C# + +- **Breaking changes** + + - `MeshAttachment.parentMesh` is now a private field to enforce using the `.ParentMesh` setter property in external code. The `MeshAttachment.ParentMesh` property is an appropriate replacement wherever `.parentMesh` was used. + - `Skeleton.GetBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + - Removed `Bone.WorldToLocalRotationX` and `Bone.WorldToLocalRotationY`. Replaced by `Bone.WorldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + - Added `stride` parameter to `VertexAttachment.ComputeWorldVertices`. + - Removed `RegionAttachment.Vertices` field. The vertices array is provided to `RegionAttachment.ComputeWorldVertices` by the API user now. + - Removed `RegionAttachment.UpdateWorldVertices`, added `RegionAttachment.ComputeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + - The completion event will fire for looped 0 duration animations every frame. + +- **Additions** +- Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` +- Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). +- Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. +- Added `PointAttachment`, additional method `NewPointAttachment` in `AttachmentLoader` interface. +- Added `ClippingAttachment`, additional method `NewClippingAttachment` in `AttachmentLoader` interface. +- Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. +- `AnimationState.Apply` returns a bool indicating if any timeline was applied or not. +- `Animation.Apply` and ` Timeline.Apply`` now take enums `MixPose`and`MixDirection` instead of bools. + +### Unity + +- Refactored renderer to work with new 3.6 features. + - **Two color tinting** is currently supported via extra UV2 and UV3 mesh vertex streams. To use Two color tinting, you need to: + - switch on "Tint Black" under "Advanced...", + - use the new `Spine/Skeleton Tint Black` shader, or your own shader that treats the UV2 and UV3 streams similarly. + - Additionally, for SkeletonGraphic, you can use `Spine/SkeletonGraphic Tint Black` (or the bundled SkeletonGraphicTintBlack material) or your own shader that uses UV2 and UV3 streams similarly. **Additional Shader Channels** TexCoord1 and TexCoord2 will need to be enabled from the Canvas component's inspector. These correspond to UV2 and UV3. + - **Clipping** is now supported. Caution: The SkeletonAnimation switches to slightly slower mesh generation code when clipping so limit your use of `ClippingAttachment`s when using on large numbers of skeletons. +- **SkeletonRenderer.initialFlip** Spine components such as SkeletonRenderer, SkeletonAnimation, SkeletonAnimator now has `initialFlipX` and `initialFlipY` fields which are also visible in the inspector under "Advanced...". It will allow you to set and preview a starting flip value for your skeleton component. This is applied immediately when the internal skeleton object is instantiated. +- **[SpineAttribute] Improvements** + - **Icons have been added to SpineAttributeDrawers**. This should make your default inspectors easier to understand at a glance. + - **Added Constraint Attributes** You can now use `[SpineIkConstraint]` `[SpineTransformConstraint]` `[SpinePathConstraint]` + - **SpineAttribute dataField** parameter can also now detect sibling fields within arrays and serializable structs/classes. + - **[SpineAttribute(includeNone:false)]** SpineAttributes now have an `includeNone` optional parameter to specify if you want to include or exclude a none ("") value option in the dropdown menu. Default is `includeNone:true`. + - **[SpineAttachment(skinField:"mySkin")]** The SpineAttachment attribute now has a skinField optional parameter to limit the dropdown items to attachments in a specific skin instead of the just default skin or all the skins in SkeletonData. +- **SkeletonDebugWindow**. Debugging tools have been moved from the SkeletonAnimation and SkeletonUtility component inspectors into its own utility window. You can access "Skeleton Debug" under the `Advanced...` foldout in the SkeletonAnimation inspector, or in SkeletonAnimation's right-click/context menu. + - **Skeleton Baking Window** The old Skeleton Baking feature is also now accessible through the SkeletonDataAsset's right-click/context menu. +- **AttachmentTools source material**. `AttachmentTools` methods can now accept a `sourceMaterial` argument to copy material properties from. +- **AttachmentTools Skin Extensions**. Using AttachmentTools, you can now add entries by slot name by also providing a skeleton argument. Also `Append(Skin)`, `RemoveAttachment` and `Clear` have been added. +- **BoneFollower and SkeletonUtilityBone Add RigidBody Button**. The BoneFollower and SkeletonUtilityBone component inspectors will now offer to add a `Rigidbody` or `Rigidbody2D` if it detects a collider of the appropriate type. Having a rigidbody on a moving transform with a collider fits better with the Unity physics systems and prevents excess calculations. It will not detect colliders on child objects so you have to add Rigidbody components manually accordingly. +- **SkeletonRenderer.OnPostProcessVertices** is a new callback that gives you a reference to the MeshGenerator after it has generated a mesh from the current skeleton pose. You can access `meshGenerator.VertexBuffer` or `meshGenerator.ColorBuffer` to modify these before they get pushed into the UnityEngine.Mesh for rendering. This can be useful for non-shader vertex effects. +- **Examples** + - **Examples now use properties**. The code in the example scripts have been switched over to using properties instead of fields to encourage their use for consistency. This is in anticipation of both users who want to move the Spine folders to the Unity Plugins folder (compiled as a different assembly), and of Unity 2017's ability to manually define different assemblies for shorter compilation times. + - **Mix And Match**. The mix-and-match example scene, code and data have been updated to reflect the current recommended setup for animation-compatible custom equip systems The underlying API has changed since 3.5 and the new API calls in MixAndMatch.cs is recommended. Documentation is in progress. + - **Sample Components**. `AtasRegionAttacher` and `SpriteAttacher` are now part of `Sample Components`, to reflect that they are meant to be used as sample code rather than production. A few other sample components have also been added. New imports of the unitypackage Examples folder will see a "Legacy" folder comprised of old sample components that no longer contain the most up-to-date and recommended workflows, but are kept in case old setups used them for production. +- **Spine folder**. In the unitypackage, the "spine-csharp" and "spine-unity" folders are now inside a "Spine" folder. This change will only affect fresh imports. Importing the unitypackage to update Spine-Unity in your existing project will update the appropriate files however you chose to arrange them, as long as the meta files are intact. +- **Breaking changes** + - The Sprite shaders module was updated to the latest version from the [source](https://github.com/traggett/UnitySpriteShaders/commits/master). Some changes were made to the underlying keyword structure. You may need to review the settings of your lit materials. Particularly, your Fixed Normals settings. + - The `Spine/Skeleton Lit` shader was switched over to non-fixed-function code. It now no longer requires mesh normals and has fixed normals at the shader level. + - The old MeshGenerator classes, interfaces and code in `Spine.Unity.MeshGeneration` are now deprecated. All mesh-generating components now share the class `Spine.Unity.MeshGenerator` defined in `SpineMesh.cs`. MeshGenerator is a serializable class. + - The `SkeletonRenderer.renderMeshes` optimization is currently non-functional. + - Old triangle-winding code has been removed from `SkeletonRenderer`. Please use shaders that have backface culling off. + - Render settings in `SkeletonGraphic` can now be accessed under `SkeletonGraphic.MeshGenerator.settings`. This is visible in the SkeletonGraphic inspector as `Advanced...` + - We will continue to bundle the unitypackage with the empty .cs files of deprecated classes until Spine 3.7 to ensure the upgrade process does not break. + - The [SpineAttachment(slotField:)] optional parameter found property value now acts as a Find(slotName) argument rather than Contains(slotName). + - `SkeletonAnimator` now uses a `SkeletonAnimator.MecanimTranslator` class to translate an Animator's Mecanim State Machine into skeleton poses. This makes code reuse possible for a Mecanim version of SkeletonGraphic. + - `SkeletonAnimator` `autoreset` and the `mixModes` array are now a part of SkeletonAnimator's MecanimTranslator `.Translator`. `autoReset` is set to `true` by default. Old prefabs and scene objects with Skeleton Animator may no longer have correct values set. + - Warnings and conditionals checking for specific Unity 5.2-and-below incompatibility have been removed. + +## XNA/MonoGame + +- Added support for clipping +- Removed `RegionBatcher` and `SkeletonRegionRenderer`, renamed `SkeletonMeshRenderer` to `SkeletonRenderer` +- Added support for two color tint. For it to work, you need to add the `SpineEffect.fx` file to your content project, then load it via `var effect = Content.Load("SpineEffect");`, and set it on the `SkeletonRenderer`. See the example project for code. +- Added support for any `Effect` to be used by `SkeletonRenderer` +- Added support for `IVertexEffect` to modify vertices of skeletons on the CPU. `IVertexEffect` instances can be set on the `SkeletonRenderer`. See example project. +- Added `SkeletonDebugRenderer` +- Made `MeshBatcher` of SkeletonRenderer accessible via a getter. Allows user to batch their own geometry together with skeleton meshes for maximum batching instead of using XNA SpriteBatcher. + +## Java + +- **Breaking changes** + + - `Skeleton.getBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + - Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + - Added `stride` parameter to `VertexAttachment.computeWorldVertices`. + - Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + - Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + - Skeleton attachments: Moved update of attached skeleton out of libGDX `SkeletonRenderer`, added overloaded method `Skeleton#updateWorldTransform(Bone), used for `SkeletonAttachment`. You now MUST call this new method +with the bone of the parent skeleton to which the child skeleton is attached. See `SkeletonAttachmentTest` for and example. + - The completion event will fire for looped 0 duration animations every frame. + +- **Additions** + - Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + - Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + - Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + - Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + - Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + - Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + - `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + - `Animation#apply` and ` Timeline#apply`` now take enums `MixPose`and`MixDirection` instead of booleans + +### libGDX + +- Fixed renderer to work with 3.6 changes +- Added support for two color tinting. Use the new `TwoColorPolygonBatch` together with `SkeletonRenderer` +- Added support for clipping. See `SkeletonClipper`. Used automatically by `SkeletonRenderer`. Does not work when using a `SpriteBatch` with `SkeletonRenderer`. Use `PolygonSpriteBatch` or `TwoColorPolygonBatch` instead. +- Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect` and `VertexEffectTest`. + +## Lua + +- **Breaking changes** + - Removed `Bone:worldToLocalRotationX` and `Bone:worldToLocalRotationY`. Replaced by `Bone:worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + - `VertexAttachment:computeWorldVertices` now takes offsets and stride to allow compositing vertices directly in a vertex buffer to be send to the GPU. The compositing is now performed in the backends' respective renderers. This also affects the subclasses `MeshAttachment`, `BoundingBoxAttachment` and `PathAttachment`. + - Removed `RegionAttachment:updateWorldVertices`, added `RegionAttachment:computeWorldVertices`, which takes offsets and stride to allow compositing vertices directly in a vertex buffer to be send to the GPU. The compositing is now performed in the backends' respective renderers. + - Removed `MeshAttachment.worldVertices` field. Computation is now performed in each backends' respective renderer. The `uv` coordinates are now stored in `MeshAttachment.uvs`. + - Removed `RegionAttachment.vertices` field. Computation is now performed in each backends respective renderer. The `uv` coordinates for each vertex are now stored in the `RegionAttachment.uvs` field. + - The completion event will fire for looped 0 duration animations every frame. +- **Additions** +- Added `Bone:localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). +- Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. +- Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. +- Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` +- Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. +- Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. +- `AnimationState#apply` returns boolean indicating if any timeline was applied or not. +- `Animation#apply` and ` Timeline#apply`` now take enums `MixPose`and`MixDirection` instead of booleans +- Added `JitterEffect` and `SwirlEffect` and support for vertex effects in Corona and Love + +### Love2D + +- Fixed renderer to work with 3.6 changes +- Added support for two color tinting. Enable it via `SkeletonRenderer.new(true)`. +- Added clipping support. +- Added support for vertex effects. Set an implementation like "JitterEffect" on `Skeleton.vertexEffect`. See `main.lua` for an example. + +### Corona + +- Fixed renderer to work with 3.6 changes. Sadly, two color tinting is not supported, as Corona doesn't let us change the vertex format needed and its doesn't allow to modify shaders in the way needed for two color tinting +- Added clipping support. +- Added support for vertex effects. Set an implementation like "JitterEffect" on `SkeletonRenderer.vertexEffect`. See `main.lua` for an example + +## Typescript/Javascript + +- **Breaking changes** + + - `Skeleton.getBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + - Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + - Removed `VertexAttachment.computeWorldVertices` overload, changed `VertexAttachment.computeWorldVerticesWith` to `VertexAttachment.computeWorldVertices`, added `stride` parameter. + - Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + - Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + - The completion event will fire for looped 0 duration animations every frame. + - Removed the Spine Widget in favor of [Spine Web Player](https://esotericsoftware.com/spine-player). + +- **Additions** + - Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + - Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + - Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + - Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + - Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + - Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + - `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + - `Animation#apply` and ` Timeline#apply`` now take enums `MixPose`and`MixDirection` instead of booleans + - Added `AssetManager.loadTextureAtlas`. Instead of loading the `.atlas` and corresponding image files manually, you can simply specify the location of the `.atlas` file and AssetManager will load the atlas and all its images automatically. `AssetManager.get("atlasname.atlas")` will then return an instance of `spine.TextureAtlas`. + - Added the [Spine Web Player](https://esotericsoftware.com/spine-player) + +### WebGL backend + +- Fixed WebGL context loss + - Added `Restorable` interface, implemented by any WebGL resource that needs restoration after a context loss. All WebGL resource classes (`Shader`, `Mesh`, `GLTexture`) implement this interface. + - Added `ManagedWebGLRenderingContext`. Handles setup of a `WebGLRenderingContext` given a canvas element and restoration of WebGL resources (`Shader`, `Mesh`, `GLTexture`) on WebGL context loss. WebGL resources register themselves with the `ManagedWebGLRenderingContext`. If the context is informed of a context loss and restoration, the registered WebGL resources' `restore()` method is called. The `restore()` method implementation on each resource type will recreate the GPU side objects. + - All classes that previously took a `WebGLRenderingContext` in the constructor now also allow a `ManagedWebGLRenderingContext`. This ensures existing applications do not break. + - To use automatic context restauration: + 1. Create or fetch a canvas element from the DOM + 2. Instantiate a `ManagedWebGLRenderingContext`, passing the canvas to the constructor. This will setup a `WebGLRenderingContext` internally and manage context loss/restoration. + 3. Pass the `ManagedWebGLRenderingContext` to the constructors of classes that you previously passed a `WebGLRenderingContext` to (`AssetManager`, `GLTexture`, `Mesh`, `Shader`, `PolygonBatcher`, `SceneRenderer`, `ShapeRenderer`, `SkeletonRenderer`, `SkeletonDebugRenderer`). +- Fixed renderer to work with 3.6 changes. +- Added support for two color tinting. +- Improved performance by using `DYNAMIC_DRAW` for vertex buffer objects and fixing bug that copied to much data to the GPU each frame in `PolygonBatcher`/`Mesh`. +- Added two color tinting support, enabled by default. You can disable it via the constructors of `SceneRenderer`, `SkeletonRenderer`and `PolygonBatcher`. Note that you will need to use a shader created via `Shader.newTwoColoredTexturedShader` shader with `SkeletonRenderer` and `PolygonBatcher` if two color tinting is enabled. +- Added clipping support +- Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`, and the example which allows to set effects. +- Added `slotRangeStart` and `slotRangeEnd` parameters to `SkeletonRenderer#draw` and `SceneRenderer#drawSkeleton`. This allows you to render only a range of slots in the draw order. See `spine-ts/webgl/tests/test-slot-range.html` for an example. + +### Canvas backend + +- Fixed renderer to work for 3.6 changes. Sadly, we can't support two color tinting via the Canvas API. +- Added support for shearing and non-uniform scaling inherited from parent bones. +- Added support for alpha tinting. + +### Three.js backend + +- Fixed renderer to work with 3.6 changes. Two color tinting is not supported. +- Added clipping support +- Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`. +- Added support for multi-page atlases + +### Widget backend + +- Fixed WebGL context loss (see WebGL backend changes). Enabled automatically. +- Fixed renderer to work for 3.6 changes. Supports two color tinting & clipping (see WebGL backend changes for details). +- Added fields `atlasContent`, `atlasPagesContent`, and `jsonContent` to `WidgetConfiguration` allowing you to directly pass the contents of the `.atlas`, atlas page `.png` files, and the `.json` file without having to do a request. See `README.md` and the example for details. +- `SpineWidget.setAnimation()` now takes an additional optional parameter for callbacks when animations are completed/interrupted/etc. diff --git a/DateToSpine/third_party/spine-runtimes/4.2/LICENSE b/DateToSpine/third_party/spine-runtimes/4.2/LICENSE new file mode 100644 index 0000000..517ff9f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/LICENSE @@ -0,0 +1,26 @@ +Spine Runtimes License Agreement +Last updated April 5, 2025. Replaces all prior versions. + +Copyright (c) 2013-2025, Esoteric Software LLC + +Integration of the Spine Runtimes into software or otherwise creating +derivative works of the Spine Runtimes is permitted under the terms and +conditions of Section 2 of the Spine Editor License Agreement: +https://esotericsoftware.com/spine-editor-license + +Otherwise, it is permitted to integrate the Spine Runtimes into software +or otherwise create derivative works of the Spine Runtimes (collectively, +"Products"), provided that each user of the Products must obtain their own +Spine Editor license and redistribution of the Products in any form must +include this license and copyright notice. + +THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, +BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/DateToSpine/third_party/spine-runtimes/4.2/Package.swift b/DateToSpine/third_party/spine-runtimes/4.2/Package.swift new file mode 100644 index 0000000..201d35c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/Package.swift @@ -0,0 +1,62 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "spine-ios", + platforms: [ + .iOS(.v13), + .tvOS(.v13), + .macCatalyst(.v13), + .visionOS(.v1), + .macOS(.v10_15), + .watchOS(.v6), + ], + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "Spine", + targets: ["SpineModule"] + ), + .library( + name: "SpineCppLite", + targets: ["SpineCppLite"] + ) + ], + targets: [ + .target( + name: "SpineModule", + dependencies: [ + .byName( + name: "Spine", + condition: .when(platforms: [ + .iOS, + ]) + ), + "SpineCppLite", + "SpineShadersStructs", + ], + path: "spine-ios/Sources/SpineModule" + ), + .target( + name: "Spine", + dependencies: [ + "SpineCppLite", "SpineShadersStructs" + ], + path: "spine-ios/Sources/Spine" + ), + .target( + name: "SpineCppLite", + path: "spine-ios/Sources/SpineCppLite", + linkerSettings: [ + .linkedLibrary("c++"), + ] + ), + .systemLibrary( + name: "SpineShadersStructs", + path: "spine-ios/Sources/SpineShadersStructs" + ) + ], + cxxLanguageStandard: .cxx11 +) diff --git a/DateToSpine/third_party/spine-runtimes/4.2/README.md b/DateToSpine/third_party/spine-runtimes/4.2/README.md new file mode 100644 index 0000000..3245185 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/README.md @@ -0,0 +1,33 @@ +# Spine Runtimes + +This GitHub project hosts the Spine Runtimes which are needed to use [Spine](http://esotericsoftware.com/) 2D skeletal animation data with various game toolkits. + +## Licensing + +You are welcome to evaluate the Spine Runtimes and the examples we provide in this repository free of charge. + +You can integrate the Spine Runtimes into your software free of charge, but users of your software must have their own [Spine license](https://esotericsoftware.com/spine-purchase). Please make your users aware of this requirement! This option is often chosen by those making development tools, such as an SDK, game toolkit, or software library. + +In order to distribute your software containing the Spine Runtimes to others that don't have a Spine license, you need a [Spine license](https://esotericsoftware.com/spine-purchase) at the time of integration. Then you can distribute your software containing the Spine Runtimes however you like, provided others don't modify it or use it to create new software. If others want to do that, they'll need their own Spine license. + +For the official legal terms governing the Spine Runtimes, please read the [Spine Runtimes License Agreement](http://esotericsoftware.com/spine-runtimes-license) and Section 2 of the [Spine Editor License Agreement](http://esotericsoftware.com/spine-editor-license#s2). + +## Documentation + +See the [Spine Runtimes Guide](http://esotericsoftware.com/spine-runtimes-guide) for detailed information about using the Spine Runtimes. The Spine [documentation page](http://esotericsoftware.com/spine-documentation#runtimesTitle) provides further information about tools and data formats. For runtime specific documentation, refer to the `README.md` file in each runtime directory. + +## Bugs, enhancements, and tasks + +Review our backlog of bugs, enhancements, and tasks in the [spine-runtimes](https://github.com/EsotericSoftware/spine-runtimes/issues) and [spine-editor](https://github.com/EsotericSoftware/spine-editor/issues) issue trackers. Our [roadmap](http://esotericsoftware.com/spine-roadmap) provides a more convenient view of the same issue tracker information. + +## Versioning + +The default branch on GitHub is stable and works with data exported from the latest, non-beta version of the Spine editor. New development is done in an `X.X-beta` branch, which may be a work in progress. Important changes to the runtimes can be reviewed in the [CHANGELOG.md file](CHANGELOG.md). Occasionally the Spine Runtimes are [tagged](https://github.com/EsotericSoftware/spine-runtimes/releases) with the specific Spine editor version they work with. + +It is highly suggested to [freeze](http://esotericsoftware.com/spine-settings#Version) the Spine editor version to match the Spine Runtimes source being used and to update them in lock step. See the [Spine Runtimes Guide](http://esotericsoftware.com/spine-runtime-architecture#Versioning) for more information. + +## Contributing + +In order to merge your contributions, we need a signed [contributor license agreement (CLA)](http://esotericsoftware.com/licenses/cla.txt) from you. You can send a copy of the CLA to contact@esotericsoftware.com. + +When possible, it is best to base your contributions on the current beta branch (`X.X-beta`). Please be sure to follow the style and formatting you find in the respective runtime code to which you are contributing. diff --git a/DateToSpine/third_party/spine-runtimes/4.2/Spine.podspec b/DateToSpine/third_party/spine-runtimes/4.2/Spine.podspec new file mode 100644 index 0000000..396a187 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/Spine.podspec @@ -0,0 +1,32 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint spine_flutter.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'Spine' + s.version = '4.2.0' + s.summary = 'Spine runtimes for iOS.' + s.description = <<-DESC +Spine runtimes for iOS. + DESC + s.homepage = 'https://esotericsoftware.com' + s.author = { "Esoteric Software LLC " => "https://esotericsoftware.com" } + s.license = { :file => 'LICENSE' } + + s.source = { :git => 'https://github.com/esotericsoftware/spine-runtimes.git', :branch => '4.2' } + s.source_files = 'spine-ios/Sources/Spine/**/*.{swift}' + s.platform = :ios, '13.0' + + s.xcconfig = { + 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/SpineCppLite/spine-cpp/spine-cpp/include" "$(PODS_ROOT)/SpineCppLite/spine-cpp/spine-cpp-lite"', + 'MTL_HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/SpineShadersStructs"' + } + + s.resource_bundles = { + 'SpineBundle' => ['spine-ios/Sources/Spine/**/*.{metal}'] + } + + s.swift_version = '5.0' + s.dependency 'SpineCppLite' + s.dependency 'SpineShadersStructs' +end diff --git a/DateToSpine/third_party/spine-runtimes/4.2/SpineConfig.cmake.in b/DateToSpine/third_party/spine-runtimes/4.2/SpineConfig.cmake.in new file mode 100644 index 0000000..601b05b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/SpineConfig.cmake.in @@ -0,0 +1 @@ +include("@CMAKE_CURRENT_BINARY_DIR@/spine-cpp/spine-cppTargets.cmake") \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.2/SpineCppLite.podspec b/DateToSpine/third_party/spine-runtimes/4.2/SpineCppLite.podspec new file mode 100644 index 0000000..94b723a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/SpineCppLite.podspec @@ -0,0 +1,25 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint spine_flutter.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'SpineCppLite' + s.version = '4.2.0' + s.summary = 'Spine runtimes for iOS.' + s.description = <<-DESC +Spine runtimes for iOS. + DESC + s.homepage = 'https://esotericsoftware.com' + s.author = { "Esoteric Software LLC " => "https://esotericsoftware.com" } + s.license = { :file => 'LICENSE' } + s.platform = :ios, '13.0' + + s.source = { :git => 'https://github.com/esotericsoftware/spine-runtimes.git', :branch => '4.2' } + s.source_files = 'spine-cpp/spine-cpp/**/*.{h,cpp}', 'spine-cpp/spine-cpp-lite/*.{h,cpp}' + s.module_map = 'spine-cpp/spine-cpp-lite/module.modulemap' + s.pod_target_xcconfig = { + 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/SpineCppLite/spine-cpp/spine-cpp/include" "$(PODS_ROOT)/SpineCppLite/spine-cpp/spine-cpp-lite"', + 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11', + 'CLANG_CXX_LIBRARY' => 'libc++' + } +end diff --git a/DateToSpine/third_party/spine-runtimes/4.2/SpineShadersStructs.podspec b/DateToSpine/third_party/spine-runtimes/4.2/SpineShadersStructs.podspec new file mode 100644 index 0000000..e8943f3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/SpineShadersStructs.podspec @@ -0,0 +1,24 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint spine_flutter.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'SpineShadersStructs' + s.version = '4.2.0' + s.summary = 'Metal shaders structs for spine' + s.description = <<-DESC +Metal shaders structs for spine. + DESC + s.homepage = 'https://esotericsoftware.com' + s.author = { "Esoteric Software LLC " => "https://esotericsoftware.com" } + s.license = { :file => 'LICENSE' } + s.platform = :ios, '13.0' + + s.source = { :git => 'https://github.com/esotericsoftware/spine-runtimes.git', :branch => '4.2' } + s.source_files = 'spine-ios/Sources/SpineShadersStructs/*.{h,cpp}' + + s.pod_target_xcconfig = { + 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11', + 'CLANG_CXX_LIBRARY' => 'libc++' + } +end diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/readme.txt b/DateToSpine/third_party/spine-runtimes/4.2/examples/readme.txt new file mode 100644 index 0000000..21ee01a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/examples/readme.txt @@ -0,0 +1,27 @@ +These example projects show off many of Spine's features. Below are a number +of other example resources that may prove useful. + +We have detailed documentation for how many of the example projects are built: +http://esotericsoftware.com/spine-examples + +See our online demos, which render Spine animations right in your browser: +http://esotericsoftware.com/spine-demos + +Learn how to use Spine with the Spine User Guide: +http://esotericsoftware.com/spine-user-guide +And the accompanying Spine User Guide videos: +https://www.youtube.com/playlist?list=PLwGl7Ikd_6GRFo7d0uRu_fN2RIlvkxW7b +And our other videos: +https://www.youtube.com/user/EsotericSoftware/videos + +Learn how to integrate Spine into your software: +http://esotericsoftware.com/spine-runtime-documentation + +Super Spineboy is a full example game using Spine and libgdx: +https://github.com/EsotericSoftware/spine-superspineboy + +Many companies around the world are doing great things with Spine: +http://esotericsoftware.com/spine-showcase + +Tag your tweets using #madewithspine to show up on our Twitter page: +http://esotericsoftware.com/madewithspine diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-ess.json b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-ess.json new file mode 100644 index 0000000..6ac1da1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-ess.json @@ -0,0 +1,3672 @@ +{ +"skeleton": { + "hash": "TC0RU1zEc1o", + "spine": "4.2.22", + "x": -221.27, + "y": -8.57, + "width": 470.72, + "height": 731.57, + "images": "./images/", + "audio": "" +}, +"bones": [ + { "name": "root" }, + { "name": "hip", "parent": "root", "y": 247.47 }, + { + "name": "torso", + "parent": "hip", + "length": 127.56, + "rotation": 103.82, + "x": -1.62, + "y": 4.9, + "color": "e0da19ff" + }, + { + "name": "front-upper-arm", + "parent": "torso", + "length": 69.45, + "rotation": 168.38, + "x": 103.76, + "y": 19.33, + "color": "00ff04ff" + }, + { + "name": "front-bracer", + "parent": "front-upper-arm", + "length": 40.57, + "rotation": 18.3, + "x": 68.8, + "y": -0.68, + "color": "00ff04ff" + }, + { + "name": "front-fist", + "parent": "front-bracer", + "length": 65.39, + "rotation": 12.43, + "x": 40.57, + "y": 0.2, + "color": "00ff04ff" + }, + { + "name": "front-thigh", + "parent": "hip", + "length": 74.81, + "rotation": -95.51, + "x": -17.46, + "y": -11.64, + "color": "00ff04ff" + }, + { + "name": "front-shin", + "parent": "front-thigh", + "length": 128.77, + "rotation": -2.21, + "x": 78.69, + "y": 1.6, + "color": "00ff04ff" + }, + { + "name": "front-foot", + "parent": "front-shin", + "length": 91.34, + "rotation": 77.91, + "x": 128.76, + "y": -0.34, + "color": "00ff04ff" + }, + { + "name": "rear-upper-arm", + "parent": "torso", + "length": 51.94, + "rotation": -169.56, + "x": 92.36, + "y": -19.22, + "color": "ff000dff" + }, + { "name": "rear-bracer", "parent": "rear-upper-arm", "length": 34.56, "rotation": 23.15, "x": 51.36, "color": "ff000dff" }, + { + "name": "gun", + "parent": "rear-bracer", + "length": 43.11, + "rotation": 5.35, + "x": 34.42, + "y": -0.45, + "color": "ff000dff" + }, + { "name": "gun-tip", "parent": "gun", "rotation": 6.83, "x": 201.05, "y": 52.14, "color": "ff000dff" }, + { + "name": "neck", + "parent": "torso", + "length": 25.45, + "rotation": -31.54, + "x": 127.5, + "y": -0.31, + "color": "e0da19ff" + }, + { + "name": "head", + "parent": "neck", + "length": 263.58, + "rotation": 23.18, + "x": 27.66, + "y": -0.26, + "color": "e0da19ff" + }, + { + "name": "rear-thigh", + "parent": "hip", + "length": 85.72, + "rotation": -72.54, + "x": 8.91, + "y": -5.63, + "color": "ff000dff" + }, + { + "name": "rear-shin", + "parent": "rear-thigh", + "length": 121.88, + "rotation": -19.83, + "x": 86.1, + "y": -1.33, + "color": "ff000dff" + }, + { + "name": "rear-foot", + "parent": "rear-shin", + "length": 82.57, + "rotation": 69.3, + "x": 121.46, + "y": -0.76, + "color": "ff000dff" + } +], +"slots": [ + { "name": "rear-upper-arm", "bone": "rear-upper-arm", "attachment": "rear-upper-arm" }, + { "name": "rear-bracer", "bone": "rear-bracer", "attachment": "rear-bracer" }, + { "name": "gun", "bone": "gun", "attachment": "gun" }, + { "name": "rear-foot", "bone": "rear-foot", "attachment": "rear-foot" }, + { "name": "rear-thigh", "bone": "rear-thigh", "attachment": "rear-thigh" }, + { "name": "rear-shin", "bone": "rear-shin", "attachment": "rear-shin" }, + { "name": "neck", "bone": "neck", "attachment": "neck" }, + { "name": "torso", "bone": "torso", "attachment": "torso" }, + { "name": "front-upper-arm", "bone": "front-upper-arm", "attachment": "front-upper-arm" }, + { "name": "head", "bone": "head", "attachment": "head" }, + { "name": "eye", "bone": "head", "attachment": "eye-indifferent" }, + { "name": "front-thigh", "bone": "front-thigh", "attachment": "front-thigh" }, + { "name": "front-foot", "bone": "front-foot", "attachment": "front-foot" }, + { "name": "front-shin", "bone": "front-shin", "attachment": "front-shin" }, + { "name": "mouth", "bone": "head", "attachment": "mouth-smile" }, + { "name": "goggles", "bone": "head", "attachment": "goggles" }, + { "name": "front-bracer", "bone": "front-bracer", "attachment": "front-bracer" }, + { "name": "front-fist", "bone": "front-fist", "attachment": "front-fist-closed" }, + { "name": "muzzle", "bone": "gun-tip", "blend": "additive" }, + { "name": "head-bb", "bone": "head" } +], +"skins": [ + { + "name": "default", + "attachments": { + "eye": { + "eye-indifferent": { "x": 85.72, "y": -28.18, "rotation": -70.63, "width": 93, "height": 89 }, + "eye-surprised": { "x": 85.72, "y": -28.18, "rotation": -70.63, "width": 93, "height": 89 } + }, + "front-bracer": { + "front-bracer": { "x": 12.03, "y": -1.68, "rotation": 79.6, "width": 58, "height": 80 } + }, + "front-fist": { + "front-fist-closed": { "x": 35.5, "y": 6, "rotation": 67.16, "width": 75, "height": 82 }, + "front-fist-open": { "x": 39.57, "y": 7.76, "rotation": 67.16, "width": 86, "height": 87 } + }, + "front-foot": { + "front-foot": { "x": 29.52, "y": 7.84, "rotation": 18.69, "width": 126, "height": 69 } + }, + "front-shin": { + "front-shin": { "x": 55.12, "y": -3.54, "rotation": 96.59, "width": 82, "height": 184 } + }, + "front-thigh": { + "front-thigh": { "x": 42.48, "y": 4.45, "rotation": 84.87, "width": 45, "height": 112 } + }, + "front-upper-arm": { + "front-upper-arm": { "x": 25.2, "y": 1.17, "rotation": 97.9, "width": 46, "height": 97 } + }, + "goggles": { + "goggles": { "x": 97.08, "y": 6.54, "rotation": -70.63, "width": 261, "height": 166 } + }, + "gun": { + "gun": { "x": 77.3, "y": 16.4, "rotation": 60.83, "width": 210, "height": 203 } + }, + "head": { + "head": { "x": 128.96, "y": 0.3, "rotation": -70.63, "width": 271, "height": 298 } + }, + "head-bb": { + "head": { + "type": "boundingbox", + "vertexCount": 6, + "vertices": [ -19.14, -70.3, 40.8, -118.07, 257.77, -115.62, 285.16, 57.18, 120.77, 164.95, -5.07, 76.95 ] + } + }, + "mouth": { + "mouth-grind": { "x": 23.69, "y": -32.24, "rotation": -70.63, "width": 93, "height": 59 }, + "mouth-oooo": { "x": 23.69, "y": -32.24, "rotation": -70.63, "width": 93, "height": 59 }, + "mouth-smile": { "x": 23.69, "y": -32.24, "rotation": -70.63, "width": 93, "height": 59 } + }, + "muzzle": { + "muzzle01": { + "x": 159.26, + "y": 5.83, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 133, + "height": 79 + }, + "muzzle02": { + "x": 191.23, + "y": 5.91, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 135, + "height": 84 + }, + "muzzle03": { + "x": 230.67, + "y": 6.02, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 166, + "height": 106 + }, + "muzzle04": { + "x": 218.54, + "y": 5.99, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15, + "width": 149, + "height": 90 + } + }, + "neck": { + "neck": { "x": 9.77, "y": -3.01, "rotation": -55.22, "width": 36, "height": 41 } + }, + "rear-bracer": { + "rear-bracer": { "x": 11.15, "y": -2.2, "rotation": 66.17, "width": 56, "height": 72 } + }, + "rear-foot": { + "rear-foot": { "x": 31.51, "y": 3.58, "rotation": 23.07, "width": 113, "height": 60 } + }, + "rear-shin": { + "rear-shin": { "x": 58.29, "y": -2.75, "rotation": 92.37, "width": 75, "height": 178 } + }, + "rear-thigh": { + "rear-thigh": { "x": 33.11, "y": -4.11, "rotation": 72.54, "width": 55, "height": 94 } + }, + "rear-upper-arm": { + "rear-upper-arm": { "x": 21.13, "y": 4.09, "rotation": 89.33, "width": 40, "height": 87 } + }, + "torso": { + "torso": { "x": 63.61, "y": 7.12, "rotation": -94.54, "width": 98, "height": 180 } + } + } + } +], +"events": { + "footstep": {} +}, +"animations": { + "aim": { + "bones": { + "front-fist": { + "rotate": [ + { "value": 36.08 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": -26.55 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "value": 62.31 } + ] + }, + "front-bracer": { + "rotate": [ + { "value": 9.11 } + ] + }, + "gun": { + "rotate": [ + { "value": -0.31 } + ] + } + } + }, + "death": { + "slots": { + "eye": { + "attachment": [ + { "name": "eye-surprised" }, + { "time": 0.4667, "name": "eye-indifferent" }, + { "time": 2.2333, "name": "eye-surprised" }, + { "time": 4.5333, "name": "eye-indifferent" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "name": "mouth-oooo" }, + { "time": 2.2333, "name": "mouth-grind" }, + { "time": 4.5333, "name": "mouth-oooo" } + ] + } + }, + "bones": { + "head": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.044, -2.83, 0.105, -14.97 ] + }, + { + "time": 0.1333, + "value": -21.89, + "curve": [ 0.158, -28.04, 0.2, -34.87 ] + }, + { + "time": 0.2333, + "value": -34.87, + "curve": [ 0.267, -34.87, 0.3, -34.22 ] + }, + { + "time": 0.3333, + "value": -33.33, + "curve": [ 0.356, -32.74, 0.374, -30.69 ] + }, + { + "time": 0.4, + "value": -27.7, + "curve": [ 0.433, -23.82, 0.467, -10.64 ] + }, + { + "time": 0.5, + "value": -10.64, + "curve": [ 0.522, -10.64, 0.544, -16.82 ] + }, + { + "time": 0.5667, + "value": -23.05, + "curve": [ 0.589, -29.28, 0.611, -49.33 ] + }, + { + "time": 0.6333, + "value": -55.92, + "curve": [ 0.678, -69.1, 0.722, -82.35 ] + }, + { + "time": 0.7667, + "value": -82.35, + "curve": [ 0.787, -78.36, 0.912, -75.47 ] + }, + { "time": 1, "value": -78.9 }, + { + "time": 2.2333, + "value": -78.72, + "curve": [ 2.289, -78.72, 2.345, -66.24 ] + }, + { + "time": 2.4, + "value": -58.4, + "curve": [ 2.434, -53.72, 2.468, -52.12 ] + }, + { + "time": 2.5, + "value": -51.96, + "curve": [ 2.683, -51.05, 2.856, -50.86 ] + }, + { + "time": 3.0333, + "value": -50.86, + "curve": [ 3.343, -50.86, 3.712, -53.09 ] + }, + { + "time": 3.9333, + "value": -55.94, + "curve": [ 4.2, -59.38, 4.463, -65.17 ] + }, + { + "time": 4.5333, + "value": -69.07, + "curve": [ 4.598, -72.69, 4.635, -81.74 ] + }, + { "time": 4.6667, "value": -85.29 } + ], + "scale": [ + { + "time": 0.5, + "curve": [ 0.511, 1, 0.522, 1.041, 0.511, 1, 0.522, 0.953 ] + }, + { + "time": 0.5333, + "x": 1.041, + "y": 0.953, + "curve": [ 0.556, 1.041, 0.589, 1.038, 0.544, 0.953, 0.589, 0.959 ] + }, + { + "time": 0.6, + "x": 1.033, + "y": 0.966, + "curve": [ 0.633, 1.018, 0.667, 0.989, 0.633, 0.989, 0.667, 1.014 ] + }, + { + "time": 0.7, + "x": 0.989, + "y": 1.014, + "curve": [ 0.733, 0.989, 0.8, 1, 0.733, 1.014, 0.8, 1 ] + }, + { "time": 0.8333 } + ] + }, + "neck": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.033, -2.83, 0.1, 12.35 ] + }, + { + "time": 0.1333, + "value": 12.35, + "curve": [ 0.158, 12.35, 0.267, 2.18 ] + }, + { + "time": 0.3333, + "value": -8.48, + "curve": [ 0.389, -17.37, 0.444, -46.28 ] + }, + { + "time": 0.5, + "value": -46.28, + "curve": [ 0.522, -46.28, 0.551, -12.18 ] + }, + { + "time": 0.5667, + "value": -2.91, + "curve": [ 0.591, 11.16, 0.611, 20.82 ] + }, + { + "time": 0.6333, + "value": 23.43, + "curve": [ 0.756, 37.76, 0.878, 47.9 ] + }, + { + "time": 1, + "value": 47.91, + "curve": [ 1.411, 47.95, 1.935, 47.95 ] + }, + { + "time": 2.2333, + "value": 47.95, + "curve": [ 2.322, 47.95, 2.432, 19.53 ] + }, + { + "time": 2.5, + "value": 18.51, + "curve": [ 2.666, 16, 2.767, 14.59 ] + }, + { + "time": 2.9, + "value": 14.59, + "curve": [ 3.156, 14.59, 3.425, 14.72 ] + }, + { + "time": 3.6667, + "value": 15.23, + "curve": [ 4.026, 16, 4.28, 17.21 ] + }, + { + "time": 4.4667, + "value": 18.51, + "curve": [ 4.527, 18.71, 4.61, 45.05 ] + }, + { "time": 4.6667, "value": 47.95 } + ] + }, + "torso": { + "rotate": [ + { + "value": -8.62, + "curve": [ 0.031, -16.41, 0.1, -26.52 ] + }, + { + "time": 0.1333, + "value": -26.52, + "curve": [ 0.167, -26.52, 0.233, 3.45 ] + }, + { + "time": 0.2667, + "value": 21.92, + "curve": [ 0.326, 54.76, 0.422, 108.54 ] + }, + { + "time": 0.5, + "value": 108.54, + "curve": [ 0.522, 108.54, 0.559, 79.42 ] + }, + { + "time": 0.5667, + "value": 76.67, + "curve": [ 0.577, 72.83, 0.633, 68.68 ] + }, + { + "time": 0.6667, + "value": 68.68, + "curve": [ 0.733, 68.68, 0.8, 74.71 ] + }, + { "time": 0.8667, "value": 74.71, "curve": "stepped" }, + { + "time": 2.3333, + "value": 74.71, + "curve": [ 2.58, 74.71, 2.79, 72.33 ] + }, + { + "time": 2.9667, + "value": 72, + "curve": [ 3.439, 71.12, 3.668, 70.89 ] + }, + { + "time": 4, + "value": 71.29, + "curve": [ 4.189, 71.52, 4.286, 72.55 ] + }, + { "time": 4.6667, "value": 74.71 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -35.85, + "curve": [ 0.024, -41.49, 0.089, -48.72 ] + }, + { + "time": 0.1333, + "value": -48.72, + "curve": [ 0.178, -48.72, 0.225, -18.52 ] + }, + { + "time": 0.2667, + "value": -2.77, + "curve": [ 0.313, 14.63, 0.356, 29.38 ] + }, + { + "time": 0.4, + "value": 42.91, + "curve": [ 0.411, 46.3, 0.422, 47.99 ] + }, + { + "time": 0.4333, + "value": 47.99, + "curve": [ 0.456, 47.99, 0.482, 40.58 ] + }, + { + "time": 0.5, + "value": 35.07, + "curve": [ 0.533, 24.91, 0.567, 12.21 ] + }, + { + "time": 0.6, + "value": 12.36, + "curve": [ 0.633, 12.52, 0.667, 35.68 ] + }, + { + "time": 0.7, + "value": 35.68, + "curve": [ 0.789, 35.68, 0.878, 20.08 ] + }, + { "time": 0.9667, "value": 12.28, "curve": "stepped" }, + { "time": 2.2333, "value": 12.28 }, + { + "time": 2.5667, + "value": 64.63, + "curve": [ 2.589, 66.48, 2.611, 69.77 ] + }, + { + "time": 2.6333, + "value": 70.2, + "curve": [ 2.756, 72.57, 2.878, 73.08 ] + }, + { + "time": 3, + "value": 73.04, + "curve": [ 3.189, 72.97, 3.378, 69.18 ] + }, + { + "time": 3.5667, + "value": 68.76, + "curve": [ 3.735, 68.38, 3.902, 72.6 ] + }, + { + "time": 4.0667, + "value": 72.12, + "curve": [ 4.224, 71.68, 4.378, 72.12 ] + }, + { + "time": 4.5333, + "value": 64.63, + "curve": [ 4.622, 60.34, 4.711, 42.63 ] + }, + { "time": 4.8, "value": 31.63 }, + { "time": 4.9333, "value": 10.72 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": -44.7, + "curve": [ 0.044, -44.7, 0.089, 52.3 ] + }, + { + "time": 0.1333, + "value": 52.3, + "curve": [ 0.178, 52.3, 0.227, 48.52 ] + }, + { + "time": 0.2667, + "value": 41.27, + "curve": [ 0.332, 29.13, 0.356, 21.33 ] + }, + { + "time": 0.4, + "value": 21.33, + "curve": [ 0.511, 21.33, 0.577, 177.32 ] + }, + { + "time": 0.6667, + "value": 178.37, + "curve": [ 0.703, 178.79, 0.822, 158.2 ] + }, + { "time": 0.9, "value": 158.2 } + ], + "translate": [ + { "time": 0.4 }, + { "time": 0.9, "x": -32.41, "y": 0.65 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 21.88, + "curve": [ 0.048, 21.49, 0.089, 20.61 ] + }, + { + "time": 0.1333, + "value": 11.49, + "curve": [ 0.156, 6.92, 0.178, -12.78 ] + }, + { + "time": 0.2, + "value": -19.19, + "curve": [ 0.222, -25.6, 0.244, -26.96 ] + }, + { + "time": 0.2667, + "value": -26.96, + "curve": [ 0.311, -26.96, 0.356, -25.04 ] + }, + { + "time": 0.4, + "value": -15.9, + "curve": [ 0.433, -9.05, 0.467, 21.01 ] + }, + { + "time": 0.5, + "value": 21.01, + "curve": [ 0.533, 21.01, 0.567, -6.78 ] + }, + { + "time": 0.6, + "value": -18.23, + "curve": [ 0.622, -25.86, 0.644, -36.22 ] + }, + { + "time": 0.6667, + "value": -36.22, + "curve": [ 0.689, -36.22, 0.72, 1.23 ] + }, + { + "time": 0.7333, + "value": 10.31, + "curve": [ 0.761, 28.71, 0.822, 44.2 ] + }, + { + "time": 0.8667, + "value": 44.2, + "curve": [ 0.911, 44.2, 1, -14.97 ] + }, + { "time": 1, "value": -18.88, "curve": "stepped" }, + { + "time": 2.2333, + "value": -18.88, + "curve": [ 2.389, -18.88, 2.544, -1.96 ] + }, + { + "time": 2.7, + "value": -1.96, + "curve": [ 2.811, -1.96, 2.923, -10.35 ] + }, + { + "time": 3.0333, + "value": -10.35, + "curve": [ 3.224, -10.35, 3.411, -1.76 ] + }, + { + "time": 3.6, + "value": -1.76, + "curve": [ 3.922, -1.76, 4.244, -1.96 ] + }, + { + "time": 4.5667, + "value": -1.96, + "curve": [ 4.644, -1.96, 4.722, 34.31 ] + }, + { + "time": 4.8, + "value": 34.31, + "curve": [ 4.844, 34.31, 4.889, -1.06 ] + }, + { "time": 4.9333, "value": -18.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -2.33, + "curve": [ 0.044, -1.82, 0.089, -0.79 ] + }, + { + "time": 0.1333, + "value": -0.79, + "curve": [ 0.178, -0.79, 0.222, -12.86 ] + }, + { + "time": 0.2667, + "value": -12.86, + "curve": [ 0.322, -12.86, 0.378, -5.51 ] + }, + { + "time": 0.4333, + "value": -5.51, + "curve": [ 0.522, -5.51, 0.611, -23.93 ] + }, + { + "time": 0.7, + "value": -23.93, + "curve": [ 0.767, -23.93, 0.833, 6.31 ] + }, + { + "time": 0.9, + "value": 6.31, + "curve": [ 0.978, 6.31, 1.114, -2.63 ] + }, + { "time": 1.1333, "value": -5.63, "curve": "stepped" }, + { "time": 2.2333, "value": -5.63 }, + { "time": 2.4333, "value": -17.37 }, + { "time": 2.7, "value": 5.73, "curve": "stepped" }, + { + "time": 3.3667, + "value": 5.73, + "curve": [ 3.5, 5.73, 3.633, 1.93 ] + }, + { + "time": 3.7667, + "value": 1.93, + "curve": [ 3.867, 1.93, 3.967, 7.13 ] + }, + { + "time": 4.0667, + "value": 7.13, + "curve": [ 4.267, 7.13, 4.467, 5.73 ] + }, + { + "time": 4.6667, + "value": 5.73, + "curve": [ 4.678, 5.73, 4.732, 13.73 ] + }, + { + "time": 4.7667, + "value": 13.89, + "curve": [ 4.833, 14.19, 4.933, 4.95 ] + }, + { "time": 4.9333, "value": 3.65 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": 10.36 }, + { "time": 0.1333, "value": -23.12 }, + { "time": 0.2667, "value": -23.12 }, + { "time": 0.4, "value": -23.16, "curve": "stepped" }, + { "time": 0.4333, "value": -23.16 }, + { "time": 0.5667, "value": -23.2 } + ] + }, + "gun": { + "rotate": [ + { "value": -2.79 }, + { "time": 0.1333, "value": -24.58 } + ] + }, + "front-thigh": { + "rotate": [ + { + "curve": [ 0.052, 4.38, 0.089, 28.31 ] + }, + { + "time": 0.1333, + "value": 48.45, + "curve": [ 0.178, 68.6, 0.222, 99.39 ] + }, + { + "time": 0.2667, + "value": 120.87, + "curve": [ 0.311, 142.34, 0.356, 169.02 ] + }, + { + "time": 0.4, + "value": 177.3, + "curve": [ 0.433, 183.51, 0.467, 183.51 ] + }, + { + "time": 0.5, + "value": 183.51, + "curve": [ 0.544, 183.51, 0.589, 176.55 ] + }, + { + "time": 0.6333, + "value": 162.29, + "curve": [ 0.678, 148.03, 0.752, 108.37 ] + }, + { + "time": 0.7667, + "value": 97.94, + "curve": [ 0.819, 105.34, 0.856, 110.74 ] + }, + { + "time": 0.9, + "value": 110.74, + "curve": [ 0.944, 110.74, 1.016, 102.2 ] + }, + { "time": 1.0333, "value": 97.93 } + ] + }, + "front-shin": { + "rotate": [ + { + "curve": [ 0.044, 0.09, 0.1, -7.14 ] + }, + { + "time": 0.1333, + "value": -14.67, + "curve": [ 0.169, -22.83, 0.222, -43.77 ] + }, + { + "time": 0.2667, + "value": -43.77, + "curve": [ 0.311, -43.77, 0.344, -43.27 ] + }, + { + "time": 0.4, + "value": -33.94, + "curve": [ 0.433, -28.34, 0.467, 4.15 ] + }, + { + "time": 0.5, + "value": 9.2, + "curve": [ 0.533, 14.25, 0.567, 14.25 ] + }, + { + "time": 0.6, + "value": 14.25, + "curve": [ 0.733, 14.25, 0.867, 4.73 ] + }, + { "time": 1, "value": -0.03 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "curve": [ 0.044, 21.88, 0.089, 41.01 ] + }, + { + "time": 0.1333, + "value": 65.64, + "curve": [ 0.178, 90.28, 0.222, 127.15 ] + }, + { + "time": 0.2667, + "value": 147.79, + "curve": [ 0.311, 168.43, 0.356, 189.48 ] + }, + { + "time": 0.4, + "value": 189.48, + "curve": [ 0.433, 189.48, 0.473, 161.8 ] + }, + { + "time": 0.5, + "value": 142.56, + "curve": [ 0.542, 113.14, 0.589, 83.04 ] + }, + { + "time": 0.6, + "value": 78.15, + "curve": [ 0.613, 83.04, 0.733, 108.16 ] + }, + { + "time": 0.8, + "value": 108.16, + "curve": [ 0.878, 108.16, 1.009, 88.71 ] + }, + { "time": 1.0333, "value": 82.7 } + ] + }, + "rear-shin": { + "rotate": [ + { + "curve": [ 0.044, -19.59, 0.089, -58.76 ] + }, + { + "time": 0.1333, + "value": -58.76, + "curve": [ 0.178, -58.76, 0.222, -54.53 ] + }, + { + "time": 0.2667, + "value": -47.85, + "curve": [ 0.311, -41.16, 0.356, -33.24 ] + }, + { + "time": 0.4, + "value": -18.63, + "curve": [ 0.433, -7.68, 0.467, 28.83 ] + }, + { + "time": 0.5, + "value": 28.83, + "curve": [ 0.533, 28.83, 0.567, 15.17 ] + }, + { + "time": 0.6, + "value": 15.17, + "curve": [ 0.633, 15.17, 0.667, 16.17 ] + }, + { + "time": 0.7, + "value": 18.37, + "curve": [ 0.744, 21.32, 0.789, 27.27 ] + }, + { + "time": 0.8333, + "value": 30.61, + "curve": [ 0.878, 33.95, 0.922, 38.42 ] + }, + { + "time": 0.9667, + "value": 38.42, + "curve": [ 1.011, 38.42, 1.079, 17.39 ] + }, + { "time": 1.1, "value": 9.11 } + ] + }, + "rear-foot": { + "rotate": [ + { + "curve": [ 0.044, 0, 0.114, -5.44 ] + }, + { + "time": 0.1333, + "value": -11.63, + "curve": [ 0.158, -19.61, 0.222, -57.59 ] + }, + { + "time": 0.2667, + "value": -57.59, + "curve": [ 0.311, -57.59, 0.356, -45.6 ] + }, + { + "time": 0.4, + "value": -45.6, + "curve": [ 0.433, -45.6, 0.467, -65.99 ] + }, + { + "time": 0.5, + "value": -65.99, + "curve": [ 0.522, -65.99, 0.544, -21.7 ] + }, + { + "time": 0.5667, + "value": -21.7, + "curve": [ 0.6, -21.7, 0.633, -47.61 ] + }, + { + "time": 0.6667, + "value": -47.61, + "curve": [ 0.722, -47.61, 0.778, -25.68 ] + }, + { + "time": 0.8333, + "value": -15.6, + "curve": [ 0.878, -7.54, 0.922, 6.79 ] + }, + { + "time": 0.9667, + "value": 6.79, + "curve": [ 1.022, 6.79, 1.093, 2.23 ] + }, + { + "time": 1.1333, + "value": -6.82, + "curve": [ 1.165, -13.89, 1.178, -28.53 ] + }, + { + "time": 1.2, + "value": -28.53, + "curve": [ 1.267, -28.53, 1.333, -23.77 ] + }, + { "time": 1.4, "value": -23.77 } + ] + }, + "front-foot": { + "rotate": [ + { + "curve": [ 0.022, -21.9, 0.044, -65.7 ] + }, + { + "time": 0.0667, + "value": -65.7, + "curve": [ 0.089, -65.7, 0.111, -65.7 ] + }, + { + "time": 0.1333, + "value": -64.65, + "curve": [ 0.222, -60.43, 0.311, -52.48 ] + }, + { + "time": 0.4, + "value": -42.68, + "curve": [ 0.433, -39, 0.467, -33.17 ] + }, + { + "time": 0.5, + "value": -24.22, + "curve": [ 0.544, -12.29, 0.589, 19.98 ] + }, + { + "time": 0.6333, + "value": 19.98, + "curve": [ 0.656, 19.98, 0.678, 13.2 ] + }, + { + "time": 0.7, + "value": 2.45, + "curve": [ 0.733, -13.69, 0.767, -60.68 ] + }, + { + "time": 0.8, + "value": -60.68, + "curve": [ 0.878, -60.68, 0.956, 0.38 ] + }, + { + "time": 1.0333, + "value": 0.38, + "curve": [ 1.078, 0.38, 1.122, -31.77 ] + }, + { + "time": 1.1667, + "value": -31.77, + "curve": [ 1.211, -31.77, 1.256, -26.74 ] + }, + { "time": 1.3, "value": -24.22 } + ] + }, + "hip": { + "translate": [ + { + "curve": [ 0.081, -41.14, 0.178, -93.27, 0.038, 78.73, 0.156, 168.49 ] + }, + { + "time": 0.2667, + "x": -137.74, + "y": 169.66, + "curve": [ 0.333, -171.09, 0.4, -202.84, 0.377, 170.82, 0.467, 29.16 ] + }, + { + "time": 0.4667, + "x": -233.47, + "y": -76.63, + "curve": [ 0.5, -248.79, 0.533, -265.16, 0.521, -158.34, 0.516, -167.9 ] + }, + { + "time": 0.5667, + "x": -275.61, + "y": -209.28, + "curve": [ 0.589, -282.57, 0.608, -285.14, 0.572, -213.87, 0.611, -216.23 ] + }, + { + "time": 0.6333, + "x": -285.69, + "y": -216.23, + "curve": [ 0.713, -287.45, 0.789, -288.08, 0.711, -216.23, 0.812, -213.49 ] + }, + { + "time": 0.8667, + "x": -288.44, + "y": -209.28, + "curve": [ 0.911, -288.65, 0.965, -288.65, 0.919, -209.28, 0.967, -209.28 ] + }, + { "time": 1, "x": -288.65, "y": -209.28 } + ] + } + } + }, + "hit": { + "slots": { + "front-fist": { + "attachment": [ + { "time": 0.1667, "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "name": "mouth-grind" }, + { "time": 0.3333, "name": "mouth-smile" } + ] + } + }, + "bones": { + "torso": { + "rotate": [ + { "value": 56.42 }, + { "time": 0.3333, "value": 8.89 } + ] + }, + "neck": { + "rotate": [ + { "value": 35.39 }, + { "time": 0.2333, "value": 24.95 } + ] + }, + "head": { + "rotate": [ + { "value": 10.22 }, + { "time": 0.3333, "value": -41.3 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -310.93, + "curve": [ 0.127, -397.15, 0.248, -472.6 ] + }, + { "time": 0.3333, "value": -472.6 } + ], + "translate": [ + { "x": 7.23, "y": -13.13 } + ] + }, + "front-bracer": { + "rotate": [ + { "value": 36.99 }, + { "time": 0.3333, "value": -28.65 } + ] + }, + "front-fist": { + "rotate": [ + { "value": 13.59 }, + { "time": 0.3333, "value": 7.56 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 271.02, + "curve": [ 0.114, 297.63, 0.227, 322.97 ] + }, + { "time": 0.3333, "value": 344.16 } + ], + "translate": [ + { "time": 0.3333, "x": -0.1, "y": -0.46 } + ] + }, + "rear-bracer": { + "rotate": [ + {}, + { "time": 0.3333, "value": 40.03 } + ] + }, + "gun": { + "rotate": [ + { "value": 14.98 }, + { "time": 0.3333, "value": 39.76 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 90.94, + "curve": [ 0.076, 75.29, 0.144, 32.03 ] + }, + { "time": 0.3333, "value": 32.03 } + ], + "translate": [ + { "x": 7.21, "y": -4 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 40.52, + "curve": [ 0.099, 55.81, 0.197, 90.52 ] + }, + { "time": 0.3333, "value": 90.77 } + ], + "translate": [ + { "x": -1.96, "y": -0.32 } + ] + }, + "front-shin": { + "rotate": [ + { "value": -96.63 }, + { "time": 0.3333, "value": -15.13 } + ] + }, + "rear-shin": { + "rotate": [ + { "value": 8 }, + { "time": 0.3333, "value": -67.54 } + ] + }, + "front-foot": { + "rotate": [ + { "value": 5.4 }, + { "time": 0.3333, "value": -16.27 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": 2.67 }, + { "time": 0.3333, "value": -10.31 } + ] + }, + "hip": { + "translate": [ + { "x": -75.55, "y": -78.04 }, + { "time": 0.2333, "x": -36.48, "y": 12.42 }, + { "time": 0.3333, "x": -36.48, "y": -3 } + ] + } + } + }, + "idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "torso": { + "rotate": [ + { + "value": -16.11, + "curve": [ 0.057, -15.7, 0.268, -14.61 ] + }, + { + "time": 0.4333, + "value": -14.6, + "curve": [ 0.591, -14.59, 0.73, -15.81 ] + }, + { + "time": 0.8333, + "value": -16.63, + "curve": [ 0.915, -17.27, 1.074, -18.04 ] + }, + { + "time": 1.2333, + "value": -18.02, + "curve": [ 1.385, -18, 1.619, -16.57 ] + }, + { "time": 1.6667, "value": -16.11 } + ], + "translate": [ + { "x": -6.5 } + ], + "scale": [ + { + "curve": [ 0.156, 0.996, 0.525, 0.994, 0.106, 1.002, 0.525, 1.01 ] + }, + { + "time": 0.8333, + "x": 0.994, + "y": 1.01, + "curve": [ 1.15, 0.994, 1.52, 0.997, 1.15, 1.01, 1.519, 1.004 ] + }, + { "time": 1.6667 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -59.85, + "curve": [ 0.329, -59.85, 0.447, -64.99 ] + }, + { + "time": 0.6667, + "value": -64.99, + "curve": [ 0.997, -64.99, 1.417, -59.85 ] + }, + { "time": 1.6667, "value": -59.85 } + ], + "translate": [ + { + "x": -7.12, + "y": -8.24, + "curve": [ 0.167, -7.12, 0.5, -3.66, 0.167, -8.24, 0.5, -5.93 ] + }, + { + "time": 0.6667, + "x": -3.66, + "y": -5.93, + "curve": [ 0.917, -3.66, 1.417, -7.12, 0.917, -5.93, 1.417, -8.24 ] + }, + { "time": 1.6667, "x": -7.12, "y": -8.24 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 39.08, + "curve": [ 0.37, 38.67, 0.55, 32.29 ] + }, + { + "time": 0.7333, + "value": 32.29, + "curve": [ 0.967, 32.29, 1.433, 39.08 ] + }, + { "time": 1.6667, "value": 39.08 } + ], + "translate": [ + { + "x": -1.83, + "y": -6.48, + "curve": [ 0.167, -1.83, 0.5, 0.35, 0.167, -6.48, 0.447, -4.92 ] + }, + { + "time": 0.6667, + "x": 0.35, + "y": -4.92, + "curve": [ 0.917, 0.35, 1.417, -1.83, 0.917, -4.92, 1.417, -6.48 ] + }, + { "time": 1.6667, "x": -1.83, "y": -6.48 } + ] + }, + "neck": { + "rotate": [ + { + "curve": [ 0.167, 0, 0.5, 2.39 ] + }, + { + "time": 0.6667, + "value": 2.39, + "curve": [ 0.917, 2.39, 1.417, 0 ] + }, + { "time": 1.6667 } + ], + "translate": [ + { "x": -1.89, "y": -4.76 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 0.65, + "curve": [ 0.157, 0.6, 0.372, -4.31 ] + }, + { + "time": 0.6667, + "value": -4.34, + "curve": [ 1.262, -4.34, 1.32, 0.65 ] + }, + { "time": 1.6667, "value": 0.65 } + ], + "translate": [ + { "x": -13.4, "y": 6.7 } + ], + "scale": [ + { + "x": 0.945, + "curve": [ 0.157, 0.945, 0.372, 0.917, 0.157, 1, 0.372, 1 ] + }, + { + "time": 0.6667, + "x": 0.917, + "curve": [ 1.262, 0.917, 1.32, 0.945, 1.262, 1, 1.32, 1 ] + }, + { "time": 1.6667, "x": 0.945 } + ] + }, + "front-shin": { + "rotate": [ + { "value": -19.59 } + ], + "scale": [ + { + "curve": [ 0.157, 1, 0.372, 0.994, 0.157, 1, 0.372, 1 ] + }, + { + "time": 0.6667, + "x": 0.994, + "curve": [ 1.262, 0.994, 1.32, 1, 1.262, 1, 1.32, 1 ] + }, + { "time": 1.6667 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 30.51, + "curve": [ 0.157, 30.6, 0.372, 40.09 ] + }, + { + "time": 0.6667, + "value": 40.15, + "curve": [ 1.262, 40.14, 1.32, 30.51 ] + }, + { "time": 1.6667, "value": 30.51 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -24.14, + "curve": [ 0.157, -24.33, 0.372, -43.64 ] + }, + { + "time": 0.6667, + "value": -43.77, + "curve": [ 1.262, -43.76, 1.32, -23.83 ] + }, + { "time": 1.6667, "value": -23.83 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 4.83, + "curve": [ 0.157, 4.88, 0.372, 10.02 ] + }, + { + "time": 0.6667, + "value": 10.05, + "curve": [ 1.262, 10.05, 1.32, 5.14 ] + }, + { "time": 1.6667, "value": 5.14 } + ], + "scale": [ + { "x": 0.755, "y": 1.31 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -7.65, + "curve": [ 0.157, -7.54, 0.372, 3.78 ] + }, + { + "time": 0.6667, + "value": 3.85, + "curve": [ 1.262, 3.84, 1.32, -7.34 ] + }, + { "time": 1.6667, "value": -7.34 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": -17.16, + "curve": [ 0.167, -17.16, 0.447, -4.1 ] + }, + { + "time": 0.6667, + "value": -4.1, + "curve": [ 0.997, -4.1, 1.417, -17.16 ] + }, + { "time": 1.6667, "value": -17.16 } + ] + }, + "head": { + "rotate": [ + { + "value": -5.51, + "curve": [ 0.167, -5.51, 0.7, -3.12 ] + }, + { + "time": 0.8667, + "value": -3.12, + "curve": [ 1.117, -3.12, 1.417, -5.51 ] + }, + { "time": 1.6667, "value": -5.51 } + ], + "scale": [ + { + "curve": [ 0.217, 1, 0.546, 0.996, 0.217, 1, 0.546, 1.007 ] + }, + { + "time": 0.8667, + "x": 0.996, + "y": 1.007, + "curve": [ 1.171, 0.996, 1.467, 1, 1.171, 1.007, 1.467, 1 ] + }, + { "time": 1.6667 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 35.2, + "curve": [ 0.086, 36.03, 0.514, 40.31 ] + }, + { + "time": 0.6667, + "value": 40.3, + "curve": [ 0.859, 40.29, 0.969, 32.24 ] + }, + { + "time": 1.2, + "value": 32.31, + "curve": [ 1.401, 32.37, 1.561, 34.14 ] + }, + { "time": 1.6667, "value": 35.2 } + ] + }, + "gun": { + "rotate": [ + { + "curve": [ 0.167, 0, 0.581, -12.7 ] + }, + { + "time": 0.8667, + "value": -12.7, + "curve": [ 1.131, -12.7, 1.437, -0.11 ] + }, + { "time": 1.6667 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -6.85, + "curve": [ 0.181, -5.23, 0.5, -3.97 ] + }, + { + "time": 0.6667, + "value": -3.89, + "curve": [ 0.84, -3.81, 1.042, -9.89 ] + }, + { + "time": 1.2667, + "value": -9.76, + "curve": [ 1.428, -9.66, 1.537, -8.3 ] + }, + { "time": 1.6667, "value": -6.85 } + ], + "scale": [ + { + "curve": [ 0.167, 1, 0.5, 0.886, 0.167, 1, 0.5, 1.101 ] + }, + { + "time": 0.6667, + "x": 0.886, + "y": 1.101, + "curve": [ 0.917, 0.886, 1.417, 1, 0.917, 1.101, 1.417, 1 ] + }, + { "time": 1.6667 } + ] + }, + "hip": { + "translate": [ + { + "x": -6.64, + "y": -23.02, + "curve": [ 0.157, -6.51, 0.372, 6.19, 0.157, -23.13, 0.372, -34.93 ] + }, + { + "time": 0.6667, + "x": 6.28, + "y": -35.01, + "curve": [ 1.262, 6.27, 1.32, -6.64, 1.262, -35, 1.32, -23.02 ] + }, + { "time": 1.6667, "x": -6.64, "y": -23.02 } + ] + } + } + }, + "jump": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" }, + { "time": 0.1, "name": "front-fist-closed" }, + { "time": 0.8333, "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { + "value": 55.08, + "curve": [ 0.007, 46.66, 0.043, 26.3 ] + }, + { + "time": 0.0667, + "value": 22.84, + "curve": [ 0.1, 17.99, 0.165, 15.78 ] + }, + { + "time": 0.2333, + "value": 15.71, + "curve": [ 0.309, 15.63, 0.411, 36.56 ] + }, + { + "time": 0.5, + "value": 36.56, + "curve": [ 0.656, 36.56, 0.811, 33.41 ] + }, + { + "time": 0.9667, + "value": 26.43, + "curve": [ 1.011, 24.43, 1.056, 9.63 ] + }, + { + "time": 1.1, + "value": 9.63, + "curve": [ 1.122, 9.63, 1.144, 9.63 ] + }, + { + "time": 1.1667, + "value": 12.33, + "curve": [ 1.178, 13.68, 1.189, 47.62 ] + }, + { + "time": 1.2, + "value": 56.85, + "curve": [ 1.211, 66.08, 1.222, 67.7 ] + }, + { + "time": 1.2333, + "value": 67.72, + "curve": [ 1.261, 67.77, 1.322, 58.12 ] + }, + { "time": 1.3333, "value": 55.08 } + ], + "translate": [ + { + "x": -5.13, + "y": 11.55, + "curve": [ 0.422, -5.13, 0.733, -5.25, 0.422, 11.55, 0.733, 11.55 ] + }, + { + "time": 1.1, + "x": -5.25, + "y": 11.55, + "curve": [ 1.133, -5.25, 1.167, -4.54, 1.133, 11.55, 1.167, -1.07 ] + }, + { + "time": 1.2, + "x": -3.98, + "y": -1.07, + "curve": [ 1.211, -3.79, 1.222, -3.62, 1.211, -1.07, 1.222, 5.22 ] + }, + { + "time": 1.2333, + "x": -3.5, + "y": 5.73, + "curve": [ 1.245, -3.37, 1.289, -3.68, 1.245, 6.24, 1.283, 5.14 ] + }, + { + "time": 1.3, + "x": -4.1, + "y": 5.23, + "curve": [ 1.311, -4.52, 1.322, -4.99, 1.32, 5.32, 1.322, 9.78 ] + }, + { "time": 1.3333, "x": -5.13, "y": 11.55 } + ] + }, + "torso": { + "rotate": [ + { + "value": -45.57, + "curve": [ 0.022, -44.61, 0.03, -39.06 ] + }, + { + "time": 0.0667, + "value": -35.29, + "curve": [ 0.12, -29.77, 0.28, -19.95 ] + }, + { + "time": 0.4333, + "value": -19.95, + "curve": [ 0.673, -19.95, 0.871, -22.38 ] + }, + { + "time": 0.9667, + "value": -27.08, + "curve": [ 1.094, -33.33, 1.176, -44.93 ] + }, + { "time": 1.3333, "value": -45.57 } + ], + "translate": [ + { "x": -3.79, "y": -0.77 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 12.81, + "curve": [ 0.067, 12.81, 0.242, 67.88 ] + }, + { + "time": 0.2667, + "value": 74.11, + "curve": [ 0.314, 86.02, 0.454, 92.23 ] + }, + { + "time": 0.5667, + "value": 92.24, + "curve": [ 0.753, 92.26, 0.966, 67.94 ] + }, + { + "time": 1, + "value": 61.32, + "curve": [ 1.039, 53.75, 1.218, 12.68 ] + }, + { "time": 1.3333, "value": 12.81 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -115.64, + "curve": [ 0.067, -117.17, 0.125, -117.15 ] + }, + { + "time": 0.1667, + "value": -117.15, + "curve": [ 0.225, -117.15, 0.332, -108.76 ] + }, + { + "time": 0.4, + "value": -107.15, + "curve": [ 0.48, -105.26, 0.685, -103.49 ] + }, + { + "time": 0.7667, + "value": -101.97, + "curve": [ 0.826, -100.87, 0.919, -92.3 ] + }, + { + "time": 1, + "value": -92.28, + "curve": [ 1.113, -92.26, 1.297, -114.22 ] + }, + { "time": 1.3333, "value": -115.64 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -40.21, + "curve": [ 0.054, -35.46, 0.15, -31.12 ] + }, + { + "time": 0.2, + "value": -31.12, + "curve": [ 0.308, -31.12, 0.547, -80.12 ] + }, + { + "time": 0.6333, + "value": -96.56, + "curve": [ 0.697, -108.56, 0.797, -112.54 ] + }, + { + "time": 0.8667, + "value": -112.6, + "curve": [ 1.137, -112.84, 1.274, -49.19 ] + }, + { "time": 1.3333, "value": -40.21 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 20.54, + "curve": [ 0.054, 32.23, 0.192, 55.84 ] + }, + { + "time": 0.2333, + "value": 62.58, + "curve": [ 0.29, 71.87, 0.375, 79.28 ] + }, + { + "time": 0.4333, + "value": 79.18, + "curve": [ 0.555, 78.98, 0.684, 27.54 ] + }, + { + "time": 0.7333, + "value": 13.28, + "curve": [ 0.786, -1.85, 0.874, -24.76 ] + }, + { + "time": 1, + "value": -25.45, + "curve": [ 1.165, -26.36, 1.303, 9.1 ] + }, + { "time": 1.3333, "value": 20.54 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16, + "curve": [ 0.114, -39.59, 0.3, -45.61 ] + }, + { + "time": 0.4, + "value": -45.61, + "curve": [ 0.442, -45.61, 0.537, -21.54 ] + }, + { + "time": 0.5667, + "value": -15.4, + "curve": [ 0.592, -10.23, 0.692, 11.89 ] + }, + { + "time": 0.7333, + "value": 11.73, + "curve": [ 0.783, 11.54, 0.831, 1.8 ] + }, + { + "time": 0.8667, + "value": -5.78, + "curve": [ 0.897, -12.22, 0.901, -14.22 ] + }, + { + "time": 0.9333, + "value": -14.51, + "curve": [ 0.974, -14.89, 0.976, 10.38 ] + }, + { + "time": 1, + "value": 10.55, + "curve": [ 1.027, 10.74, 1.023, -8.44 ] + }, + { + "time": 1.0333, + "value": -8.42, + "curve": [ 1.059, -8.36, 1.074, 10.12 ] + }, + { + "time": 1.1, + "value": 10.22, + "curve": [ 1.168, 10.48, 1.27, -36.07 ] + }, + { "time": 1.3333, "value": -36.16 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.5, + "curve": [ 0.048, 36.1, 0.168, 20.45 ] + }, + { + "time": 0.3, + "value": 20.45, + "curve": [ 0.476, 20.45, 0.571, 33.76 ] + }, + { + "time": 0.6, + "value": 38.67, + "curve": [ 0.642, 45.8, 0.681, 57.44 ] + }, + { + "time": 0.7333, + "value": 62.91, + "curve": [ 0.829, 72.8, 0.996, 77.61 ] + }, + { + "time": 1.0333, + "value": 80.37, + "curve": [ 1.082, 83.94, 1.148, 90.6 ] + }, + { + "time": 1.2, + "value": 90.6, + "curve": [ 1.248, 90.46, 1.289, 44.58 ] + }, + { "time": 1.3333, "value": 40.5 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.022, 25.12, 0.187, -0.89 ] + }, + { + "time": 0.2, + "value": -2.52, + "curve": [ 0.257, -9.92, 0.372, -17.38 ] + }, + { + "time": 0.4333, + "value": -17.41, + "curve": [ 0.54, -17.47, 0.659, -16.91 ] + }, + { + "time": 0.7667, + "value": -12.1, + "curve": [ 0.907, -5.79, 1.025, 14.58 ] + }, + { + "time": 1.1, + "value": 20.58, + "curve": [ 1.191, 27.85, 1.283, 29.67 ] + }, + { "time": 1.3333, "value": 29.67 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.88, + "curve": [ 0.104, 11.82, 0.179, 11.15 ] + }, + { + "time": 0.2, + "value": 10.08, + "curve": [ 0.255, 7.29, 0.405, -8.15 ] + }, + { + "time": 0.4333, + "value": -9.35, + "curve": [ 0.508, -12.48, 0.595, -13.14 ] + }, + { + "time": 0.6667, + "value": -12.61, + "curve": [ 0.714, -12.26, 0.815, -5.57 ] + }, + { + "time": 0.8333, + "value": -4.08, + "curve": [ 0.883, -0.07, 1.011, 10.6 ] + }, + { + "time": 1.1, + "value": 15.01, + "curve": [ 1.178, 18.87, 1.279, 20.64 ] + }, + { "time": 1.3333, "value": 20.73 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.14, + "curve": [ 0.063, 13.1, 0.222, -20.78 ] + }, + { + "time": 0.3333, + "value": -20.78, + "curve": [ 0.467, -20.78, 0.6, 7.26 ] + }, + { + "time": 0.7333, + "value": 11.44, + "curve": [ 0.811, 13.88, 0.889, 13.88 ] + }, + { + "time": 0.9667, + "value": 13.88, + "curve": [ 1.044, 13.88, 1.122, 7.56 ] + }, + { + "time": 1.2, + "value": 7.56, + "curve": [ 1.244, 7.56, 1.289, 11.28 ] + }, + { "time": 1.3333, "value": 13.14 } + ], + "scale": [ + { + "curve": [ 0.041, 1, 0.052, 0.962, 0.041, 1, 0.052, 1.137 ] + }, + { + "time": 0.1, + "x": 0.954, + "y": 1.137, + "curve": [ 0.202, 0.962, 0.318, 1, 0.202, 1.137, 0.252, 1.002 ] + }, + { "time": 0.4667 }, + { + "time": 1.0667, + "x": 1.002, + "curve": [ 1.092, 1.002, 1.126, 1.173, 1.092, 1, 1.128, 0.975 ] + }, + { + "time": 1.1667, + "x": 1.174, + "y": 0.973, + "curve": [ 1.204, 1.175, 1.233, 0.959, 1.206, 0.972, 1.227, 1.062 ] + }, + { + "time": 1.2667, + "x": 0.958, + "y": 1.063, + "curve": [ 1.284, 0.958, 1.311, 1, 1.288, 1.063, 1.311, 1 ] + }, + { "time": 1.3333 } + ] + }, + "hip": { + "translate": [ + { + "y": -45.46, + "curve": [ 0.042, -0.09, 0.15, 15.22, 0.031, 44.98, 0.123, 289.73 ] + }, + { + "time": 0.2, + "x": 15.22, + "y": 415.85, + "curve": [ 0.332, 15.22, 0.539, -34.52, 0.271, 532.93, 0.483, 753.87 ] + }, + { + "time": 0.7667, + "x": -34.52, + "y": 754.96, + "curve": [ 0.888, -34.52, 1.057, -21.95, 1.049, 754.54, 1.098, 379.84 ] + }, + { + "time": 1.1333, + "x": -15.67, + "y": 266.77, + "curve": [ 1.144, -14.77, 1.188, -10.53, 1.15, 213.72, 1.172, -61.32 ] + }, + { + "time": 1.2333, + "x": -6.53, + "y": -61.34, + "curve": [ 1.272, -3.22, 1.311, 0.05, 1.291, -61.36, 1.296, -44.8 ] + }, + { "time": 1.3333, "y": -45.46 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -74.19, + "curve": [ 0, -51.14, 0.042, -12.54 ] + }, + { + "time": 0.1667, + "value": -12.28, + "curve": [ 0.285, -12.32, 0.389, -51.96 ] + }, + { + "time": 0.5, + "value": -51.96, + "curve": [ 0.633, -51.96, 0.767, -40.17 ] + }, + { + "time": 0.9, + "value": -30.59, + "curve": [ 0.967, -25.8, 1.033, -16.01 ] + }, + { + "time": 1.1, + "value": -8.85, + "curve": [ 1.122, -6.46, 1.144, -1.91 ] + }, + { + "time": 1.1667, + "value": -1.91, + "curve": [ 1.178, -1.91, 1.189, -58.19 ] + }, + { + "time": 1.2, + "value": -72.71, + "curve": [ 1.211, -87.23, 1.222, -89.05 ] + }, + { + "time": 1.2333, + "value": -89.05, + "curve": [ 1.273, -89.05, 1.308, -79.55 ] + }, + { "time": 1.3333, "value": -74.19 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 15.88, + "curve": [ 0, 13.33, 0.05, -26.64 ] + }, + { + "time": 0.0667, + "value": -26.64, + "curve": [ 0.192, -26.64, 0.442, -11.77 ] + }, + { + "time": 0.5667, + "value": -11.77, + "curve": [ 0.692, -11.77, 0.942, -19.36 ] + }, + { + "time": 1.0667, + "value": -19.36, + "curve": [ 1.089, -19.36, 1.127, -67.74 ] + }, + { + "time": 1.1667, + "value": -63.62, + "curve": [ 1.178, -62.51, 1.189, 5.83 ] + }, + { + "time": 1.2, + "value": 11.39, + "curve": [ 1.222, 22.51, 1.244, 22.51 ] + }, + { + "time": 1.2667, + "value": 22.51, + "curve": [ 1.289, 22.51, 1.333, 16.45 ] + }, + { "time": 1.3333, "value": 15.88 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -7.14, + "curve": [ 0.044, -17.32, 0.089, -37.67 ] + }, + { + "time": 0.1333, + "value": -37.67, + "curve": [ 0.311, -37.67, 0.521, -26.72 ] + }, + { + "time": 0.6667, + "value": -15.71, + "curve": [ 0.776, -7.49, 0.911, 14.92 ] + }, + { + "time": 1.0333, + "value": 14.92, + "curve": [ 1.133, 14.92, 1.233, 0.21 ] + }, + { "time": 1.3333, "value": -7.14 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.36, + "curve": [ 0.022, 16.28, 0.15, 30.81 ] + }, + { + "time": 0.2, + "value": 30.81, + "curve": [ 0.258, 30.81, 0.375, 13.26 ] + }, + { + "time": 0.4333, + "value": 13.26, + "curve": [ 0.508, 13.26, 0.658, 15.05 ] + }, + { + "time": 0.7333, + "value": 14.98, + "curve": [ 0.789, 14.94, 0.828, 13.62 ] + }, + { + "time": 0.8667, + "value": 12.72, + "curve": [ 0.887, 12.25, 0.984, 9.83 ] + }, + { + "time": 1.0333, + "value": 8.6, + "curve": [ 1.045, 8.31, 1.083, 7.55 ] + }, + { + "time": 1.1333, + "value": 7.13, + "curve": [ 1.175, 6.78, 1.283, 6.18 ] + }, + { "time": 1.3333, "value": 6.18 } + ] + } + }, + "events": [ + { "time": 1.2, "name": "footstep" } + ] + }, + "run": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { + "value": 49.77, + "curve": [ 0.007, 49.71, 0.022, 41.99 ] + }, + { + "time": 0.0333, + "value": 32.26, + "curve": [ 0.044, 22.54, 0.056, 0.1 ] + }, + { + "time": 0.0667, + "value": -8.56, + "curve": [ 0.078, -17.22, 0.089, -19.05 ] + }, + { + "time": 0.1, + "value": -19.71, + "curve": [ 0.144, -22.38, 0.189, -22.38 ] + }, + { + "time": 0.2333, + "value": -22.38, + "curve": [ 0.267, -22.38, 0.3, 36.57 ] + }, + { + "time": 0.3333, + "value": 54.69, + "curve": [ 0.367, 72.82, 0.4, 86.37 ] + }, + { + "time": 0.4333, + "value": 86.37, + "curve": [ 0.478, 86.37, 0.522, 46.94 ] + }, + { + "time": 0.5667, + "value": 46.94, + "curve": [ 0.589, 46.94, 0.652, 49.34 ] + }, + { "time": 0.6667, "value": 49.77 } + ], + "translate": [ + { + "x": -7.86, + "y": 10.34, + "curve": [ 0.036, -7.85, 0.123, -6.71, 0.056, 10.34, 0.108, 9.74 ] + }, + { + "time": 0.1667, + "x": -5.7, + "y": 7.99, + "curve": [ 0.22, -4.49, 0.295, -0.78, 0.236, 5.93, 0.28, 3.22 ] + }, + { + "time": 0.3333, + "x": 1.68, + "y": 3.19, + "curve": [ 0.358, 3.28, 0.449, 9.99, 0.384, 3.16, 0.449, 4.98 ] + }, + { + "time": 0.5, + "x": 9.99, + "y": 6.76, + "curve": [ 0.556, 10, 0.611, -7.86, 0.556, 8.69, 0.611, 10.34 ] + }, + { "time": 0.6667, "x": -7.86, "y": 10.34 } + ] + }, + "torso": { + "rotate": [ + { + "value": -38.65, + "curve": [ 0.022, -39.16, 0.067, -41.4 ] + }, + { + "time": 0.1, + "value": -41.4, + "curve": [ 0.156, -41.4, 0.211, -37.6 ] + }, + { + "time": 0.2667, + "value": -37.6, + "curve": [ 0.289, -37.6, 0.315, -38.2 ] + }, + { + "time": 0.3333, + "value": -38.63, + "curve": [ 0.369, -39.48, 0.434, -41.38 ] + }, + { + "time": 0.4667, + "value": -41.39, + "curve": [ 0.512, -41.39, 0.556, -37.69 ] + }, + { + "time": 0.6, + "value": -37.69, + "curve": [ 0.622, -37.69, 0.652, -38.3 ] + }, + { "time": 0.6667, "value": -38.65 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 17.72, + "curve": [ 0.025, 28.51, 0.067, 54.38 ] + }, + { + "time": 0.1, + "value": 54.38, + "curve": [ 0.144, 54.38, 0.189, 19.31 ] + }, + { + "time": 0.2333, + "value": 19.31, + "curve": [ 0.254, 19.31, 0.278, 32.87 ] + }, + { + "time": 0.3, + "value": 32.87, + "curve": [ 0.311, 32.87, 0.322, 32.87 ] + }, + { + "time": 0.3333, + "value": 28.23, + "curve": [ 0.344, 23.6, 0.356, 4.08 ] + }, + { + "time": 0.3667, + "value": -3.6, + "curve": [ 0.389, -18.95, 0.411, -38.43 ] + }, + { + "time": 0.4333, + "value": -40.85, + "curve": [ 0.478, -45.69, 0.522, -45.69 ] + }, + { + "time": 0.5667, + "value": -45.69, + "curve": [ 0.6, -45.69, 0.633, -7.24 ] + }, + { "time": 0.6667, "value": 17.72 } + ], + "translate": [ + { + "x": -13.59, + "y": 3.21, + "curve": [ 0.013, -12.85, 0.183, -8.55, 0.03, 4.05, 0.183, 6.17 ] + }, + { + "time": 0.2333, + "x": -8.55, + "y": 6.17, + "curve": [ 0.308, -8.55, 0.492, -19.75, 0.308, 6.17, 0.492, 0.61 ] + }, + { + "time": 0.5667, + "x": -19.75, + "y": 0.61, + "curve": [ 0.592, -19.75, 0.633, -15.46, 0.592, 0.61, 0.633, 2.28 ] + }, + { "time": 0.6667, "x": -13.59, "y": 3.21 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": 324.21, + "curve": [ 0.051, 363.15, 0.145, 449.66 ] + }, + { + "time": 0.2333, + "value": 449.66, + "curve": [ 0.28, 450.07, 0.324, 419.51 ] + }, + { + "time": 0.3333, + "value": 411.11, + "curve": [ 0.358, 390.19, 0.445, 293.13 ] + }, + { + "time": 0.5667, + "value": 292.23, + "curve": [ 0.599, 291.99, 0.633, 298.54 ] + }, + { "time": 0.6667, "value": 324.21 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 7.49, + "curve": [ 0.032, 2.15, 0.089, -2.82 ] + }, + { + "time": 0.1333, + "value": -2.8, + "curve": [ 0.186, -2.78, 0.221, 26.29 ] + }, + { + "time": 0.2333, + "value": 32.37, + "curve": [ 0.247, 39.19, 0.286, 61.45 ] + }, + { + "time": 0.3333, + "value": 61.58, + "curve": [ 0.371, 61.69, 0.42, 55.79 ] + }, + { + "time": 0.4667, + "value": 49.68, + "curve": [ 0.533, 40.96, 0.643, 13.39 ] + }, + { "time": 0.6667, "value": 7.49 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -10.96, + "curve": [ 0.014, -13.6, 0.036, -43.27 ] + }, + { + "time": 0.0667, + "value": -43.37, + "curve": [ 0.102, -43.49, 0.182, -28.46 ] + }, + { + "time": 0.2, + "value": -23.04, + "curve": [ 0.23, -13.87, 0.264, 3.86 ] + }, + { + "time": 0.3333, + "value": 3.7, + "curve": [ 0.38, 3.64, 0.489, -21.29 ] + }, + { + "time": 0.5667, + "value": -21.29, + "curve": [ 0.6, -21.29, 0.633, -10.96 ] + }, + { "time": 0.6667, "value": -10.96 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 35.32, + "curve": [ 0.028, 18.56, 0.128, -79.86 ] + }, + { + "time": 0.2333, + "value": -79.87, + "curve": [ 0.38, -79.88, 0.403, 63.25 ] + }, + { + "time": 0.5667, + "value": 64.13, + "curve": [ 0.607, 64.35, 0.633, 55.07 ] + }, + { "time": 0.6667, "value": 35.32 } + ], + "translate": [ + { + "x": -4.58, + "y": 0.93, + "curve": [ 0.044, -5.37, 0.169, -5.48, 0.044, 2.63, 0.169, 2.85 ] + }, + { + "time": 0.2333, + "x": -5.48, + "y": 2.85, + "curve": [ 0.346, -5.48, 0.475, -2.68, 0.346, 2.85, 0.475, -3.13 ] + }, + { + "time": 0.5667, + "x": -2.68, + "y": -3.13, + "curve": [ 0.611, -2.68, 0.633, -3.98, 0.611, -3.13, 0.633, -0.35 ] + }, + { "time": 0.6667, "x": -4.58, "y": 0.93 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": 17.03 }, + { + "time": 0.2333, + "value": -13.07, + "curve": [ 0.252, -16.08, 0.297, -19.37 ] + }, + { + "time": 0.3333, + "value": -19.38, + "curve": [ 0.435, -19.41, 0.522, 38.96 ] + }, + { + "time": 0.5667, + "value": 38.87, + "curve": [ 0.619, 38.76, 0.625, 24.64 ] + }, + { "time": 0.6667, "value": 17.03 } + ] + }, + "neck": { + "rotate": [ + { + "value": 10.23, + "curve": [ 0.024, 9.75, 0.075, 9.74 ] + }, + { + "time": 0.1, + "value": 9.74, + "curve": [ 0.125, 9.74, 0.208, 13.36 ] + }, + { + "time": 0.2333, + "value": 13.36, + "curve": [ 0.258, 13.36, 0.3, 10.88 ] + }, + { + "time": 0.3333, + "value": 10.3, + "curve": [ 0.367, 9.72, 0.408, 9.72 ] + }, + { + "time": 0.4333, + "value": 9.72, + "curve": [ 0.458, 9.72, 0.542, 13.36 ] + }, + { + "time": 0.5667, + "value": 13.36, + "curve": [ 0.592, 13.36, 0.633, 10.91 ] + }, + { "time": 0.6667, "value": 10.23 } + ] + }, + "head": { + "rotate": [ + { + "value": 8.93, + "curve": [ 0.033, 7.96, 0.065, 6.03 ] + }, + { + "time": 0.1, + "value": 6.03, + "curve": [ 0.146, 6.03, 0.189, 10.78 ] + }, + { + "time": 0.2333, + "value": 10.78, + "curve": [ 0.267, 10.78, 0.309, 9.94 ] + }, + { + "time": 0.3333, + "value": 8.93, + "curve": [ 0.358, 7.93, 0.388, 6.1 ] + }, + { + "time": 0.4333, + "value": 6.1, + "curve": [ 0.486, 6.1, 0.544, 10.76 ] + }, + { + "time": 0.6, + "value": 10.76, + "curve": [ 0.622, 10.76, 0.652, 9.58 ] + }, + { "time": 0.6667, "value": 8.93 } + ], + "scale": [ + { + "x": 0.992, + "y": 1.01, + "curve": [ 0.036, 0.991, 0.068, 0.991, 0.014, 1.013, 0.083, 1.026 ] + }, + { + "time": 0.1, + "x": 0.991, + "y": 1.026, + "curve": [ 0.128, 0.991, 0.205, 1.038, 0.128, 1.026, 0.197, 0.982 ] + }, + { + "time": 0.2333, + "x": 1.038, + "y": 0.982, + "curve": [ 0.272, 1.038, 0.305, 1.008, 0.262, 0.982, 0.311, 0.995 ] + }, + { + "time": 0.3333, + "curve": [ 0.351, 0.995, 0.417, 0.981, 0.359, 1.006, 0.417, 1.026 ] + }, + { + "time": 0.4333, + "x": 0.981, + "y": 1.026, + "curve": [ 0.467, 0.981, 0.533, 1.037, 0.467, 1.026, 0.533, 0.982 ] + }, + { + "time": 0.5667, + "x": 1.037, + "y": 0.982, + "curve": [ 0.592, 1.037, 0.636, 0.993, 0.592, 0.982, 0.64, 1.004 ] + }, + { "time": 0.6667, "x": 0.992, "y": 1.01 } + ] + }, + "gun": { + "rotate": [ + { + "value": 18.25, + "curve": [ 0.033, 19.24, 0.087, 20.25 ] + }, + { + "time": 0.1333, + "value": 20.19, + "curve": [ 0.168, 20.32, 0.254, -8.82 ] + }, + { + "time": 0.2667, + "value": -11.88, + "curve": [ 0.291, -17.91, 0.344, -24.11 ] + }, + { + "time": 0.4, + "value": -23.88, + "curve": [ 0.448, -23.69, 0.533, -15.47 ] + }, + { "time": 0.5667, "value": -8.69 }, + { "time": 0.6667, "value": 18.25 } + ] + }, + "hip": { + "translate": [ + { + "x": 0.63, + "y": -34.19, + "curve": [ 0.042, 0.39, 0.118, 7.62, 0.042, -33.83, 0.084, 20.04 ] + }, + { + "time": 0.1667, + "x": 7.61, + "y": 20.36, + "curve": [ 0.194, 7.6, 0.21, 5.06, 0.204, 20.65, 0.217, -8.69 ] + }, + { + "time": 0.2333, + "x": 1.68, + "y": -18.48, + "curve": [ 0.279, -4.99, 0.297, -5.64, 0.254, -31.08, 0.292, -34.55 ] + }, + { + "time": 0.3333, + "x": -5.76, + "y": -35, + "curve": [ 0.379, -5.9, 0.451, 6.8, 0.384, -35.56, 0.416, 17.6 ] + }, + { + "time": 0.5, + "x": 6.61, + "y": 17.01, + "curve": [ 0.536, 6.47, 0.545, 3.56, 0.533, 16.75, 0.548, -8.71 ] + }, + { + "time": 0.5667, + "x": 0.35, + "y": -18.81, + "curve": [ 0.597, -4.07, 0.633, 0.82, 0.584, -28.58, 0.633, -34.48 ] + }, + { "time": 0.6667, "x": 0.63, "y": -34.19 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -27.81, + "curve": [ 0.078, -27.81, 0.156, 17.7 ] + }, + { + "time": 0.2333, + "value": 17.7, + "curve": [ 0.256, 17.7, 0.278, 12.8 ] + }, + { + "time": 0.3, + "value": 12.8, + "curve": [ 0.311, 12.8, 0.322, 17.93 ] + }, + { + "time": 0.3333, + "value": 20.49, + "curve": [ 0.344, 20.49, 0.356, 36.91 ] + }, + { + "time": 0.3667, + "value": 33.49, + "curve": [ 0.378, 30.04, 0.389, 28.84 ] + }, + { + "time": 0.4, + "value": 19.93, + "curve": [ 0.411, 10.9, 0.422, -5.84 ] + }, + { + "time": 0.4333, + "value": -8.18, + "curve": [ 0.478, -17.39, 0.523, 4.88 ] + }, + { + "time": 0.5667, + "value": 2.21, + "curve": [ 0.6, 0.19, 0.633, -27.81 ] + }, + { "time": 0.6667, "value": -27.81 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 11.76, + "curve": [ 0.008, 11.76, 0.02, 19.97 ] + }, + { + "time": 0.0333, + "value": 20.38, + "curve": [ 0.044, 20.72, 0.056, 17.21 ] + }, + { + "time": 0.0667, + "value": 11.96, + "curve": [ 0.079, 6.01, 0.089, -24.56 ] + }, + { + "time": 0.1, + "value": -25.8, + "curve": [ 0.144, -30.78, 0.189, -30.78 ] + }, + { + "time": 0.2333, + "value": -30.78, + "curve": [ 0.267, -30.78, 0.3, -29.2 ] + }, + { + "time": 0.3333, + "value": -24.64, + "curve": [ 0.389, -17.03, 0.444, -0.27 ] + }, + { + "time": 0.5, + "value": 5.74, + "curve": [ 0.556, 11.76, 0.633, 11.76 ] + }, + { "time": 0.6667, "value": 11.76 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -66.44, + "curve": [ 0.011, -66.44, 0.022, -65.11 ] + }, + { + "time": 0.0333, + "value": -58, + "curve": [ 0.044, -50.9, 0.056, -28.78 ] + }, + { + "time": 0.0667, + "value": -23.84, + "curve": [ 0.078, -18.9, 0.089, -18.9 ] + }, + { + "time": 0.1, + "value": -18.9, + "curve": [ 0.144, -18.9, 0.189, -66.55 ] + }, + { + "time": 0.2333, + "value": -85.8, + "curve": [ 0.267, -100.25, 0.3, -120 ] + }, + { + "time": 0.3333, + "value": -120, + "curve": [ 0.367, -120, 0.4, -116.77 ] + }, + { + "time": 0.4333, + "value": -103.62, + "curve": [ 0.456, -94.85, 0.478, -73.54 ] + }, + { + "time": 0.5, + "value": -54.26, + "curve": [ 0.522, -34.99, 0.544, -5.08 ] + }, + { + "time": 0.5667, + "value": -5.08, + "curve": [ 0.589, -5.08, 0.611, -31.56 ] + }, + { + "time": 0.6333, + "value": -45.19, + "curve": [ 0.644, -52.01, 0.656, -66.44 ] + }, + { "time": 0.6667, "value": -66.44 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -99.91, + "curve": [ 0.048, -99.45, 0.067, -87.25 ] + }, + { + "time": 0.1, + "value": -72.41, + "curve": [ 0.144, -52.61, 0.189, 4.01 ] + }, + { + "time": 0.2333, + "value": 4.01, + "curve": [ 0.256, 4.01, 0.278, -32.4 ] + }, + { + "time": 0.3, + "value": -46.27, + "curve": [ 0.311, -53.2, 0.322, -58.41 ] + }, + { + "time": 0.3333, + "value": -58.41, + "curve": [ 0.367, -58.41, 0.4, -2.86 ] + }, + { + "time": 0.4333, + "value": -2.86, + "curve": [ 0.478, -2.86, 0.522, -61.56 ] + }, + { + "time": 0.5667, + "value": -80.05, + "curve": [ 0.6, -93.91, 0.632, -99.87 ] + }, + { "time": 0.6667, "value": -99.91 } + ] + }, + "gun-tip": { + "rotate": [ + { "time": 0.4333, "value": 12.93 } + ] + } + }, + "drawOrder": [ + { + "offsets": [ + { "slot": "head", "offset": -2 } + ] + } + ], + "events": [ + { "time": 0.2667, "name": "footstep" }, + { "time": 0.6, "name": "footstep" } + ] + }, + "shoot": { + "slots": { + "muzzle": { + "rgba": [ + { "time": 0.3667, "color": "ffffff00" } + ], + "attachment": [ + { "time": 0.1333, "name": "muzzle01" }, + { "time": 0.2, "name": "muzzle02" }, + { "time": 0.2667, "name": "muzzle03" }, + { "time": 0.3333, "name": "muzzle04" }, + { "time": 0.3667 } + ] + } + }, + "bones": { + "gun-tip": { + "translate": [ + { "time": 0.1333 }, + { "time": 0.2333, "x": 32.31, "y": 2.94 } + ] + }, + "gun": { + "rotate": [ + { "value": 1.91, "curve": "stepped" }, + { + "time": 0.1, + "value": 1.91, + "curve": [ 0.113, 4.95, 0.122, 6.56 ] + }, + { + "time": 0.1333, + "value": 6.56, + "curve": [ 0.167, 6.56, 0.2, -0.97 ] + }, + { + "time": 0.2333, + "value": -0.97, + "curve": [ 0.289, -0.97, 0.344, 0.95 ] + }, + { "time": 0.4, "value": 1.91 } + ], + "translate": [ + { "x": 7.95, "y": 5.85, "curve": "stepped" }, + { + "time": 0.1, + "x": 7.95, + "y": 5.85, + "curve": [ 0.167, 7.95, 0.204, -9.3, 0.167, 5.85, 0.204, -1.41 ] + }, + { + "time": 0.3, + "x": -9.3, + "y": -1.41, + "curve": [ 0.333, -9.3, 0.367, 7.95, 0.333, -1.41, 0.367, 5.85 ] + }, + { "time": 0.4, "x": 7.95, "y": 5.85 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": -30.47 } + ], + "translate": [ + { + "time": 0.1, + "curve": [ 0.156, -4.39, 0.204, -6, 0.167, -3.38, 0.204, -3.72 ] + }, + { "time": 0.3, "x": -6, "y": -3.72 }, + { "time": 0.4 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "value": 62.31 } + ], + "translate": [ + { + "time": 0.1, + "curve": [ 0.167, 0, 0.204, 2.81, 0.16, 11.74, 0.23, 11.7 ] + }, + { "time": 0.3, "x": 2.81, "y": 11.53 }, + { "time": 0.4 } + ] + } + } + }, + "walk": { + "bones": { + "hip": { + "rotate": [ + { "value": 0.94 } + ], + "translate": [ + { + "x": -2.86, + "y": -13.86, + "curve": [ 0.025, -2.84, 0.067, -2.82, 0.028, -19.14, 0.054, -31.19 ] + }, + { + "time": 0.1, + "x": -2.61, + "y": -31.36, + "curve": [ 0.143, -2.34, 0.202, -1.79, 0.152, -31.16, 0.213, -14.81 ] + }, + { + "time": 0.2667, + "x": -1.21, + "y": -7.12, + "curve": [ 0.308, -0.86, 0.345, -0.51, 0.306, -1.63, 0.341, 3.15 ] + }, + { + "time": 0.3667, + "x": -0.33, + "y": 3.15, + "curve": [ 0.41, 0.02, 0.458, 0.26, 0.427, 3.3, 0.481, -6.75 ] + }, + { + "time": 0.5, + "x": 0.26, + "y": -10.59, + "curve": [ 0.553, 0.26, 0.559, 0.2, 0.519, -14.41, 0.548, -31.74 ] + }, + { + "time": 0.6, + "x": -0.17, + "y": -31.56, + "curve": [ 0.632, -0.45, 0.683, -0.94, 0.646, -31.41, 0.688, -17.46 ] + }, + { + "time": 0.7333, + "x": -1.4, + "y": -8.62, + "curve": [ 0.783, -1.85, 0.833, -2.28, 0.77, -1.61, 0.831, 3.51 ] + }, + { + "time": 0.8667, + "x": -2.46, + "y": 3.48, + "curve": [ 0.901, -2.63, 0.967, -2.87, 0.913, 3.45, 0.967, -7.64 ] + }, + { "time": 1, "x": -2.86, "y": -13.86 } + ] + }, + "torso": { + "rotate": [ + { + "value": -20.72, + "curve": [ 0.013, -20.49, 0.071, -19.12 ] + }, + { + "time": 0.1333, + "value": -19.12, + "curve": [ 0.187, -19.12, 0.285, -22.22 ] + }, + { + "time": 0.3667, + "value": -22.22, + "curve": [ 0.405, -22.22, 0.491, -20.92 ] + }, + { + "time": 0.5, + "value": -20.71, + "curve": [ 0.51, -20.48, 0.582, -19.06 ] + }, + { + "time": 0.6333, + "value": -19.06, + "curve": [ 0.709, -19.07, 0.815, -22.22 ] + }, + { + "time": 0.8667, + "value": -22.22, + "curve": [ 0.908, -22.22, 0.981, -21.1 ] + }, + { "time": 1, "value": -20.72 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.78, + "curve": [ 0.025, 17.93, 0.071, 18.46 ] + }, + { + "time": 0.1333, + "value": 18.46, + "curve": [ 0.187, 18.46, 0.285, 17.34 ] + }, + { + "time": 0.3667, + "value": 17.34, + "curve": [ 0.405, 17.34, 0.47, 17.6 ] + }, + { + "time": 0.5, + "value": 17.79, + "curve": [ 0.518, 17.9, 0.582, 18.47 ] + }, + { + "time": 0.6333, + "value": 18.46, + "curve": [ 0.709, 18.45, 0.815, 17.32 ] + }, + { + "time": 0.8667, + "value": 17.32, + "curve": [ 0.908, 17.32, 0.971, 17.57 ] + }, + { "time": 1, "value": 17.78 } + ] + }, + "head": { + "rotate": [ + { + "value": -12.23, + "curve": [ 0.061, -12.23, 0.191, -7.45 ] + }, + { + "time": 0.2667, + "value": -7.43, + "curve": [ 0.341, -7.42, 0.421, -12.23 ] + }, + { + "time": 0.5, + "value": -12.23, + "curve": [ 0.567, -12.26, 0.694, -7.46 ] + }, + { + "time": 0.7667, + "value": -7.47, + "curve": [ 0.853, -7.49, 0.943, -12.23 ] + }, + { "time": 1, "value": -12.23 } + ], + "scale": [ + { + "curve": [ 0.039, 1, 0.084, 0.991, 0.039, 1, 0.084, 1.019 ] + }, + { + "time": 0.1333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.205, 0.991, 0.318, 1.019, 0.205, 1.019, 0.337, 0.992 ] + }, + { + "time": 0.4, + "x": 1.019, + "y": 0.992, + "curve": [ 0.456, 1.019, 0.494, 1.001, 0.483, 0.991, 0.493, 0.999 ] + }, + { + "time": 0.5, + "curve": [ 0.508, 0.998, 0.584, 0.991, 0.51, 1.002, 0.584, 1.019 ] + }, + { + "time": 0.6333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.705, 0.991, 0.818, 1.019, 0.705, 1.019, 0.837, 0.992 ] + }, + { + "time": 0.9, + "x": 1.019, + "y": 0.992, + "curve": [ 0.956, 1.019, 0.955, 1, 0.983, 0.991, 0.955, 1 ] + }, + { "time": 1 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 41.41, + "curve": [ 0.033, 41.52, 0.075, 57.36 ] + }, + { + "time": 0.1, + "value": 57.36, + "curve": [ 0.142, 57.36, 0.249, 30.8 ] + }, + { + "time": 0.2667, + "value": 26.81, + "curve": [ 0.314, 16.08, 0.378, 5.4 ] + }, + { + "time": 0.4, + "value": 2.75, + "curve": [ 0.455, -3.75, 0.54, -12.39 ] + }, + { + "time": 0.6, + "value": -12.39, + "curve": [ 0.633, -12.39, 0.722, 21.07 ] + }, + { + "time": 0.7333, + "value": 25.71, + "curve": [ 0.751, 32.81, 0.824, 63.52 ] + }, + { + "time": 0.8667, + "value": 63.79, + "curve": [ 0.913, 64.09, 0.948, 41.49 ] + }, + { "time": 1, "value": 41.41 } + ], + "translate": [ + { + "x": 17.15, + "y": -0.09, + "curve": [ 0.178, 17.14, 0.295, -4.26, 0.009, -0.09, 0.475, 0.02 ] + }, + { + "time": 0.5, + "x": -4.26, + "y": 0.02, + "curve": [ 0.705, -4.27, 0.875, 17.16, 0.525, 0.02, 0.875, -0.09 ] + }, + { "time": 1, "x": 17.15, "y": -0.09 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": -40.72, + "curve": [ 0.026, -42.96, 0.075, -43 ] + }, + { + "time": 0.1, + "value": -43, + "curve": [ 0.142, -43, 0.239, 8.23 ] + }, + { + "time": 0.2667, + "value": 18.99, + "curve": [ 0.284, 25.64, 0.367, 38.72 ] + }, + { + "time": 0.4, + "value": 38.72, + "curve": [ 0.425, 38.72, 0.475, 18.7 ] + }, + { + "time": 0.5, + "value": 18.7, + "curve": [ 0.525, 18.7, 0.575, 31.73 ] + }, + { + "time": 0.6, + "value": 31.73, + "curve": [ 0.633, 31.73, 0.719, 15.2 ] + }, + { + "time": 0.7333, + "value": 11.21, + "curve": [ 0.767, 2.12, 0.851, -15.29 ] + }, + { + "time": 0.8667, + "value": -18.46, + "curve": [ 0.905, -26.32, 0.951, -35.33 ] + }, + { "time": 1, "value": -40.72 } + ], + "translate": [ + { + "x": -17.71, + "y": -4.63, + "curve": [ 0.028, -19.31, 0.04, -20.22, 0.027, -4.63, 0.036, 1.71 ] + }, + { + "time": 0.0667, + "x": -20.72, + "y": 1.6, + "curve": [ 0.082, -21, 0.087, -20.93, 0.082, 1.54, 0.091, 0.29 ] + }, + { + "time": 0.1, + "x": -20.95, + "y": 0.06, + "curve": [ 0.162, -21.05, 0.4, 7.79, 0.194, -2.43, 0.4, -1.9 ] + }, + { + "time": 0.5, + "x": 7.79, + "y": -1.94, + "curve": [ 0.519, 7.78, 0.542, 7.33, 0.517, -1.94, 0.54, 5.55 ] + }, + { + "time": 0.5667, + "x": 6.45, + "y": 5.4, + "curve": [ 0.587, 5.74, 0.721, -0.95, 0.587, 5.28, 0.732, -3.74 ] + }, + { + "time": 0.7667, + "x": -3.61, + "y": -4.14, + "curve": [ 0.855, -8.76, 0.942, -14.37, 0.814, -4.69, 0.944, -4.63 ] + }, + { "time": 1, "x": -17.71, "y": -4.63 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -14.27, + "curve": [ 0.021, -18.08, 0.058, -19.4 ] + }, + { + "time": 0.1, + "value": -19.4, + "curve": [ 0.238, -19.69, 0.337, 7.78 ] + }, + { + "time": 0.3667, + "value": 16.2, + "curve": [ 0.399, 25.42, 0.497, 60.19 ] + }, + { + "time": 0.6, + "value": 60.26, + "curve": [ 0.719, 60.13, 0.845, 27.61 ] + }, + { + "time": 0.8667, + "value": 22.45, + "curve": [ 0.892, 16.38, 0.967, -8.36 ] + }, + { "time": 1, "value": -14.27 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 13.57, + "curve": [ 0.022, 9.71, 0.147, -15.4 ] + }, + { + "time": 0.3667, + "value": -15.3, + "curve": [ 0.457, -15.28, 0.635, 30.8 ] + }, + { + "time": 0.8, + "value": 30.92, + "curve": [ 0.894, 30.82, 0.98, 18.35 ] + }, + { "time": 1, "value": 13.57 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -28.72, + "curve": [ 0.024, -31.74, 0.176, -43.4 ] + }, + { + "time": 0.3667, + "value": -43.6, + "curve": [ 0.403, -43.65, 0.47, -40.15 ] + }, + { + "time": 0.5, + "value": -35.63, + "curve": [ 0.547, -28.59, 0.624, -4.57 ] + }, + { + "time": 0.7333, + "value": -4.59, + "curve": [ 0.891, -4.62, 0.954, -24.28 ] + }, + { "time": 1, "value": -28.48 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.034, 30.94, 0.068, 32.05 ] + }, + { + "time": 0.1, + "value": 31.88, + "curve": [ 0.194, 31.01, 0.336, -0.11 ] + }, + { + "time": 0.3667, + "value": -7.11, + "curve": [ 0.421, -19.73, 0.53, -46.21 ] + }, + { + "time": 0.6, + "value": -45.75, + "curve": [ 0.708, -45.03, 0.844, -13.56 ] + }, + { + "time": 0.8667, + "value": -6.48, + "curve": [ 0.909, 6.59, 0.958, 24.21 ] + }, + { "time": 1, "value": 28.28 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.06, + "curve": [ 0.044, 11.16, 0.063, 11.49 ] + }, + { + "time": 0.1, + "value": 11.49, + "curve": [ 0.215, 11.49, 0.336, 2.92 ] + }, + { + "time": 0.3667, + "value": 0.84, + "curve": [ 0.416, -2.52, 0.498, -10.84 ] + }, + { + "time": 0.6, + "value": -10.83, + "curve": [ 0.762, -10.71, 0.845, -3.05 ] + }, + { + "time": 0.8667, + "value": -1.34, + "curve": [ 0.917, 2.54, 0.977, 8.81 ] + }, + { "time": 1, "value": 10.06 } + ] + }, + "gun": { + "rotate": [ + { + "value": -14.67, + "curve": [ 0.086, -14.67, 0.202, 8.31 ] + }, + { + "time": 0.2333, + "value": 12.14, + "curve": [ 0.279, 17.71, 0.391, 25.79 ] + }, + { + "time": 0.5, + "value": 25.77, + "curve": [ 0.631, 25.74, 0.694, 4.53 ] + }, + { + "time": 0.7333, + "value": -0.65, + "curve": [ 0.768, -5.21, 0.902, -14.4 ] + }, + { "time": 1, "value": -14.67 } + ] + }, + "gun-tip": { + "rotate": [ + { "time": 0.2333, "value": 0.11 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": 26.22 }, + { + "time": 0.0333, + "value": 28.94, + "curve": [ 0.05, 28.94, 0.081, 17.62 ] + }, + { + "time": 0.1, + "value": 12.68, + "curve": [ 0.121, 7.25, 0.239, -22.96 ] + }, + { + "time": 0.2667, + "value": -26.31, + "curve": [ 0.299, -30.12, 0.364, -35.52 ] + }, + { + "time": 0.4, + "value": -35.38, + "curve": [ 0.418, -35.31, 0.485, 1.14 ] + }, + { + "time": 0.5, + "value": 6.17, + "curve": [ 0.503, 7.08, 0.519, 11.27 ] + }, + { + "time": 0.5333, + "value": 11.15, + "curve": [ 0.545, 11.06, 0.552, 11.27 ] + }, + { "time": 0.5667, "value": 3.69 }, + { "time": 0.6, "value": 3.55 }, + { "time": 0.7, "value": 10.77 }, + { "time": 1, "value": 26.22 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -6.79, + "curve": [ 0.028, -6.79, 0.087, -49.32 ] + }, + { + "time": 0.1, + "value": -51.42, + "curve": [ 0.109, -52.92, 0.137, -55.37 ] + }, + { + "time": 0.1667, + "value": -55.35, + "curve": [ 0.188, -55.34, 0.238, -44.96 ] + }, + { + "time": 0.2667, + "value": -40.55, + "curve": [ 0.284, -37.93, 0.365, -23.14 ] + }, + { + "time": 0.4333, + "value": -22.85, + "curve": [ 0.524, -22.46, 0.585, -48.24 ] + }, + { + "time": 0.6, + "value": -54.5, + "curve": [ 0.618, -61.64, 0.714, -97.51 ] + }, + { + "time": 0.7333, + "value": -102.65, + "curve": [ 0.749, -106.84, 0.768, -109.78 ] + }, + { + "time": 0.8, + "value": -109.78, + "curve": [ 0.818, -109.78, 0.859, -94.44 ] + }, + { + "time": 0.8667, + "value": -87.74, + "curve": [ 0.874, -81.52, 0.969, -6.79 ] + }, + { "time": 1, "value": -6.79 } + ], + "scale": [ + {}, + { "time": 0.0333, "x": 0.983 }, + { "time": 0.1, "x": 0.967, "y": 0.981 }, + { "time": 0.4333 }, + { "time": 0.5333, "x": 0.958, "y": 0.951 }, + { "time": 0.6333 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": 6.84, + "curve": [ 0.025, 6.84, 0.093, -24.57 ] + }, + { + "time": 0.1, + "value": -28.08, + "curve": [ 0.121, -38.52, 0.204, -92.35 ] + }, + { + "time": 0.2667, + "value": -91.68, + "curve": [ 0.309, -91.22, 0.379, -77.62 ] + }, + { + "time": 0.4, + "value": -68.91, + "curve": [ 0.43, -56.58, 0.474, 2.28 ] + }, + { + "time": 0.5, + "value": 2.63, + "curve": [ 0.538, 3.15, 0.567, -35.43 ] + }, + { + "time": 0.6, + "value": -35.18, + "curve": [ 0.634, -34.93, 0.665, -34.17 ] + }, + { + "time": 0.7, + "value": -30.64, + "curve": [ 0.718, -28.79, 0.857, -8.34 ] + }, + { + "time": 0.8667, + "value": -6.83, + "curve": [ 0.915, 0.75, 0.967, 6.84 ] + }, + { "time": 1, "value": 6.84 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 2.73, + "curve": [ 0.013, 4.28, 0.019, 5.27 ] + }, + { + "time": 0.0333, + "value": 5.15, + "curve": [ 0.045, 5.05, 0.063, -4.11 ] + }, + { + "time": 0.0667, + "value": -6.67, + "curve": [ 0.111, -6.72, 0.148, 3.78 ] + }, + { "time": 0.1667, "value": 4.67 }, + { "time": 0.2667, "value": 7.06 }, + { "time": 0.3333, "value": 8.97 }, + { "time": 0.4, "value": 11.15 }, + { + "time": 0.5333, + "value": 21.62, + "curve": [ 0.572, 21.62, 0.587, 17.19 ] + }, + { + "time": 0.6, + "value": 13.77, + "curve": [ 0.639, 3.33, 0.713, -20.85 ] + }, + { + "time": 0.7333, + "value": -27.3, + "curve": [ 0.757, -34.54, 0.766, -37.13 ] + }, + { + "time": 0.8, + "value": -38.01, + "curve": [ 0.828, -38.72, 0.976, -2.16 ] + }, + { "time": 1, "value": 2.73 } + ] + } + }, + "events": [ + { "name": "footstep" }, + { "time": 0.5333, "name": "footstep" } + ] + } +} +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-ess.skel b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-ess.skel new file mode 100644 index 0000000..59e6abf Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-ess.skel differ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-pma.atlas b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-pma.atlas new file mode 100644 index 0000000..ad3d77b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-pma.atlas @@ -0,0 +1,95 @@ +spineboy-pma.png + size: 1024, 256 + filter: Linear, Linear + pma: true + scale: 0.5 +crosshair + bounds: 352, 7, 45, 45 +eye-indifferent + bounds: 862, 105, 47, 45 +eye-surprised + bounds: 505, 79, 47, 45 +front-bracer + bounds: 826, 66, 29, 40 +front-fist-closed + bounds: 786, 65, 38, 41 +front-fist-open + bounds: 710, 51, 43, 44 + rotate: 90 +front-foot + bounds: 210, 6, 63, 35 +front-shin + bounds: 665, 128, 41, 92 + rotate: 90 +front-thigh + bounds: 2, 2, 23, 56 + rotate: 90 +front-upper-arm + bounds: 250, 205, 23, 49 +goggles + bounds: 665, 171, 131, 83 +gun + bounds: 798, 152, 105, 102 +head + bounds: 2, 27, 136, 149 +hoverboard-board + bounds: 2, 178, 246, 76 +hoverboard-thruster + bounds: 722, 96, 30, 32 + rotate: 90 +hoverglow-small + bounds: 275, 81, 137, 38 +mouth-grind + bounds: 614, 97, 47, 30 +mouth-oooo + bounds: 612, 65, 47, 30 +mouth-smile + bounds: 661, 64, 47, 30 +muzzle-glow + bounds: 382, 54, 25, 25 +muzzle-ring + bounds: 275, 54, 25, 105 + rotate: 90 +muzzle01 + bounds: 911, 95, 67, 40 + rotate: 90 +muzzle02 + bounds: 792, 108, 68, 42 +muzzle03 + bounds: 956, 171, 83, 53 + rotate: 90 +muzzle04 + bounds: 275, 7, 75, 45 +muzzle05 + bounds: 140, 3, 68, 38 +neck + bounds: 250, 182, 18, 21 +portal-bg + bounds: 140, 43, 133, 133 +portal-flare1 + bounds: 554, 65, 56, 30 +portal-flare2 + bounds: 759, 112, 57, 31 + rotate: 90 +portal-flare3 + bounds: 554, 97, 58, 30 +portal-shade + bounds: 275, 121, 133, 133 +portal-streaks1 + bounds: 410, 126, 126, 128 +portal-streaks2 + bounds: 538, 129, 125, 125 +rear-bracer + bounds: 857, 67, 28, 36 +rear-foot + bounds: 663, 96, 57, 30 +rear-shin + bounds: 414, 86, 38, 89 + rotate: 90 +rear-thigh + bounds: 756, 63, 28, 47 +rear-upper-arm + bounds: 60, 5, 20, 44 + rotate: 90 +torso + bounds: 905, 164, 49, 90 diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-pma.png b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-pma.png new file mode 100644 index 0000000..711fd83 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-pma.png differ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-pro.json b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-pro.json new file mode 100644 index 0000000..f3ba209 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-pro.json @@ -0,0 +1,8723 @@ +{ +"skeleton": { + "hash": "dr3Kr/vMgPA", + "spine": "4.2.22", + "x": -188.63, + "y": -7.94, + "width": 418.45, + "height": 686.2, + "images": "./images/", + "audio": "" +}, +"bones": [ + { "name": "root", "rotation": 0.05 }, + { "name": "hip", "parent": "root", "y": 247.27 }, + { "name": "crosshair", "parent": "root", "x": 302.83, "y": 569.45, "color": "ff3f00ff", "icon": "circle" }, + { + "name": "aim-constraint-target", + "parent": "hip", + "length": 26.24, + "rotation": 19.61, + "x": 1.02, + "y": 5.62, + "color": "abe323ff" + }, + { "name": "rear-foot-target", "parent": "root", "x": 61.91, "y": 0.42, "color": "ff3f00ff", "icon": "ik" }, + { "name": "rear-leg-target", "parent": "rear-foot-target", "x": -33.91, "y": 37.34, "color": "ff3f00ff", "icon": "ik" }, + { + "name": "rear-thigh", + "parent": "hip", + "length": 85.72, + "rotation": -72.54, + "x": 8.91, + "y": -5.63, + "color": "ff000dff" + }, + { + "name": "rear-shin", + "parent": "rear-thigh", + "length": 121.88, + "rotation": -19.83, + "x": 86.1, + "y": -1.33, + "color": "ff000dff" + }, + { + "name": "rear-foot", + "parent": "rear-shin", + "length": 51.58, + "rotation": 45.78, + "x": 121.46, + "y": -0.76, + "color": "ff000dff" + }, + { + "name": "back-foot-tip", + "parent": "rear-foot", + "length": 50.3, + "rotation": -0.85, + "x": 51.17, + "y": 0.24, + "inherit": "noRotationOrReflection", + "color": "ff000dff" + }, + { "name": "board-ik", "parent": "root", "x": -131.78, "y": 69.09, "color": "4c56ffff", "icon": "arrows" }, + { "name": "clipping", "parent": "root" }, + { + "name": "hoverboard-controller", + "parent": "root", + "rotation": -0.28, + "x": -329.69, + "y": 69.82, + "color": "ff0004ff", + "icon": "arrowsB" + }, + { "name": "exhaust1", "parent": "hoverboard-controller", "rotation": 3.02, "x": -249.68, "y": 53.39 }, + { "name": "exhaust2", "parent": "hoverboard-controller", "rotation": 26.34, "x": -191.6, "y": -22.92 }, + { + "name": "exhaust3", + "parent": "hoverboard-controller", + "rotation": -12.34, + "x": -236.03, + "y": 80.54, + "scaleX": 0.7847, + "scaleY": 0.7847 + }, + { "name": "portal-root", "parent": "root", "x": 12.9, "y": 328.54, "scaleX": 2.0334, "scaleY": 2.0334 }, + { "name": "flare1", "parent": "portal-root", "x": -6.34, "y": -161.57, "icon": "particles" }, + { "name": "flare10", "parent": "portal-root", "x": -6.34, "y": -161.57, "icon": "particles" }, + { "name": "flare2", "parent": "portal-root", "x": -6.34, "y": -161.57, "icon": "particles" }, + { "name": "flare3", "parent": "portal-root", "x": -6.34, "y": -161.57, "icon": "particles" }, + { "name": "flare4", "parent": "portal-root", "x": -6.34, "y": -161.57, "icon": "particles" }, + { "name": "flare5", "parent": "portal-root", "x": -6.34, "y": -161.57, "icon": "particles" }, + { "name": "flare6", "parent": "portal-root", "x": -6.34, "y": -161.57, "icon": "particles" }, + { "name": "flare7", "parent": "portal-root", "x": -6.34, "y": -161.57, "icon": "particles" }, + { "name": "flare8", "parent": "portal-root", "x": -6.34, "y": -161.57, "icon": "particles" }, + { "name": "flare9", "parent": "portal-root", "x": -6.34, "y": -161.57, "icon": "particles" }, + { + "name": "torso", + "parent": "hip", + "length": 42.52, + "rotation": 103.82, + "x": -1.62, + "y": 4.9, + "color": "e0da19ff" + }, + { "name": "torso2", "parent": "torso", "length": 42.52, "x": 42.52, "color": "e0da19ff" }, + { "name": "torso3", "parent": "torso2", "length": 42.52, "x": 42.52, "color": "e0da19ff" }, + { "name": "front-shoulder", "parent": "torso3", "rotation": 255.89, "x": 18.72, "y": 19.33, "color": "00ff04ff" }, + { "name": "front-upper-arm", "parent": "front-shoulder", "length": 69.45, "rotation": -87.51, "color": "00ff04ff" }, + { + "name": "front-bracer", + "parent": "front-upper-arm", + "length": 40.57, + "rotation": 18.3, + "x": 68.8, + "y": -0.68, + "color": "00ff04ff" + }, + { + "name": "front-fist", + "parent": "front-bracer", + "length": 65.39, + "rotation": 12.43, + "x": 40.57, + "y": 0.2, + "color": "00ff04ff" + }, + { "name": "front-foot-target", "parent": "root", "x": -13.53, "y": 0.04, "color": "ff3f00ff", "icon": "ik" }, + { "name": "front-leg-target", "parent": "front-foot-target", "x": -28.4, "y": 29.06, "color": "ff3f00ff", "icon": "ik" }, + { + "name": "front-thigh", + "parent": "hip", + "length": 74.81, + "rotation": -95.51, + "x": -17.46, + "y": -11.64, + "color": "00ff04ff" + }, + { + "name": "front-shin", + "parent": "front-thigh", + "length": 128.77, + "rotation": -2.21, + "x": 78.69, + "y": 1.6, + "color": "00ff04ff" + }, + { + "name": "front-foot", + "parent": "front-shin", + "length": 41.01, + "rotation": 51.27, + "x": 128.76, + "y": -0.34, + "color": "00ff04ff" + }, + { + "name": "front-foot-tip", + "parent": "front-foot", + "length": 56.03, + "rotation": -1.68, + "x": 41.42, + "y": -0.09, + "inherit": "noRotationOrReflection", + "color": "00ff04ff" + }, + { "name": "back-shoulder", "parent": "torso3", "rotation": -104.11, "x": 7.32, "y": -19.22, "color": "ff000dff" }, + { "name": "rear-upper-arm", "parent": "back-shoulder", "length": 51.94, "rotation": -65.45, "color": "ff000dff" }, + { "name": "rear-bracer", "parent": "rear-upper-arm", "length": 34.56, "rotation": 23.15, "x": 51.36, "color": "ff000dff" }, + { + "name": "gun", + "parent": "rear-bracer", + "length": 43.11, + "rotation": -5.43, + "x": 34.42, + "y": -0.45, + "color": "ff000dff" + }, + { "name": "gun-tip", "parent": "gun", "rotation": 7.1, "x": 200.78, "y": 52.5, "color": "ff0000ff" }, + { + "name": "neck", + "parent": "torso3", + "length": 25.45, + "rotation": -31.54, + "x": 42.46, + "y": -0.31, + "color": "e0da19ff" + }, + { + "name": "head", + "parent": "neck", + "length": 131.79, + "rotation": 26.1, + "x": 27.66, + "y": -0.26, + "color": "e0da19ff" + }, + { + "name": "hair1", + "parent": "head", + "length": 47.23, + "rotation": -49.1, + "x": 149.83, + "y": -59.77, + "color": "e0da19ff" + }, + { + "name": "hair2", + "parent": "hair1", + "length": 55.57, + "rotation": 50.42, + "x": 47.23, + "y": 0.19, + "color": "e0da19ff" + }, + { + "name": "hair3", + "parent": "head", + "length": 62.22, + "rotation": -32.17, + "x": 164.14, + "y": 3.68, + "color": "e0da19ff" + }, + { + "name": "hair4", + "parent": "hair3", + "length": 80.28, + "rotation": 83.71, + "x": 62.22, + "y": -0.04, + "color": "e0da19ff" + }, + { "name": "hoverboard-thruster-front", "parent": "hoverboard-controller", "rotation": -29.2, "x": 95.77, "y": -2.99, "inherit": "noRotationOrReflection" }, + { "name": "hoverboard-thruster-rear", "parent": "hoverboard-controller", "rotation": -29.2, "x": -76.47, "y": -4.88, "inherit": "noRotationOrReflection" }, + { "name": "hoverglow-front", "parent": "hoverboard-thruster-front", "rotation": 0.17, "x": -1.78, "y": -37.79 }, + { "name": "hoverglow-rear", "parent": "hoverboard-thruster-rear", "rotation": 0.17, "x": 1.06, "y": -35.66 }, + { + "name": "muzzle", + "parent": "rear-bracer", + "rotation": 3.06, + "x": 242.34, + "y": 34.26, + "color": "ffb900ff", + "icon": "muzzleFlash" + }, + { "name": "muzzle-ring", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring2", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring3", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring4", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "portal", "parent": "portal-root" }, + { "name": "portal-shade", "parent": "portal-root" }, + { "name": "portal-streaks1", "parent": "portal-root" }, + { "name": "portal-streaks2", "parent": "portal-root" }, + { "name": "side-glow1", "parent": "hoverboard-controller", "x": -110.56, "y": 2.62, "color": "000effff" }, + { + "name": "side-glow2", + "parent": "hoverboard-controller", + "x": -110.56, + "y": 2.62, + "scaleX": 0.738, + "scaleY": 0.738, + "color": "000effff" + }, + { "name": "head-control", "parent": "head", "x": 110.21, "color": "00a220ff", "icon": "arrows" } +], +"slots": [ + { "name": "portal-bg", "bone": "portal" }, + { "name": "portal-shade", "bone": "portal-shade" }, + { "name": "portal-streaks2", "bone": "portal-streaks2", "blend": "additive" }, + { "name": "portal-streaks1", "bone": "portal-streaks1", "blend": "additive" }, + { "name": "portal-flare8", "bone": "flare8", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare9", "bone": "flare9", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare10", "bone": "flare10", "color": "c3cbffff", "blend": "additive" }, + { "name": "clipping", "bone": "clipping" }, + { "name": "exhaust3", "bone": "exhaust3", "color": "5eb4ffff", "blend": "additive" }, + { "name": "hoverboard-thruster-rear", "bone": "hoverboard-thruster-rear" }, + { "name": "hoverboard-thruster-front", "bone": "hoverboard-thruster-front" }, + { "name": "hoverboard-board", "bone": "hoverboard-controller" }, + { "name": "side-glow1", "bone": "side-glow1", "color": "ff8686ff", "blend": "additive" }, + { "name": "side-glow3", "bone": "side-glow1", "color": "ff8686ff", "blend": "additive" }, + { "name": "side-glow2", "bone": "side-glow2", "color": "ff8686ff", "blend": "additive" }, + { "name": "hoverglow-front", "bone": "hoverglow-front", "color": "5eb4ffff", "blend": "additive" }, + { "name": "hoverglow-rear", "bone": "hoverglow-rear", "color": "5eb4ffff", "blend": "additive" }, + { "name": "exhaust1", "bone": "exhaust2", "color": "5eb4ffff", "blend": "additive" }, + { "name": "exhaust2", "bone": "exhaust1", "color": "5eb4ffff", "blend": "additive" }, + { "name": "rear-upper-arm", "bone": "rear-upper-arm", "attachment": "rear-upper-arm" }, + { "name": "rear-bracer", "bone": "rear-bracer", "attachment": "rear-bracer" }, + { "name": "gun", "bone": "gun", "attachment": "gun" }, + { "name": "rear-foot", "bone": "rear-foot", "attachment": "rear-foot" }, + { "name": "rear-thigh", "bone": "rear-thigh", "attachment": "rear-thigh" }, + { "name": "rear-shin", "bone": "rear-shin", "attachment": "rear-shin" }, + { "name": "neck", "bone": "neck", "attachment": "neck" }, + { "name": "torso", "bone": "torso", "attachment": "torso" }, + { "name": "front-upper-arm", "bone": "front-upper-arm", "attachment": "front-upper-arm" }, + { "name": "head", "bone": "head", "attachment": "head" }, + { "name": "eye", "bone": "head", "attachment": "eye-indifferent" }, + { "name": "front-thigh", "bone": "front-thigh", "attachment": "front-thigh" }, + { "name": "front-foot", "bone": "front-foot", "attachment": "front-foot" }, + { "name": "front-shin", "bone": "front-shin", "attachment": "front-shin" }, + { "name": "mouth", "bone": "head", "attachment": "mouth-smile" }, + { "name": "goggles", "bone": "head", "attachment": "goggles" }, + { "name": "front-bracer", "bone": "front-bracer", "attachment": "front-bracer" }, + { "name": "front-fist", "bone": "front-fist", "attachment": "front-fist-closed" }, + { "name": "muzzle", "bone": "muzzle" }, + { "name": "head-bb", "bone": "head" }, + { "name": "portal-flare1", "bone": "flare1", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare2", "bone": "flare2", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare3", "bone": "flare3", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare4", "bone": "flare4", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare5", "bone": "flare5", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare6", "bone": "flare6", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare7", "bone": "flare7", "color": "c3cbffff", "blend": "additive" }, + { "name": "crosshair", "bone": "crosshair" }, + { "name": "muzzle-glow", "bone": "gun-tip", "color": "ffffff00", "blend": "additive" }, + { "name": "muzzle-ring", "bone": "muzzle-ring", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring2", "bone": "muzzle-ring2", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring3", "bone": "muzzle-ring3", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring4", "bone": "muzzle-ring4", "color": "d8baffff", "blend": "additive" } +], +"ik": [ + { + "name": "aim-ik", + "order": 13, + "bones": [ "rear-upper-arm" ], + "target": "crosshair", + "mix": 0 + }, + { + "name": "aim-torso-ik", + "order": 8, + "bones": [ "aim-constraint-target" ], + "target": "crosshair" + }, + { + "name": "board-ik", + "order": 1, + "bones": [ "hoverboard-controller" ], + "target": "board-ik" + }, + { + "name": "front-foot-ik", + "order": 6, + "bones": [ "front-foot" ], + "target": "front-foot-target" + }, + { + "name": "front-leg-ik", + "order": 4, + "bones": [ "front-thigh", "front-shin" ], + "target": "front-leg-target", + "bendPositive": false + }, + { + "name": "rear-foot-ik", + "order": 7, + "bones": [ "rear-foot" ], + "target": "rear-foot-target" + }, + { + "name": "rear-leg-ik", + "order": 5, + "bones": [ "rear-thigh", "rear-shin" ], + "target": "rear-leg-target", + "bendPositive": false + } +], +"transform": [ + { + "name": "aim-front-arm-transform", + "order": 11, + "bones": [ "front-upper-arm" ], + "target": "aim-constraint-target", + "rotation": -180, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "aim-head-transform", + "order": 10, + "bones": [ "head" ], + "target": "aim-constraint-target", + "rotation": 84.3, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "aim-rear-arm-transform", + "order": 12, + "bones": [ "rear-upper-arm" ], + "target": "aim-constraint-target", + "x": 57.7, + "y": 56.4, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "aim-torso-transform", + "order": 9, + "bones": [ "torso" ], + "target": "aim-constraint-target", + "rotation": 69.5, + "shearY": -36, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "front-foot-board-transform", + "order": 2, + "bones": [ "front-foot-target" ], + "target": "hoverboard-controller", + "x": -69.8, + "y": 20.7, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "rear-foot-board-transform", + "order": 3, + "bones": [ "rear-foot-target" ], + "target": "hoverboard-controller", + "x": 86.6, + "y": 21.3, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "shoulder", + "bones": [ "back-shoulder" ], + "target": "front-shoulder", + "x": 40.17, + "y": -1.66, + "mixRotate": 0, + "mixX": -1, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "toes-board", + "order": 14, + "bones": [ "front-foot-tip", "back-foot-tip" ], + "target": "hoverboard-controller", + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + } +], +"skins": [ + { + "name": "default", + "attachments": { + "clipping": { + "clipping": { + "type": "clipping", + "end": "head-bb", + "vertexCount": 9, + "vertices": [ 66.76, 509.48, 19.98, 434.54, 5.34, 336.28, 22.19, 247.93, 77.98, 159.54, 182.21, -97.56, 1452.26, -99.8, 1454.33, 843.61, 166.57, 841.02 ], + "color": "ce3a3aff" + } + }, + "crosshair": { + "crosshair": { "width": 89, "height": 89 } + }, + "exhaust1": { + "hoverglow-small": { "scaleX": 0.4629, "scaleY": 0.8129, "rotation": -83.07, "width": 274, "height": 75 } + }, + "exhaust2": { + "hoverglow-small": { + "x": 0.01, + "y": -0.76, + "scaleX": 0.4208, + "scaleY": 0.8403, + "rotation": -89.25, + "width": 274, + "height": 75 + } + }, + "exhaust3": { + "hoverglow-small": { "scaleX": 0.4629, "scaleY": 0.8129, "rotation": -83.07, "width": 274, "height": 75 } + }, + "eye": { + "eye-indifferent": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 66, -36.8, -91.35, 0.3, 46, 73.41, -91.35, 0.7, 2, 66, -87.05, -13.11, 0.70968, 46, 23.16, -13.11, 0.29032, 2, 66, -12.18, 34.99, 0.82818, 46, 98.03, 34.99, 0.17182, 2, 66, 38.07, -43.25, 0.59781, 46, 148.28, -43.25, 0.40219 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 89 + }, + "eye-surprised": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 2, 66, -46.74, -89.7, 0.3, 46, 63.47, -89.7, 0.7, 2, 66, -77.58, -1.97, 0.71, 46, 32.63, -1.97, 0.29, 2, 66, 6.38, 27.55, 0.83, 46, 116.59, 27.55, 0.17, 2, 66, 37.22, -60.19, 0.6, 46, 147.44, -60.19, 0.4 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 89 + } + }, + "front-bracer": { + "front-bracer": { "x": 12.03, "y": -1.68, "rotation": 79.6, "width": 58, "height": 80 } + }, + "front-fist": { + "front-fist-closed": { "x": 35.5, "y": 6, "rotation": 67.16, "width": 75, "height": 82 }, + "front-fist-open": { "x": 39.57, "y": 7.76, "rotation": 67.16, "width": 86, "height": 87 } + }, + "front-foot": { + "front-foot": { + "type": "mesh", + "uvs": [ 0.59417, 0.23422, 0.62257, 0.30336, 0.6501, 0.37036, 0.67637, 0.38404, 0.72068, 0.4071, 0.76264, 0.42894, 1, 0.70375, 1, 1, 0.65517, 1, 0.46923, 0.99999, 0, 1, 0, 0.39197, 0.17846, 0, 0.49796, 0 ], + "triangles": [ 8, 9, 3, 4, 8, 3, 5, 8, 4, 6, 8, 5, 8, 6, 7, 11, 1, 10, 0, 12, 13, 0, 11, 12, 0, 1, 11, 9, 2, 3, 1, 2, 10, 9, 10, 2 ], + "vertices": [ 2, 38, 18.17, 41.57, 0.7896, 39, 12.46, 46.05, 0.2104, 2, 38, 24.08, 40.76, 0.71228, 39, 16.12, 41.34, 0.28772, 2, 38, 29.81, 39.98, 0.55344, 39, 19.67, 36.78, 0.44656, 2, 38, 32.81, 41.67, 0.38554, 39, 23, 35.89, 0.61446, 2, 38, 37.86, 44.52, 0.25567, 39, 28.61, 34.4, 0.74433, 2, 38, 42.65, 47.22, 0.17384, 39, 33.92, 32.99, 0.82616, 1, 39, 64.15, 14.56, 1, 1, 39, 64.51, -5.87, 1, 1, 39, 21.08, -6.64, 1, 2, 38, 44.67, -6.77, 0.5684, 39, -2.34, -6.97, 0.4316, 1, 38, 3.1, -48.81, 1, 1, 38, -26.73, -19.31, 1, 1, 38, -30.15, 15.69, 1, 1, 38, -1.84, 44.32, 1 ], + "hull": 14, + "edges": [ 14, 16, 16, 18, 18, 20, 4, 18, 20, 22, 24, 26, 22, 24, 12, 14, 10, 12, 2, 4, 2, 20, 4, 6, 6, 16, 2, 0, 0, 26, 6, 8, 8, 10 ], + "width": 126, + "height": 69 + } + }, + "front-shin": { + "front-shin": { + "type": "mesh", + "uvs": [ 0.90031, 0.05785, 1, 0.12828, 1, 0.21619, 0.9025, 0.31002, 0.78736, 0.35684, 0.78081, 0.39874, 0.77215, 0.45415, 0.77098, 0.51572, 0.84094, 0.63751, 0.93095, 0.7491, 0.95531, 0.7793, 0.78126, 0.87679, 0.5613, 1, 0.2687, 1, 0, 1, 0.00279, 0.96112, 0.01358, 0.81038, 0.02822, 0.60605, 0.08324, 0.45142, 0.18908, 0.31882, 0.29577, 0.2398, 0.30236, 0.14941, 0.37875, 0.05902, 0.53284, 0, 0.70538, 0, 0.41094, 0.71968, 0.40743, 0.54751, 0.41094, 0.4536, 0.4724, 0.35186, 0.33367, 0.27829, 0.50226, 0.31664, 0.65328, 0.67507, 0.60762, 0.52716, 0.6006, 0.45125, 0.62747, 0.37543, 0.6573, 0.3385, 0.27843, 0.32924, 0.18967, 0.45203, 0.16509, 0.58586, 0.18265, 0.7682, 0.50532, 0.24634, 0.59473, 0.17967, 0.60161, 0.10611, 0.51392, 0.04327, 0.72198, 0.28849, 0.82343, 0.20266, 0.86814, 0.11377, 0.79592, 0.04634, 0.44858, 0.15515, 0.25466, 0.96219, 0.53169, 0.9448, 0.7531, 0.8324 ], + "triangles": [ 24, 0, 47, 43, 23, 24, 47, 43, 24, 43, 22, 23, 42, 43, 47, 46, 47, 0, 42, 47, 46, 46, 0, 1, 48, 22, 43, 48, 43, 42, 21, 22, 48, 41, 48, 42, 45, 42, 46, 41, 42, 45, 46, 1, 2, 45, 46, 2, 40, 48, 41, 48, 20, 21, 29, 48, 40, 29, 20, 48, 44, 41, 45, 40, 41, 44, 3, 45, 2, 44, 45, 3, 30, 29, 40, 35, 30, 40, 36, 19, 20, 36, 20, 29, 44, 35, 40, 28, 29, 30, 4, 44, 3, 35, 44, 4, 34, 30, 35, 5, 35, 4, 34, 28, 30, 33, 28, 34, 37, 19, 36, 18, 19, 37, 27, 29, 28, 27, 28, 33, 36, 29, 27, 37, 36, 27, 5, 34, 35, 6, 34, 5, 33, 34, 6, 6, 32, 33, 7, 32, 6, 26, 37, 27, 38, 18, 37, 38, 37, 26, 17, 18, 38, 31, 32, 7, 31, 7, 8, 32, 25, 26, 38, 26, 25, 27, 33, 32, 32, 26, 27, 39, 38, 25, 17, 38, 39, 16, 17, 39, 51, 31, 8, 51, 8, 9, 11, 51, 9, 11, 9, 10, 31, 50, 25, 31, 25, 32, 50, 31, 51, 49, 39, 25, 49, 25, 50, 15, 16, 39, 49, 15, 39, 13, 49, 50, 14, 15, 49, 13, 14, 49, 12, 50, 51, 12, 51, 11, 13, 50, 12 ], + "vertices": [ -23.66, 19.37, -11.73, 28.98, 4.34, 30.83, 22.41, 24.87, 32.05, 16.48, 39.77, 16.83, 49.98, 17.3, 61.25, 18.5, 82.85, 26.78, 102.4, 36.46, 107.69, 39.09, 127.15, 26.97, 151.74, 11.65, 154.49, -12.18, 157.02, -34.07, 149.89, -34.66, 122.23, -36.97, 84.75, -40.09, 55.97, -38.88, 30.73, -33.05, 15.29, -26.03, -1.3, -27.41, -18.54, -23.09, -30.78, -11.79, -32.4, 2.27, 101.92, -6.52, 70.48, -10.44, 53.28, -12.14, 34.11, -9.28, 21.96, -22.13, 27.39, -7.59, 91.48, 12.28, 64.88, 5.44, 51.07, 3.26, 36.95, 3.85, 29.92, 5.5, 31.8, -25.56, 55.08, -30.19, 79.77, -29.37, 112.93, -24.09, 14.51, -8.83, 1.48, -2.95, -12.03, -3.94, -22.69, -12.41, 20.17, 9.71, 3.53, 16.16, -13.14, 17.93, -24.78, 10.62, -1.62, -15.37, 147.71, -14.13, 141.93, 8.07, 119.3, 23.74 ], + "hull": 25, + "edges": [ 8, 6, 6, 4, 4, 2, 2, 0, 0, 48, 46, 48, 46, 44, 44, 42, 42, 40, 40, 38, 38, 36, 36, 34, 32, 34, 50, 52, 52, 54, 54, 56, 40, 58, 58, 60, 8, 10, 20, 22, 22, 24, 62, 64, 64, 66, 66, 68, 8, 70, 70, 60, 68, 70, 58, 72, 72, 74, 74, 76, 76, 78, 24, 26, 26, 28, 58, 80, 80, 82, 82, 84, 84, 86, 86, 44, 70, 88, 88, 90, 90, 92, 92, 94, 94, 48, 80, 88, 88, 6, 82, 90, 90, 4, 84, 92, 92, 2, 86, 94, 94, 0, 56, 60, 10, 12, 12, 14, 14, 16, 28, 30, 30, 32, 26, 98, 98, 78, 30, 98, 24, 100, 100, 50, 98, 100, 22, 102, 102, 62, 100, 102, 16, 18, 18, 20, 102, 18 ], + "width": 82, + "height": 184 + } + }, + "front-thigh": { + "front-thigh": { "x": 42.48, "y": 4.45, "rotation": 84.87, "width": 45, "height": 112 } + }, + "front-upper-arm": { + "front-upper-arm": { "x": 28.31, "y": 7.37, "rotation": 97.9, "width": 46, "height": 97 } + }, + "goggles": { + "goggles": { + "type": "mesh", + "uvs": [ 0.53653, 0.04114, 0.72922, 0.16036, 0.91667, 0.33223, 0.97046, 0.31329, 1, 0.48053, 0.95756, 0.5733, 0.88825, 0.6328, 0.86878, 0.78962, 0.77404, 0.8675, 0.72628, 1, 0.60714, 0.93863, 0.49601, 0.88138, 0.41558, 0.75027, 0.32547, 0.70084, 0.2782, 0.58257, 0.1721, 0.63281, 0.17229, 0.75071, 0.10781, 0.79898, 0, 0.32304, 0, 0.12476, 0.07373, 0.07344, 0.15423, 0.10734, 0.23165, 0.13994, 0.30313, 0.02256, 0.34802, 0, 0.42979, 0.69183, 0.39476, 0.51042, 0.39488, 0.31512, 0.45878, 0.23198, 0.56501, 0.28109, 0.69961, 0.39216, 0.82039, 0.54204, 0.85738, 0.62343, 0.91107, 0.51407, 0.72639, 0.32147, 0.58764, 0.19609, 0.48075, 0.11269, 0.37823, 0.05501, 0.3287, 0.17866, 0.319, 0.305, 0.36036, 0.53799, 0.40327, 0.70072, 0.30059, 0.55838, 0.21957, 0.2815, 0.09963, 0.28943, 0.56863, 0.4368, 0.4911, 0.37156, 0.51185, 0.52093, 0.67018, 0.59304, 0.7619, 0.68575, 0.73296, 0.43355 ], + "triangles": [ 18, 44, 15, 21, 19, 20, 17, 18, 15, 44, 19, 21, 2, 3, 4, 18, 19, 44, 2, 33, 34, 33, 2, 4, 5, 33, 4, 5, 6, 33, 7, 32, 6, 31, 50, 33, 32, 31, 33, 6, 32, 33, 31, 49, 50, 49, 31, 32, 49, 32, 7, 8, 49, 7, 33, 50, 34, 17, 15, 16, 9, 48, 8, 49, 48, 50, 50, 48, 45, 47, 45, 48, 50, 45, 30, 45, 47, 46, 45, 46, 29, 30, 45, 29, 30, 29, 34, 30, 34, 50, 47, 26, 46, 25, 10, 11, 12, 25, 11, 41, 12, 42, 42, 44, 43, 43, 21, 22, 41, 40, 25, 41, 42, 40, 29, 35, 34, 40, 26, 25, 25, 26, 47, 37, 24, 0, 36, 37, 0, 42, 43, 39, 42, 39, 40, 28, 38, 36, 40, 39, 26, 28, 27, 38, 26, 39, 27, 37, 38, 23, 39, 43, 38, 38, 37, 36, 27, 39, 38, 43, 22, 38, 37, 23, 24, 22, 23, 38, 36, 0, 35, 28, 36, 35, 29, 28, 35, 27, 28, 46, 26, 27, 46, 35, 0, 1, 34, 35, 1, 12, 41, 25, 47, 10, 25, 44, 21, 43, 42, 14, 44, 14, 15, 44, 13, 14, 42, 12, 13, 42, 46, 28, 29, 47, 48, 10, 48, 9, 10, 49, 8, 48, 2, 34, 1 ], + "vertices": [ 2, 66, 61.88, 22.81, 0.832, 46, 172.09, 22.81, 0.168, 2, 66, 59.89, -31.19, 0.6855, 46, 170.1, -31.19, 0.3145, 2, 66, 49.2, -86.8, 0.32635, 46, 159.41, -86.8, 0.67365, 2, 66, 56.82, -99.01, 0.01217, 46, 167.03, -99.01, 0.98783, 1, 46, 143.4, -115.48, 1, 2, 66, 15, -110.14, 0.0041, 46, 125.21, -110.14, 0.9959, 2, 66, -0.32, -96.36, 0.07948, 46, 109.89, -96.36, 0.92052, 2, 66, -26.56, -100.19, 0.01905, 46, 83.65, -100.19, 0.98095, 2, 66, -46.96, -81.16, 0.4921, 46, 63.26, -81.16, 0.50791, 2, 66, -71.84, -76.69, 0.56923, 46, 38.37, -76.69, 0.43077, 2, 66, -72.54, -43.98, 0.74145, 46, 37.67, -43.98, 0.25855, 2, 66, -73.2, -13.47, 0.87929, 46, 37.01, -13.47, 0.12071, 2, 66, -59.63, 13.55, 0.864, 46, 50.58, 13.55, 0.136, 2, 66, -59.69, 38.45, 0.85289, 46, 50.52, 38.45, 0.14711, 2, 66, -45.26, 56.6, 0.74392, 46, 64.95, 56.6, 0.25608, 2, 66, -62.31, 79.96, 0.624, 46, 47.9, 79.96, 0.376, 2, 66, -80.76, 73.42, 0.616, 46, 29.45, 73.42, 0.384, 2, 66, -93.9, 86.64, 0.288, 46, 16.31, 86.64, 0.712, 1, 46, 81.51, 139.38, 1, 1, 46, 112.56, 150.3, 1, 2, 66, 16.76, 134.97, 0.02942, 46, 126.97, 134.97, 0.97058, 2, 66, 18.42, 113.28, 0.36147, 46, 128.63, 113.28, 0.63853, 2, 66, 20.02, 92.43, 0.7135, 46, 130.23, 92.43, 0.2865, 2, 66, 44.58, 81.29, 0.69603, 46, 154.79, 81.29, 0.30397, 2, 66, 52, 71.48, 0.848, 46, 162.21, 71.48, 0.152, 2, 66, -49.25, 13.27, 0.8, 46, 60.96, 13.27, 0.2, 2, 66, -23.88, 31.88, 0.896, 46, 86.33, 31.88, 0.104, 2, 66, 6.72, 42.6, 0.928, 46, 116.93, 42.6, 0.072, 2, 66, 25.26, 31.44, 0.8, 46, 135.47, 31.44, 0.2, 2, 66, 26.77, 2.59, 0.75, 46, 136.98, 2.59, 0.25, 2, 66, 21.02, -36.66, 0.54887, 46, 131.23, -36.66, 0.45113, 2, 66, 8.01, -74.65, 0.36029, 46, 118.22, -74.65, 0.63971, 2, 66, -1.52, -88.24, 0.1253, 46, 108.69, -88.24, 0.8747, 2, 66, 20.25, -95.44, 0.08687, 46, 130.46, -95.44, 0.91313, 2, 66, 34.42, -39.36, 0.72613, 46, 144.63, -39.36, 0.27387, 2, 66, 42.03, 1.7, 0.824, 46, 152.25, 1.7, 0.176, 2, 66, 45.85, 32.6, 0.856, 46, 156.06, 32.6, 0.144, 1, 66, 46.01, 61.02, 1, 1, 66, 22.35, 66.41, 1, 1, 66, 1.73, 61.84, 1, 2, 66, -31.17, 38.83, 0.928, 46, 79.04, 38.83, 0.072, 2, 66, -52.94, 19.31, 0.79073, 46, 57.27, 19.31, 0.20927, 2, 66, -39.54, 52.42, 0.912, 46, 70.67, 52.42, 0.088, 2, 66, -3.2, 87.61, 0.744, 46, 107.02, 87.61, 0.256, 2, 66, -14.82, 116.7, 0.6368, 46, 95.4, 116.7, 0.3632, 2, 66, 2.7, -6.87, 0.856, 46, 112.91, -6.87, 0.144, 2, 66, 6.21, 15.8, 0.744, 46, 116.42, 15.8, 0.256, 2, 66, -15.39, 2.47, 0.856, 46, 94.82, 2.47, 0.144, 2, 66, -12.98, -40.48, 0.72102, 46, 97.24, -40.48, 0.27898, 2, 66, -19.55, -68.16, 0.59162, 46, 90.66, -68.16, 0.40838, 2, 66, 17.44, -47.15, 0.53452, 46, 127.65, -47.15, 0.46548 ], + "hull": 25, + "edges": [ 36, 34, 34, 32, 32, 30, 30, 28, 28, 26, 26, 24, 24, 22, 18, 16, 16, 14, 14, 12, 12, 10, 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 48, 48, 46, 46, 44, 36, 38, 40, 38, 24, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 62, 64, 64, 12, 8, 66, 66, 68, 68, 70, 70, 72, 72, 74, 74, 76, 76, 78, 78, 80, 80, 82, 82, 24, 24, 84, 84, 86, 86, 44, 40, 42, 42, 44, 42, 88, 88, 30, 58, 90, 90, 92, 92, 94, 18, 20, 20, 22, 94, 20, 18, 96, 96, 98, 60, 100, 100, 62, 98, 100 ], + "width": 261, + "height": 166 + } + }, + "gun": { + "gun": { "x": 77.3, "y": 16.4, "rotation": 60.83, "width": 210, "height": 203 } + }, + "head": { + "head": { + "type": "mesh", + "uvs": [ 0.75919, 0.06107, 0.88392, 0.17893, 0.90174, 0.30856, 0.94224, 0.1966, 1, 0.26584, 1, 0.422, 0.95864, 0.46993, 0.92118, 0.51333, 0.85957, 0.5347, 0.78388, 0.65605, 0.74384, 0.74838, 0.85116, 0.75151, 0.84828, 0.82564, 0.81781, 0.85367, 0.75599, 0.85906, 0.76237, 0.90468, 0.65875, 1, 0.38337, 1, 0.1858, 0.85404, 0.12742, 0.81091, 0.06025, 0.69209, 0, 0.58552, 0, 0.41021, 0.0853, 0.20692, 0.24243, 0.14504, 0.5, 0.1421, 0.50324, 0.07433, 0.41738, 0, 0.57614, 0, 0.85059, 0.36087, 0.73431, 0.43206, 0.68481, 0.31271, 0.72165, 0.16718, 0.55931, 0.04154, 0.44764, 0.22895, 0.23926, 0.26559, 0.71272, 0.44036, 0.56993, 0.383, 0.41678, 0.33511, 0.293, 0.31497, 0.70802, 0.44502, 0.56676, 0.38976, 0.41521, 0.34416, 0.28754, 0.33017, 0.88988, 0.50177, 0.30389, 0.73463, 0.2646, 0.65675, 0.21414, 0.61584, 0.14613, 0.62194, 0.10316, 0.66636, 0.10358, 0.72557, 0.14505, 0.79164, 0.20263, 0.81355, 0.27873, 0.80159, 0.34947, 0.7376, 0.23073, 0.57073, 0.08878, 0.60707, 0.29461, 0.8129, 0.73006, 0.87883, 0.69805, 0.87348, 0.66166, 0.79681, 0.22468, 0.69824, 0.14552, 0.67405 ], + "triangles": [ 50, 49, 62, 34, 25, 31, 39, 35, 34, 38, 39, 34, 37, 38, 34, 42, 39, 38, 43, 39, 42, 32, 2, 31, 31, 37, 34, 42, 38, 37, 41, 42, 37, 43, 22, 39, 30, 31, 29, 36, 37, 31, 30, 36, 31, 40, 41, 37, 36, 40, 37, 36, 30, 44, 55, 22, 43, 55, 48, 56, 47, 48, 55, 46, 55, 54, 42, 55, 43, 47, 55, 46, 62, 49, 48, 61, 47, 46, 62, 48, 47, 61, 62, 47, 46, 54, 45, 42, 41, 55, 61, 46, 45, 55, 41, 54, 61, 51, 50, 61, 50, 62, 60, 41, 40, 54, 41, 60, 53, 61, 45, 52, 51, 61, 57, 53, 45, 57, 45, 54, 53, 52, 61, 52, 19, 51, 57, 18, 52, 57, 52, 53, 17, 54, 60, 57, 54, 17, 18, 57, 17, 19, 50, 51, 33, 27, 28, 26, 27, 33, 0, 33, 28, 32, 33, 0, 32, 0, 1, 33, 25, 26, 33, 32, 25, 31, 25, 32, 2, 32, 1, 2, 3, 4, 29, 31, 2, 2, 4, 5, 29, 2, 5, 6, 29, 5, 30, 29, 6, 44, 30, 6, 18, 19, 52, 49, 56, 48, 34, 24, 25, 35, 23, 24, 35, 24, 34, 39, 22, 35, 22, 23, 35, 7, 44, 6, 8, 36, 44, 40, 36, 8, 8, 44, 7, 56, 21, 22, 55, 56, 22, 9, 40, 8, 20, 21, 56, 20, 56, 49, 9, 60, 40, 10, 60, 9, 20, 50, 19, 12, 10, 11, 13, 10, 12, 14, 60, 10, 13, 14, 10, 59, 60, 14, 58, 59, 14, 58, 14, 15, 16, 17, 60, 59, 16, 60, 15, 16, 59, 15, 59, 58, 20, 49, 50 ], + "vertices": [ 2, 50, 41.97, -41.8, 0.94074, 66, 165.41, -22.6, 0.05926, 4, 48, 73.47, 27.54, 0.26795, 50, -5.75, -51.71, 0.4738, 49, 112.99, -11.41, 0.12255, 66, 143.5, -66.13, 0.1357, 4, 48, 38.23, 10.99, 0.6831, 50, -41.01, -35.22, 0.07866, 49, 92.73, -44.66, 0.04872, 66, 108.65, -83.49, 0.18952, 2, 48, 73.35, 10.89, 0.8455, 66, 143.77, -82.78, 0.1545, 2, 48, 58.59, -10.38, 0.91607, 66, 129.5, -104.39, 0.08393, 3, 46, 195.82, -119.82, 0.104, 47, 75.49, -4.55, 0.09191, 48, 14.36, -24.8, 0.80409, 4, 46, 178.62, -113.98, 0.19022, 47, 59.82, -13.72, 0.33409, 48, -2.7, -18.57, 0.46643, 66, 68.41, -113.98, 0.00926, 4, 46, 163.06, -108.69, 0.18724, 47, 45.64, -22.03, 0.3133, 48, -18.14, -12.93, 0.47469, 66, 52.84, -108.69, 0.02477, 2, 46, 151.52, -95.05, 0.91122, 66, 41.31, -95.05, 0.08878, 2, 46, 110.61, -87.69, 0.70564, 66, 0.4, -87.69, 0.29436, 2, 46, 81.05, -86.58, 0.63951, 66, -29.16, -86.58, 0.36049, 2, 46, 89.82, -114.32, 0.57, 66, -20.39, -114.32, 0.43, 2, 46, 68.72, -120.91, 0.57, 66, -41.49, -120.91, 0.43, 2, 46, 58.1, -115.9, 0.57, 66, -52.11, -115.9, 0.43, 2, 46, 51.03, -100.63, 0.64242, 66, -59.18, -100.63, 0.35758, 2, 46, 38.79, -106.76, 0.81659, 66, -71.43, -106.76, 0.18341, 2, 46, 2.68, -89.7, 0.77801, 66, -107.53, -89.7, 0.22199, 2, 46, -22.07, -19.3, 0.823, 66, -132.28, -19.3, 0.177, 2, 46, 1.2, 45.63, 0.51204, 66, -109.01, 45.63, 0.48796, 2, 46, 8.07, 64.81, 0.60869, 66, -102.14, 64.81, 0.39131, 2, 46, 35.44, 93.73, 0.80009, 66, -74.77, 93.73, 0.19991, 2, 46, 59.98, 119.66, 0.93554, 66, -50.23, 119.66, 0.06446, 2, 46, 109.26, 136.99, 0.99895, 66, -0.95, 136.99, 0.00105, 1, 46, 174.07, 135.27, 1, 3, 46, 205.59, 101.22, 0.80778, 49, -16.84, 104.63, 0.15658, 66, 95.38, 101.22, 0.03564, 3, 50, 58.94, 30.5, 0.43491, 49, 38.36, 61.89, 0.28116, 66, 119.35, 35.65, 0.28393, 2, 50, 75.56, 19.01, 0.92164, 66, 138.68, 41.52, 0.07836, 1, 50, 106.7, 26.9, 1, 1, 50, 83.79, -9.51, 1, 5, 47, 44.51, 27.24, 0.15139, 48, 19.12, 19.33, 0.44847, 50, -46.82, -15.19, 0.05757, 49, 72.19, -48.24, 0.1149, 66, 89.35, -75.58, 0.22767, 3, 47, 7.42, 19.08, 0.37772, 49, 34.32, -45.24, 0.09918, 66, 58.9, -52.89, 0.52311, 2, 49, 45.94, -9.07, 0.4826, 66, 87.99, -28.45, 0.5174, 2, 50, 20.62, -16.35, 0.7435, 66, 132.21, -23.49, 0.2565, 2, 50, 75.74, 0.94, 0.97172, 66, 152.95, 30.42, 0.02828, 4, 46, 200.45, 40.46, 0.18809, 50, 44.6, 56.29, 0.05831, 49, 11.15, 50.46, 0.14366, 66, 90.24, 40.46, 0.60994, 2, 46, 171.41, 90.12, 0.48644, 66, 61.2, 90.12, 0.51356, 2, 46, 164.84, -48.18, 0.43217, 66, 54.62, -48.18, 0.56783, 4, 46, 168.13, -6.02, 0.01949, 47, -28.65, 49.02, 0.02229, 49, 8.54, -6.09, 0.12791, 66, 57.92, -6.02, 0.83031, 2, 46, 167.84, 37.87, 0.15, 66, 57.63, 37.87, 0.85, 2, 46, 162.36, 71.5, 0.24107, 66, 52.15, 71.5, 0.75893, 2, 46, 163.11, -47.44, 0.41951, 66, 52.9, -47.44, 0.58049, 2, 46, 165.94, -5.87, 0.16355, 66, 55.73, -5.87, 0.83645, 2, 46, 165.14, 37.38, 0.15, 66, 54.93, 37.38, 0.85, 2, 46, 157.6, 71.4, 0.21735, 66, 47.39, 71.4, 0.78265, 3, 46, 163.5, -99.54, 0.61812, 47, 39.01, -15.71, 0.30445, 66, 53.29, -99.54, 0.07744, 2, 46, 45.38, 27.24, 0.16741, 66, -64.83, 27.24, 0.83259, 2, 46, 63.74, 44.98, 0.15, 66, -46.47, 44.98, 0.85, 2, 46, 70.7, 61.92, 0.22175, 66, -39.51, 61.92, 0.77825, 2, 46, 62.88, 78.71, 0.38, 66, -47.34, 78.71, 0.62, 2, 46, 46.53, 85.3, 0.51, 66, -63.68, 85.3, 0.49, 2, 46, 29.92, 79.34, 0.388, 66, -80.29, 79.34, 0.612, 2, 46, 15.08, 62.21, 0.38, 66, -95.13, 62.21, 0.62, 2, 46, 14.09, 45.32, 0.41, 66, -96.12, 45.32, 0.59, 2, 46, 24.3, 27.06, 0.192, 66, -85.91, 27.06, 0.808, 1, 66, -61.57, 15.3, 1, 2, 46, 84.87, 62.14, 0.16757, 66, -25.34, 62.14, 0.83243, 2, 46, 61.9, 94.84, 0.68145, 66, -48.31, 94.84, 0.31855, 2, 46, 22.54, 21.88, 0.16, 66, -87.67, 21.88, 0.84, 2, 46, 43.15, -95.95, 0.73445, 66, -67.06, -95.95, 0.26555, 2, 46, 41.77, -87.24, 0.67858, 66, -68.44, -87.24, 0.32142, 2, 46, 60.05, -70.36, 0.50195, 66, -50.16, -70.36, 0.49805, 2, 46, 48.49, 51.09, 0.25, 66, -61.72, 51.09, 0.75, 2, 46, 48.17, 73.71, 0.15634, 66, -62.04, 73.71, 0.84366 ], + "hull": 29, + "edges": [ 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 56, 54, 56, 54, 52, 52, 50, 50, 48, 48, 46, 46, 44, 42, 44, 32, 34, 4, 58, 58, 60, 62, 64, 64, 66, 66, 54, 50, 68, 68, 70, 70, 44, 60, 72, 62, 74, 72, 74, 74, 76, 76, 78, 78, 44, 16, 80, 80, 82, 82, 84, 84, 86, 86, 44, 14, 88, 88, 72, 14, 16, 10, 12, 12, 14, 12, 60, 90, 92, 92, 94, 94, 96, 96, 98, 98, 100, 100, 102, 102, 104, 104, 106, 106, 90, 108, 110, 110, 112, 38, 40, 40, 42, 112, 40, 34, 36, 36, 38, 36, 114, 114, 108, 30, 32, 30, 28, 24, 26, 28, 26, 22, 24, 22, 20, 20, 18, 18, 16, 28, 116, 116, 118, 118, 120, 120, 20 ], + "width": 271, + "height": 298 + } + }, + "head-bb": { + "head": { + "type": "boundingbox", + "vertexCount": 6, + "vertices": [ -19.14, -70.3, 40.8, -118.08, 257.78, -115.62, 285.17, 57.18, 120.77, 164.95, -5.07, 76.95 ] + } + }, + "hoverboard-board": { + "hoverboard-board": { + "type": "mesh", + "uvs": [ 0.13865, 0.56624, 0.11428, 0.51461, 0.07619, 0.52107, 0.02364, 0.52998, 0.01281, 0.53182, 0, 0.37979, 0, 0.2206, 0.00519, 0.10825, 0.01038, 0.10726, 0.03834, 0.10194, 0.05091, 0, 0.08326, 0, 0.10933, 0.04206, 0.1382, 0.08865, 0.18916, 0.24067, 0.22234, 0.4063, 0.23886, 0.44063, 0.83412, 0.44034, 0.88444, 0.38296, 0.92591, 0.32639, 0.95996, 0.28841, 0.98612, 0.28542, 1, 0.38675, 0.99494, 0.47104, 0.97883, 0.53251, 0.94409, 0.62135, 0.90206, 0.69492, 0.86569, 0.71094, 0.82822, 0.70791, 0.81286, 0.77127, 0.62931, 0.77266, 0.61364, 0.70645, 0.47166, 0.70664, 0.45901, 0.77827, 0.27747, 0.76986, 0.2658, 0.70372, 0.24976, 0.71381, 0.24601, 0.77827, 0.23042, 0.84931, 0.20926, 0.90956, 0.17299, 1, 0.15077, 0.99967, 0.12906, 0.90192, 0.10369, 0.73693, 0.10198, 0.62482, 0.09131, 0.47272, 0.09133, 0.41325, 0.15082, 0.41868, 0.21991, 0.51856, 0.06331, 0.10816, 0.08383, 0.21696, 0.08905, 0.37532, 0.15903, 0.58726, 0.17538, 0.65706, 0.20118, 0.8029, 0.17918, 0.55644, 0.22166, 0.5802, 0.86259, 0.57962, 0.92346, 0.48534, 0.96691, 0.36881, 0.0945, 0.13259, 0.12688, 0.17831, 0.15986, 0.24682, 0.18036, 0.31268, 0.20607, 0.4235, 0.16074, 0.85403, 0.13624, 0.70122, 0.12096, 0.64049, 0.02396, 0.21811, 0.02732, 0.37839, 0.02557, 0.4972, 0.14476, 0.45736, 0.18019, 0.51689, 0.19692, 0.56636 ], + "triangles": [ 10, 11, 12, 9, 10, 12, 49, 9, 12, 60, 49, 12, 13, 60, 12, 61, 60, 13, 50, 49, 60, 50, 60, 61, 68, 8, 9, 68, 9, 49, 68, 49, 50, 7, 8, 68, 6, 7, 68, 61, 13, 14, 62, 61, 14, 50, 61, 62, 63, 62, 14, 59, 20, 21, 19, 20, 59, 51, 50, 62, 51, 62, 63, 51, 69, 68, 51, 68, 50, 6, 68, 69, 5, 6, 69, 18, 19, 59, 15, 63, 14, 59, 21, 22, 47, 51, 63, 47, 46, 51, 47, 63, 64, 15, 64, 63, 64, 15, 16, 71, 46, 47, 23, 59, 22, 69, 51, 70, 45, 46, 71, 70, 51, 2, 58, 18, 59, 58, 59, 23, 17, 18, 58, 70, 5, 69, 2, 51, 46, 1, 45, 71, 47, 48, 71, 47, 64, 48, 48, 72, 71, 1, 71, 72, 16, 48, 64, 45, 2, 46, 2, 45, 1, 70, 4, 5, 3, 70, 2, 3, 4, 70, 24, 58, 23, 72, 0, 1, 73, 55, 72, 55, 0, 72, 48, 73, 72, 57, 17, 58, 25, 57, 58, 56, 48, 16, 73, 48, 56, 56, 16, 17, 56, 17, 57, 52, 0, 55, 24, 25, 58, 44, 0, 52, 67, 44, 52, 52, 56, 53, 73, 52, 55, 56, 52, 73, 67, 52, 53, 26, 57, 25, 66, 67, 53, 56, 32, 35, 53, 56, 35, 56, 57, 32, 28, 31, 57, 57, 31, 32, 57, 27, 28, 26, 27, 57, 36, 53, 35, 43, 44, 67, 43, 67, 66, 34, 35, 32, 29, 31, 28, 30, 31, 29, 53, 54, 66, 53, 36, 54, 33, 34, 32, 37, 54, 36, 65, 43, 66, 38, 54, 37, 54, 65, 66, 39, 65, 54, 42, 43, 65, 38, 39, 54, 40, 42, 65, 40, 41, 42, 65, 39, 40 ], + "vertices": [ -189.36, 15.62, -201.35, 23.47, -220.09, 22.49, -245.95, 21.13, -251.28, 20.86, -257.58, 43.96, -257.57, 68.16, -255.02, 85.24, -252.47, 85.39, -238.71, 86.2, -232.52, 101.69, -216.61, 101.69, -203.78, 95.3, -189.58, 88.21, -164.51, 65.1, -148.19, 39.93, -140.06, 34.71, 152.82, 34.73, 177.57, 43.45, 197.97, 52.05, 214.72, 57.82, 227.6, 58.27, 234.42, 42.87, 231.94, 30.06, 224.01, 20.72, 206.91, 7.21, 186.23, -3.97, 168.34, -6.4, 149.9, -5.94, 142.35, -15.57, 52.04, -15.77, 44.33, -5.71, -25.52, -5.73, -31.75, -16.62, -121.07, -15.34, -126.81, -5.28, -134.7, -6.81, -136.54, -16.61, -144.22, -27.41, -154.63, -36.57, -172.47, -50.31, -183.41, -50.26, -194.09, -35.4, -206.56, -10.32, -207.4, 6.72, -212.65, 29.84, -212.64, 38.88, -183.37, 38.05, -149.38, 22.86, -226.43, 85.25, -216.33, 68.71, -213.76, 44.64, -179.34, 12.42, -171.29, 1.81, -158.6, -20.36, -169.42, 17.11, -148.52, 13.49, 166.82, 13.56, 196.76, 27.89, 218.14, 45.6, -211.08, 81.54, -195.15, 74.59, -178.93, 64.17, -168.84, 54.16, -156.19, 37.31, -178.5, -28.13, -190.55, -4.9, -198.07, 4.33, -245.79, 68.54, -244.14, 44.18, -245, 26.12, -186.36, 32.17, -168.92, 23.12, -160.69, 15.6 ], + "hull": 45, + "edges": [ 0, 2, 8, 10, 10, 12, 12, 14, 18, 20, 20, 22, 26, 28, 28, 30, 30, 32, 32, 34, 34, 36, 36, 38, 38, 40, 40, 42, 42, 44, 44, 46, 46, 48, 48, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 60, 62, 62, 64, 64, 66, 66, 68, 68, 70, 70, 72, 72, 74, 80, 82, 82, 84, 84, 86, 86, 88, 0, 88, 2, 90, 90, 92, 92, 94, 94, 96, 96, 32, 18, 98, 98, 100, 100, 102, 2, 4, 102, 4, 92, 102, 0, 104, 104, 106, 106, 108, 78, 80, 108, 78, 74, 76, 76, 78, 62, 56, 64, 70, 0, 110, 112, 114, 114, 116, 116, 118, 118, 42, 50, 116, 114, 34, 98, 120, 120, 122, 22, 24, 24, 26, 120, 24, 122, 124, 124, 126, 126, 128, 128, 96, 80, 130, 130, 132, 132, 134, 134, 88, 14, 16, 16, 18, 136, 16, 136, 138, 138, 140, 4, 6, 6, 8, 140, 6, 96, 112, 92, 142, 142, 144, 110, 146, 146, 112, 144, 146 ], + "width": 492, + "height": 152 + } + }, + "hoverboard-thruster-front": { + "hoverboard-thruster": { "x": 0.02, "y": -7.08, "rotation": 0.17, "width": 60, "height": 64 } + }, + "hoverboard-thruster-rear": { + "hoverboard-thruster": { "x": 1.1, "y": -6.29, "rotation": 0.17, "width": 60, "height": 64 } + }, + "hoverglow-front": { + "hoverglow-small": { + "x": 2.13, + "y": -2, + "scaleX": 0.303, + "scaleY": 0.495, + "rotation": 0.15, + "width": 274, + "height": 75 + } + }, + "hoverglow-rear": { + "hoverglow-small": { + "x": 1.39, + "y": -2.09, + "scaleX": 0.303, + "scaleY": 0.495, + "rotation": 0.61, + "width": 274, + "height": 75 + } + }, + "mouth": { + "mouth-grind": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 66, -98.93, -85.88, 0.22, 46, 11.28, -85.88, 0.78, 2, 66, -129.77, 1.84, 0.6, 46, -19.56, 1.84, 0.4, 2, 66, -74.12, 21.41, 0.6, 46, 36.09, 21.41, 0.4, 2, 66, -43.28, -66.32, 0.4, 46, 66.93, -66.32, 0.6 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + }, + "mouth-oooo": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 46, 11.28, -85.89, 0.22, 66, -98.93, -85.89, 0.78, 2, 46, -19.56, 1.85, 0.6, 66, -129.78, 1.85, 0.4, 2, 46, 36.1, 21.42, 0.6, 66, -74.12, 21.42, 0.4, 2, 46, 66.94, -66.32, 0.4, 66, -43.27, -66.32, 0.6 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + }, + "mouth-smile": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 66, -98.93, -85.89, 0.21075, 46, 11.28, -85.89, 0.78925, 2, 66, -129.77, 1.85, 0.6, 46, -19.56, 1.85, 0.4, 2, 66, -74.11, 21.42, 0.6, 46, 36.1, 21.42, 0.4, 2, 66, -43.27, -66.32, 0.40772, 46, 66.94, -66.32, 0.59228 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + } + }, + "muzzle": { + "muzzle01": { + "x": 151.97, + "y": 5.81, + "scaleX": 3.7361, + "scaleY": 3.7361, + "rotation": 0.15, + "width": 133, + "height": 79 + }, + "muzzle02": { + "x": 187.25, + "y": 5.9, + "scaleX": 4.0623, + "scaleY": 4.0623, + "rotation": 0.15, + "width": 135, + "height": 84 + }, + "muzzle03": { + "x": 231.96, + "y": 6.02, + "scaleX": 4.1325, + "scaleY": 4.1325, + "rotation": 0.15, + "width": 166, + "height": 106 + }, + "muzzle04": { + "x": 231.96, + "y": 6.02, + "scaleX": 4.0046, + "scaleY": 4.0046, + "rotation": 0.15, + "width": 149, + "height": 90 + }, + "muzzle05": { + "x": 293.8, + "y": 6.19, + "scaleX": 4.4673, + "scaleY": 4.4673, + "rotation": 0.15, + "width": 135, + "height": 75 + } + }, + "muzzle-glow": { + "muzzle-glow": { "width": 50, "height": 50 } + }, + "muzzle-ring": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "muzzle-ring2": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "muzzle-ring3": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "muzzle-ring4": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "neck": { + "neck": { "x": 9.77, "y": -3.01, "rotation": -55.22, "width": 36, "height": 41 } + }, + "portal-bg": { + "portal-bg": { "x": -3.1, "y": 7.25, "scaleX": 1.0492, "scaleY": 1.0492, "width": 266, "height": 266 } + }, + "portal-flare1": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare2": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare3": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare4": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare5": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare6": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare7": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare8": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare9": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare10": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-shade": { + "portal-shade": { "width": 266, "height": 266 } + }, + "portal-streaks1": { + "portal-streaks1": { "scaleX": 0.9774, "scaleY": 0.9774, "width": 252, "height": 256 } + }, + "portal-streaks2": { + "portal-streaks2": { "x": -1.64, "y": 2.79, "width": 250, "height": 249 } + }, + "rear-bracer": { + "rear-bracer": { "x": 11.15, "y": -2.2, "rotation": 66.17, "width": 56, "height": 72 } + }, + "rear-foot": { + "rear-foot": { + "type": "mesh", + "uvs": [ 0.48368, 0.1387, 0.51991, 0.21424, 0.551, 0.27907, 0.58838, 0.29816, 0.63489, 0.32191, 0.77342, 0.39267, 1, 0.73347, 1, 1, 0.54831, 0.99883, 0.31161, 1, 0, 1, 0, 0.41397, 0.13631, 0, 0.41717, 0 ], + "triangles": [ 8, 3, 4, 8, 4, 5, 8, 5, 6, 8, 6, 7, 11, 1, 10, 3, 9, 2, 2, 10, 1, 12, 13, 0, 0, 11, 12, 1, 11, 0, 2, 9, 10, 3, 8, 9 ], + "vertices": [ 2, 8, 10.45, 29.41, 0.90802, 9, -6.74, 49.62, 0.09198, 2, 8, 16.56, 29.27, 0.84259, 9, -2.65, 45.09, 0.15741, 2, 8, 21.8, 29.15, 0.69807, 9, 0.85, 41.2, 0.30193, 2, 8, 25.53, 31.43, 0.52955, 9, 5.08, 40.05, 0.47045, 2, 8, 30.18, 34.27, 0.39303, 9, 10.33, 38.62, 0.60697, 2, 8, 44.02, 42.73, 0.27525, 9, 25.98, 34.36, 0.72475, 2, 8, 76.47, 47.28, 0.21597, 9, 51.56, 13.9, 0.78403, 2, 8, 88.09, 36.29, 0.28719, 9, 51.55, -2.09, 0.71281, 2, 8, 52.94, -0.73, 0.47576, 9, 0.52, -1.98, 0.52424, 2, 8, 34.63, -20.23, 0.68757, 9, -26.23, -2.03, 0.31243, 2, 8, 10.44, -45.81, 0.84141, 9, -61.43, -2, 0.15859, 2, 8, -15.11, -21.64, 0.93283, 9, -61.4, 33.15, 0.06717, 1, 8, -22.57, 6.61, 1, 1, 8, -0.76, 29.67, 1 ], + "hull": 14, + "edges": [ 14, 12, 10, 12, 14, 16, 16, 18, 18, 20, 4, 18, 20, 22, 24, 26, 22, 24, 4, 2, 2, 20, 4, 6, 6, 16, 6, 8, 8, 10, 2, 0, 0, 26 ], + "width": 113, + "height": 60 + } + }, + "rear-shin": { + "rear-shin": { "x": 58.29, "y": -2.75, "rotation": 92.37, "width": 75, "height": 178 } + }, + "rear-thigh": { + "rear-thigh": { "x": 33.11, "y": -4.11, "rotation": 72.54, "width": 55, "height": 94 } + }, + "rear-upper-arm": { + "rear-upper-arm": { "x": 21.13, "y": 4.09, "rotation": 89.33, "width": 40, "height": 87 } + }, + "side-glow1": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.2353, "scaleY": 0.4132, "width": 274, "height": 75 } + }, + "side-glow2": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.2353, "scaleY": 0.4132, "width": 274, "height": 75 } + }, + "side-glow3": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.3586, "scaleY": 0.6297, "width": 274, "height": 75 } + }, + "torso": { + "torso": { + "type": "mesh", + "uvs": [ 0.6251, 0.12672, 1, 0.26361, 1, 0.28871, 1, 0.66021, 1, 0.68245, 0.92324, 0.69259, 0.95116, 0.84965, 0.77124, 1, 0.49655, 1, 0.27181, 1, 0.13842, 0.77196, 0.09886, 0.6817, 0.05635, 0.58471, 0, 0.45614, 0, 0.33778, 0, 0.19436, 0.14463, 0, 0.27802, 0, 0.72525, 0.27835, 0.76091, 0.46216, 0.84888, 0.67963, 0.68257, 0.63249, 0.53986, 0.3847, 0.25443, 0.3217, 0.30063, 0.55174, 0.39553, 0.79507, 0.26389, 0.17007, 0.5241, 0.18674, 0.71492, 0.76655, 0.82151, 0.72956, 0.27626, 0.4304, 0.62327, 0.52952, 0.3455, 0.66679, 0.53243, 0.2914 ], + "triangles": [ 18, 1, 2, 19, 2, 3, 18, 0, 1, 23, 15, 26, 27, 26, 16, 14, 15, 23, 15, 16, 26, 17, 27, 16, 13, 14, 23, 0, 27, 17, 13, 23, 30, 11, 12, 24, 21, 31, 19, 12, 13, 30, 24, 22, 31, 31, 22, 19, 12, 30, 24, 32, 24, 31, 24, 30, 22, 3, 20, 19, 32, 31, 21, 11, 24, 32, 4, 5, 3, 8, 28, 7, 7, 29, 6, 7, 28, 29, 9, 25, 8, 8, 25, 28, 9, 10, 25, 29, 5, 6, 10, 32, 25, 25, 21, 28, 25, 32, 21, 10, 11, 32, 28, 21, 29, 29, 20, 5, 29, 21, 20, 5, 20, 3, 20, 21, 19, 33, 26, 27, 22, 18, 19, 19, 18, 2, 33, 27, 18, 30, 23, 22, 22, 33, 18, 23, 33, 22, 33, 23, 26, 27, 0, 18 ], + "vertices": [ 2, 29, 44.59, -10.39, 0.88, 40, -17.65, 33.99, 0.12, 3, 28, 59.65, -45.08, 0.12189, 29, 17.13, -45.08, 0.26811, 40, 22.68, 15.82, 0.61, 3, 28, 55.15, -44.72, 0.1345, 29, 12.63, -44.72, 0.2555, 40, 23.43, 11.37, 0.61, 3, 27, 31.01, -39.45, 0.51133, 28, -11.51, -39.45, 0.30867, 40, 34.58, -54.57, 0.18, 3, 27, 27.01, -39.14, 0.53492, 28, -15.5, -39.14, 0.28508, 40, 35.25, -58.52, 0.18, 2, 27, 25.79, -31.5, 0.75532, 28, -16.73, -31.5, 0.24468, 1, 27, -2.61, -32, 1, 1, 27, -28.2, -12.29, 1, 1, 27, -26.08, 14.55, 1, 1, 27, -24.35, 36.5, 1, 2, 27, 17.6, 46.3, 0.8332, 28, -24.92, 46.3, 0.1668, 2, 27, 34.1, 48.89, 0.59943, 28, -8.42, 48.89, 0.40058, 3, 27, 51.83, 51.67, 0.29262, 28, 9.32, 51.67, 0.63181, 29, -33.2, 51.67, 0.07557, 3, 27, 75.34, 55.35, 0.06656, 28, 32.82, 55.35, 0.62298, 29, -9.7, 55.35, 0.31046, 2, 28, 54.06, 53.67, 0.37296, 29, 11.54, 53.67, 0.62704, 2, 28, 79.79, 51.64, 0.10373, 29, 37.27, 51.64, 0.89627, 1, 29, 71.04, 34.76, 1, 1, 29, 70.01, 21.72, 1, 1, 30, 36.74, 7.06, 1, 3, 30, 45.7, -24.98, 0.67, 28, 25.87, -18.9, 0.3012, 29, -16.65, -18.9, 0.0288, 2, 27, 28.69, -24.42, 0.77602, 28, -13.83, -24.42, 0.22398, 3, 30, 43.24, -56.49, 0.064, 27, 38.43, -8.84, 0.67897, 28, -4.09, -8.84, 0.25703, 3, 30, 22.02, -14.85, 0.29, 28, 41.48, 1.59, 0.53368, 29, -1.04, 1.59, 0.17632, 3, 30, -7.45, -8.33, 0.76, 28, 54.98, 28.59, 0.06693, 29, 12.46, 28.59, 0.17307, 3, 30, 3.91, -48.4, 0.25, 27, 55.87, 27.33, 0.15843, 28, 13.35, 27.33, 0.59157, 1, 27, 11.47, 21.51, 1, 2, 30, -11.09, 18.74, 0.416, 29, 39.6, 25.51, 0.584, 2, 30, 14.56, 20.03, 0.53, 29, 34.6, 0.33, 0.47, 1, 27, 14.12, -10.1, 1, 2, 27, 19.94, -21.03, 0.92029, 28, -22.58, -21.03, 0.07971, 3, 30, -2.08, -27.26, 0.29, 28, 35.31, 27.99, 0.49582, 29, -7.21, 27.99, 0.21418, 2, 30, 34.42, -39.19, 0.25, 28, 14.84, -4.5, 0.75, 2, 27, 34.87, 24.58, 0.67349, 28, -7.64, 24.58, 0.32651, 2, 30, 18.5, 1.59, 0.76, 29, 15.76, 1, 0.24 ], + "hull": 18, + "edges": [ 14, 12, 12, 10, 10, 8, 18, 20, 32, 34, 30, 32, 2, 4, 36, 4, 36, 38, 38, 40, 4, 6, 6, 8, 40, 6, 40, 42, 14, 16, 16, 18, 50, 16, 46, 52, 54, 36, 2, 0, 0, 34, 54, 0, 54, 32, 20, 50, 14, 56, 56, 42, 50, 56, 56, 58, 58, 40, 58, 10, 46, 60, 60, 48, 26, 60, 60, 44, 24, 26, 24, 48, 42, 62, 62, 44, 48, 62, 48, 64, 64, 50, 42, 64, 20, 22, 22, 24, 64, 22, 26, 28, 28, 30, 28, 46, 44, 66, 66, 54, 46, 66, 66, 36, 62, 38 ], + "width": 98, + "height": 180 + } + } + } + } +], +"events": { + "footstep": {} +}, +"animations": { + "aim": { + "slots": { + "crosshair": { + "attachment": [ + { "name": "crosshair" } + ] + } + }, + "bones": { + "front-fist": { + "rotate": [ + { "value": 36.08 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": -26.55 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "value": 62.31 } + ] + }, + "front-bracer": { + "rotate": [ + { "value": 9.11 } + ] + }, + "gun": { + "rotate": [ + { "value": -0.31 } + ] + } + }, + "ik": { + "aim-ik": [ + { "mix": 0.995 } + ] + }, + "transform": { + "aim-front-arm-transform": [ + { "mixRotate": 0.784, "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ], + "aim-head-transform": [ + { "mixRotate": 0.659, "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ], + "aim-torso-transform": [ + { "mixRotate": 0.423, "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ] + } + }, + "death": { + "slots": { + "eye": { + "attachment": [ + { "name": "eye-surprised" }, + { "time": 0.5333, "name": "eye-indifferent" }, + { "time": 2.2, "name": "eye-surprised" }, + { "time": 4.6, "name": "eye-indifferent" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "name": "mouth-oooo" }, + { "time": 0.5333, "name": "mouth-grind" }, + { "time": 1.4, "name": "mouth-oooo" }, + { "time": 2.1667, "name": "mouth-grind" }, + { "time": 4.5333, "name": "mouth-oooo" } + ] + } + }, + "bones": { + "head": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.015, -2.83, 0.036, 12.72 ] + }, + { + "time": 0.0667, + "value": 12.19, + "curve": [ 0.096, 11.68, 0.119, -1.14 ] + }, + { + "time": 0.1333, + "value": -6.86, + "curve": [ 0.149, -13.27, 0.21, -37.28 ] + }, + { + "time": 0.3, + "value": -36.86, + "curve": [ 0.354, -36.61, 0.412, -32.35 ] + }, + { + "time": 0.4667, + "value": -23.49, + "curve": [ 0.49, -19.87, 0.512, -3.29 ] + }, + { + "time": 0.5333, + "value": -3.24, + "curve": [ 0.56, -3.39, 0.614, -67.25 ] + }, + { + "time": 0.6333, + "value": -74.4, + "curve": [ 0.652, -81.58, 0.702, -88.94 ] + }, + { + "time": 0.7333, + "value": -88.93, + "curve": [ 0.805, -88.91, 0.838, -80.87 ] + }, + { + "time": 0.8667, + "value": -81.03, + "curve": [ 0.922, -81.32, 0.976, -85.29 ] + }, + { "time": 1, "value": -85.29, "curve": "stepped" }, + { + "time": 2.2333, + "value": -85.29, + "curve": [ 2.314, -85.29, 2.382, -68.06 ] + }, + { + "time": 2.4667, + "value": -63.48, + "curve": [ 2.57, -57.87, 2.916, -55.24 ] + }, + { + "time": 3.2, + "value": -55.1, + "curve": [ 3.447, -54.98, 4.135, -56.61 ] + }, + { + "time": 4.2667, + "value": -58.23, + "curve": [ 4.672, -63.24, 4.646, -82.69 ] + }, + { "time": 4.9333, "value": -85.29 } + ], + "scale": [ + { + "time": 0.4667, + "curve": [ 0.469, 1.005, 0.492, 1.065, 0.475, 1.018, 0.492, 0.94 ] + }, + { + "time": 0.5, + "x": 1.065, + "y": 0.94, + "curve": [ 0.517, 1.065, 0.541, 0.991, 0.517, 0.94, 0.542, 1.026 ] + }, + { + "time": 0.5667, + "x": 0.99, + "y": 1.025, + "curve": [ 0.593, 0.988, 0.609, 1.002, 0.595, 1.024, 0.607, 1.001 ] + }, + { "time": 0.6333 } + ] + }, + "neck": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.114, 1.33, 0.195, 4.13 ] + }, + { + "time": 0.2667, + "value": 4.13, + "curve": [ 0.351, 4.14, 0.444, -24.5 ] + }, + { + "time": 0.5, + "value": -24.69, + "curve": [ 0.571, -23.89, 0.55, 34.22 ] + }, + { + "time": 0.6667, + "value": 35.13, + "curve": [ 0.713, 34.81, 0.756, 22.76 ] + }, + { + "time": 0.8333, + "value": 22.82, + "curve": [ 0.868, 22.84, 0.916, 47.95 ] + }, + { "time": 0.9667, "value": 47.95, "curve": "stepped" }, + { + "time": 2.2333, + "value": 47.95, + "curve": [ 2.3, 47.95, 2.617, 18.72 ] + }, + { + "time": 2.6667, + "value": 18.51, + "curve": [ 3.172, 16.58, 4.06, 16.79 ] + }, + { + "time": 4.5333, + "value": 18.51, + "curve": [ 4.707, 19.13, 4.776, 41.11 ] + }, + { "time": 4.8, "value": 47.95 } + ] + }, + "torso": { + "rotate": [ + { + "value": -8.62, + "curve": [ 0.01, -16.71, 0.032, -33.6 ] + }, + { + "time": 0.0667, + "value": -33.37, + "curve": [ 0.182, -32.61, 0.298, 123.07 ] + }, + { + "time": 0.4667, + "value": 122.77, + "curve": [ 0.511, 122.69, 0.52, 100.2 ] + }, + { + "time": 0.5667, + "value": 88.96, + "curve": [ 0.588, 83.89, 0.667, 75.34 ] + }, + { + "time": 0.7, + "value": 75.34, + "curve": [ 0.767, 75.34, 0.9, 76.03 ] + }, + { "time": 0.9667, "value": 76.03 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -38.86, + "curve": [ 0.022, -40.38, 0.096, -41.92 ] + }, + { + "time": 0.1333, + "value": -41.92, + "curve": [ 0.176, -41.92, 0.216, -16.92 ] + }, + { + "time": 0.2333, + "value": -4.35, + "curve": [ 0.258, 13.69, 0.308, 60.35 ] + }, + { + "time": 0.4, + "value": 60.17, + "curve": [ 0.496, 59.98, 0.539, 33.63 ] + }, + { + "time": 0.5667, + "value": 23.06, + "curve": [ 0.595, 32.71, 0.675, 53.71 ] + }, + { + "time": 0.7333, + "value": 53.61, + "curve": [ 0.797, 53.51, 0.926, 30.98 ] + }, + { "time": 0.9333, "value": 19.57, "curve": "stepped" }, + { + "time": 1.9667, + "value": 19.57, + "curve": [ 2.245, 19.57, 2.702, 77.03 ] + }, + { + "time": 3.0667, + "value": 77.06, + "curve": [ 3.209, 77.33, 3.291, 67.99 ] + }, + { + "time": 3.4333, + "value": 67.96, + "curve": [ 3.608, 68.34, 3.729, 73.88 ] + }, + { + "time": 3.8333, + "value": 73.42, + "curve": [ 4.152, 73.91, 4.46, 71.98 ] + }, + { + "time": 4.6333, + "value": 64.77, + "curve": [ 4.688, 62.5, 4.847, 26.42 ] + }, + { "time": 4.8667, "value": 10.94 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": -44.7, + "curve": [ 0.033, -44.7, 0.12, 54.89 ] + }, + { + "time": 0.1333, + "value": 64.62, + "curve": [ 0.154, 79.18, 0.214, 79.42 ] + }, + { + "time": 0.2667, + "value": 63.4, + "curve": [ 0.293, 55.19, 0.332, 30.13 ] + }, + { + "time": 0.3667, + "value": 30.13, + "curve": [ 0.4, 30.13, 0.441, 39.87 ] + }, + { + "time": 0.4667, + "value": 55.13, + "curve": [ 0.488, 68.18, 0.52, 100.72 ] + }, + { + "time": 0.5333, + "value": 111.96, + "curve": [ 0.551, 126.88, 0.627, 185.97 ] + }, + { + "time": 0.6667, + "value": 185.97, + "curve": [ 0.692, 185.97, 0.736, 162.43 ] + }, + { + "time": 0.8, + "value": 158.01, + "curve": [ 0.9, 151.12, 1.017, 144.01 ] + }, + { "time": 1.1, "value": 144.01, "curve": "stepped" }, + { + "time": 2.3667, + "value": 144.01, + "curve": [ 2.492, 144.01, 2.742, 138.63 ] + }, + { + "time": 2.8667, + "value": 138.63, + "curve": [ 3.067, 138.63, 3.467, 138.63 ] + }, + { + "time": 3.6667, + "value": 138.63, + "curve": [ 3.883, 138.63, 4.317, 135.18 ] + }, + { + "time": 4.5333, + "value": 135.18, + "curve": [ 4.575, 135.18, 4.692, 131.59 ] + }, + { + "time": 4.7333, + "value": 131.59, + "curve": [ 4.758, 131.59, 4.517, 144.01 ] + }, + { "time": 4.8333, "value": 144.01 } + ], + "translate": [ + { + "time": 0.4667, + "curve": [ 0.517, 0, 0.617, -34.96, 0.517, 0, 0.617, -16.59 ] + }, + { "time": 0.6667, "x": -35.02, "y": -16.62 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 21.88, + "curve": [ 0.033, 21.88, 0.099, 20.44 ] + }, + { + "time": 0.1333, + "value": 9.43, + "curve": [ 0.164, -0.29, 0.162, -38.26 ] + }, + { + "time": 0.2, + "value": -38.05, + "curve": [ 0.24, -37.96, 0.228, -17.82 ] + }, + { + "time": 0.3333, + "value": -9.73, + "curve": [ 0.372, -6.76, 0.431, -0.74 ] + }, + { + "time": 0.4667, + "value": 6.47, + "curve": [ 0.489, 11.05, 0.503, 19.09 ] + }, + { + "time": 0.5333, + "value": 19.09, + "curve": [ 0.571, 19.09, 0.554, -42.67 ] + }, + { + "time": 0.6, + "value": -42.67, + "curve": [ 0.653, -42.67, 0.691, -13.8 ] + }, + { + "time": 0.7, + "value": -3.54, + "curve": [ 0.707, 3.8, 0.719, 24.94 ] + }, + { + "time": 0.8, + "value": 25.31, + "curve": [ 0.902, 24.75, 0.992, -0.34 ] + }, + { "time": 1, "value": -32.16, "curve": "stepped" }, + { + "time": 2.2333, + "value": -32.16, + "curve": [ 2.6, -32.16, 2.638, -5.3 ] + }, + { + "time": 2.7, + "value": -1.96, + "curve": [ 2.707, -1.56, 2.775, 1.67 ] + }, + { + "time": 2.8, + "value": 1.67, + "curve": [ 2.825, 1.67, 2.875, -0.39 ] + }, + { + "time": 2.9, + "value": -0.39, + "curve": [ 2.925, -0.39, 2.975, 0.26 ] + }, + { + "time": 3, + "value": 0.26, + "curve": [ 3.025, 0.26, 3.075, -1.81 ] + }, + { + "time": 3.1, + "value": -1.81, + "curve": [ 3.125, -1.81, 3.175, -0.52 ] + }, + { + "time": 3.2, + "value": -0.52, + "curve": [ 3.225, -0.52, 3.275, -2.41 ] + }, + { + "time": 3.3, + "value": -2.41, + "curve": [ 3.333, -2.41, 3.4, -0.38 ] + }, + { + "time": 3.4333, + "value": -0.38, + "curve": [ 3.467, -0.38, 3.533, -2.25 ] + }, + { + "time": 3.5667, + "value": -2.25, + "curve": [ 3.592, -2.25, 3.642, -0.33 ] + }, + { + "time": 3.6667, + "value": -0.33, + "curve": [ 3.7, -0.33, 3.767, -1.34 ] + }, + { + "time": 3.8, + "value": -1.34, + "curve": [ 3.825, -1.34, 3.862, -0.77 ] + }, + { + "time": 3.9, + "value": -0.77, + "curve": [ 3.942, -0.77, 3.991, -1.48 ] + }, + { + "time": 4, + "value": -1.87, + "curve": [ 4.167, -1.87, 4.5, -1.96 ] + }, + { + "time": 4.6667, + "value": -1.96, + "curve": [ 4.709, 18.05, 4.767, 34.55 ] + }, + { + "time": 4.8, + "value": 34.55, + "curve": [ 4.84, 34.24, 4.902, 12.03 ] + }, + { "time": 4.9333, "value": -18.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -2.33, + "curve": [ 0.019, 4.43, 0.069, 10.82 ] + }, + { + "time": 0.1, + "value": 10.6, + "curve": [ 0.148, 10.6, 0.123, -15.24 ] + }, + { + "time": 0.2, + "value": -15.35, + "curve": [ 0.266, -15.44, 0.316, -6.48 ] + }, + { + "time": 0.3333, + "value": -3.9, + "curve": [ 0.362, 0.43, 0.479, 22.36 ] + }, + { + "time": 0.5667, + "value": 22.01, + "curve": [ 0.61, 21.84, 0.627, 12.85 ] + }, + { + "time": 0.6333, + "value": 9.05, + "curve": [ 0.643, 2.77, 0.622, -39.43 ] + }, + { + "time": 0.7, + "value": -39.5, + "curve": [ 0.773, -39.57, 0.814, 14.77 ] + }, + { + "time": 0.8667, + "value": 14.81, + "curve": [ 0.965, 14.88, 1.1, 5.64 ] + }, + { "time": 1.1, "value": -6.08, "curve": "stepped" }, + { + "time": 2.2333, + "value": -6.08, + "curve": [ 2.307, -6.08, 2.427, -25.89 ] + }, + { + "time": 2.5333, + "value": -22.42, + "curve": [ 2.598, -20.38, 2.657, 5.73 ] + }, + { + "time": 2.7, + "value": 5.73, + "curve": [ 2.77, 5.73, 2.851, -5.38 ] + }, + { + "time": 2.9333, + "value": -5.38, + "curve": [ 3.008, -5.38, 3.087, -4.54 ] + }, + { + "time": 3.1667, + "value": -4.17, + "curve": [ 3.223, -3.91, 4.486, 5.73 ] + }, + { + "time": 4.6667, + "value": 5.73, + "curve": [ 4.733, 5.73, 4.886, -2.47 ] + }, + { "time": 4.9333, "value": -6.52 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.36, + "curve": [ 0.033, 10.36, 0.1, -32.89 ] + }, + { + "time": 0.1333, + "value": -32.89, + "curve": [ 0.183, -32.89, 0.283, -4.45 ] + }, + { + "time": 0.3333, + "value": -4.45, + "curve": [ 0.367, -4.45, 0.438, -6.86 ] + }, + { + "time": 0.4667, + "value": -8.99, + "curve": [ 0.529, -13.62, 0.605, -20.58 ] + }, + { + "time": 0.6333, + "value": -23.2, + "curve": [ 0.708, -30.18, 0.758, -35.56 ] + }, + { + "time": 0.8, + "value": -35.56, + "curve": [ 0.875, -35.56, 1.025, -23.2 ] + }, + { "time": 1.1, "value": -23.2 } + ] + }, + "gun": { + "rotate": [ + { + "value": -2.79, + "curve": [ 0.033, -2.79, 0.12, -7.22 ] + }, + { + "time": 0.1333, + "value": -8.52, + "curve": [ 0.168, -11.87, 0.29, -23.71 ] + }, + { + "time": 0.3333, + "value": -26.24, + "curve": [ 0.369, -28.31, 0.436, -29.75 ] + }, + { + "time": 0.5, + "value": -29.66, + "curve": [ 0.552, -29.58, 0.611, -25.47 ] + }, + { + "time": 0.6333, + "value": -22.68, + "curve": [ 0.656, -19.76, 0.68, -10.02 ] + }, + { + "time": 0.7, + "value": -6.49, + "curve": [ 0.722, -2.6, 0.75, -1.22 ] + }, + { + "time": 0.7667, + "value": -1.35, + "curve": [ 0.792, -1.55, 0.842, -19.74 ] + }, + { "time": 0.8667, "value": -19.8 } + ] + }, + "hip": { + "translate": [ + { + "curve": [ 0.098, -42.62, 0.166, -79.85, 0.029, 84.97, 0.109, 155.93 ] + }, + { + "time": 0.2667, + "x": -133.79, + "y": 152.44, + "curve": [ 0.361, -184.63, 0.392, -203.69, 0.42, 149.12, 0.467, -15.7 ] + }, + { + "time": 0.4667, + "x": -230.02, + "y": -113.87, + "curve": [ 0.523, -249.86, 0.565, -261.7, 0.473, -133.1, 0.583, -203.43 ] + }, + { + "time": 0.6, + "x": -268.57, + "y": -203.43, + "curve": [ 0.663, -280.98, 0.816, -290.05, 0.708, -203.43, 0.892, -203.5 ] + }, + { "time": 1, "x": -290.42, "y": -203.5 } + ] + }, + "front-thigh": { + "rotate": [ + { + "curve": [ 0.06, 1.02, 0.151, 45.23 ] + }, + { + "time": 0.1667, + "value": 54.01, + "curve": [ 0.19, 66.85, 0.358, 169.85 ] + }, + { + "time": 0.5, + "value": 169.51, + "curve": [ 0.628, 169.85, 0.692, 108.85 ] + }, + { + "time": 0.7, + "value": 97.74, + "curve": [ 0.723, 102.6, 0.805, 111.6 ] + }, + { + "time": 0.8667, + "value": 111.69, + "curve": [ 0.899, 111.83, 1.015, 109.15 ] + }, + { "time": 1.0667, "value": 95.8 } + ] + }, + "front-shin": { + "rotate": [ + { + "curve": [ 0.086, -0.02, 0.191, -24.25 ] + }, + { + "time": 0.2, + "value": -26.5, + "curve": [ 0.214, -29.92, 0.249, -40.51 ] + }, + { + "time": 0.3333, + "value": -40.57, + "curve": [ 0.431, -40.7, 0.459, -11.34 ] + }, + { + "time": 0.4667, + "value": -8.71, + "curve": [ 0.477, -5.16, 0.524, 17.13 ] + }, + { + "time": 0.6, + "value": 16.98, + "curve": [ 0.632, 17.09, 0.625, 2.76 ] + }, + { + "time": 0.6333, + "value": 2.76, + "curve": [ 0.648, 2.76, 0.653, 2.75 ] + }, + { + "time": 0.6667, + "value": 2.59, + "curve": [ 0.678, 2.39, 0.733, 2.53 ] + }, + { + "time": 0.7333, + "value": -9.43, + "curve": [ 0.745, -2.48, 0.782, 3.12 ] + }, + { + "time": 0.8, + "value": 4.28, + "curve": [ 0.832, 6.32, 0.895, 8.46 ] + }, + { + "time": 0.9333, + "value": 8.49, + "curve": [ 0.986, 8.53, 1.051, 6.38 ] + }, + { + "time": 1.0667, + "value": 2.28, + "curve": [ 1.078, 4.17, 1.103, 5.86 ] + }, + { + "time": 1.1333, + "value": 5.88, + "curve": [ 1.191, 5.93, 1.209, 4.56 ] + }, + { "time": 1.2333, "value": 2.52 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.12, 50.26 ] + }, + { + "time": 0.1333, + "value": 57.3, + "curve": [ 0.164, 73.34, 0.274, 147.18 ] + }, + { + "time": 0.3333, + "value": 147.1, + "curve": [ 0.475, 146.45, 0.583, 95.72 ] + }, + { + "time": 0.6, + "value": 79.66, + "curve": [ 0.62, 94.74, 0.732, 103.15 ] + }, + { + "time": 0.7667, + "value": 103.02, + "curve": [ 0.812, 102.85, 0.897, 95.75 ] + }, + { "time": 0.9333, "value": 83.01 } + ] + }, + "rear-shin": { + "rotate": [ + { + "curve": [ 0.021, -16.65, 0.091, -54.82 ] + }, + { + "time": 0.1667, + "value": -55.29, + "curve": [ 0.187, -55.42, 0.213, -52.52 ] + }, + { + "time": 0.2333, + "value": -45.98, + "curve": [ 0.242, -43.1, 0.311, -12.73 ] + }, + { + "time": 0.3333, + "value": -6.32, + "curve": [ 0.356, 0.13, 0.467, 24.5 ] + }, + { + "time": 0.5, + "value": 24.5, + "curve": [ 0.543, 24.5, 0.56, 3.78 ] + }, + { + "time": 0.5667, + "value": -3.53, + "curve": [ 0.585, 3.86, 0.659, 16.63 ] + }, + { + "time": 0.7, + "value": 16.56, + "curve": [ 0.782, 16.43, 0.896, 8.44 ] + }, + { + "time": 0.9333, + "value": 4.04, + "curve": [ 0.956, 6.84, 1.008, 8.41 ] + }, + { + "time": 1.0333, + "value": 8.41, + "curve": [ 1.067, 8.41, 1.122, 8.14 ] + }, + { "time": 1.1667, "value": 5.8 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -0.28, + "curve": [ 0.033, -0.28, 0.256, -66.71 ] + }, + { + "time": 0.3667, + "value": -66.84, + "curve": [ 0.418, -66.91, 0.499, -21.79 ] + }, + { + "time": 0.6, + "value": -21.52, + "curve": [ 0.652, -21.38, 0.665, -53.96 ] + }, + { + "time": 0.7, + "value": -54.26, + "curve": [ 0.757, -53.96, 0.843, -2.07 ] + }, + { + "time": 0.9333, + "value": -1.47, + "curve": [ 0.968, -2.07, 0.975, -19.96 ] + }, + { + "time": 1, + "value": -19.96, + "curve": [ 1.025, -19.96, 1.075, -12.42 ] + }, + { + "time": 1.1, + "value": -12.42, + "curve": [ 1.133, -12.42, 1.2, -18.34 ] + }, + { "time": 1.2333, "value": -18.34 } + ] + }, + "front-foot": { + "rotate": [ + { + "curve": [ 0.008, -11.33, 0.108, -57.71 ] + }, + { + "time": 0.1333, + "value": -57.71, + "curve": [ 0.175, -57.71, 0.229, 19.73 ] + }, + { + "time": 0.3, + "value": 19.34, + "curve": [ 0.354, 19.34, 0.4, -57.76 ] + }, + { + "time": 0.4333, + "value": -57.76, + "curve": [ 0.458, -57.76, 0.511, -3.56 ] + }, + { + "time": 0.5333, + "value": 3.7, + "curve": [ 0.563, 13.29, 0.633, 15.79 ] + }, + { + "time": 0.6667, + "value": 15.79, + "curve": [ 0.7, 15.79, 0.767, -48.75 ] + }, + { + "time": 0.8, + "value": -48.75, + "curve": [ 0.842, -48.75, 0.925, 4.7 ] + }, + { + "time": 0.9667, + "value": 4.7, + "curve": [ 1, 4.7, 1.067, -22.9 ] + }, + { + "time": 1.1, + "value": -22.9, + "curve": [ 1.142, -22.9, 1.225, -13.28 ] + }, + { "time": 1.2667, "value": -13.28 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": -0.28 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -0.28, + "curve": [ 0.008, -0.28, 0.003, -66.62 ] + }, + { + "time": 0.0667, + "value": -65.75, + "curve": [ 0.166, -64.42, 0.234, 14.35 ] + }, + { + "time": 0.2667, + "value": 38.25, + "curve": [ 0.294, 57.91, 0.392, 89.79 ] + }, + { + "time": 0.4667, + "value": 90.73, + "curve": [ 0.483, 90.73, 0.55, 177.66 ] + }, + { + "time": 0.5667, + "value": 177.66, + "curve": [ 0.733, 176.24, 0.75, 11.35 ] + }, + { + "time": 0.8, + "value": 11.35, + "curve": [ 0.886, 12.29, 0.911, 47.88 ] + }, + { + "time": 0.9333, + "value": 56.77, + "curve": [ 0.967, 70.59, 1.05, 86.46 ] + }, + { + "time": 1.1, + "value": 86.46, + "curve": [ 1.187, 86.46, 1.214, 66.44 ] + }, + { "time": 1.3333, "value": 64.55 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "value": -0.28, + "curve": [ 0, -7.97, 0.027, -18.69 ] + }, + { + "time": 0.0667, + "value": -19, + "curve": [ 0.166, -19.3, 0.208, 15.58 ] + }, + { + "time": 0.2667, + "value": 45.95, + "curve": [ 0.306, 66.24, 0.378, 99.08 ] + }, + { + "time": 0.4333, + "value": 99.08, + "curve": [ 0.497, 98.62, 0.488, -1.2 ] + }, + { + "time": 0.5667, + "value": -1.32, + "curve": [ 0.637, -0.84, 0.687, 94.41 ] + }, + { + "time": 0.7333, + "value": 94.33, + "curve": [ 0.832, 94.16, 0.895, 29.6 ] + }, + { + "time": 0.9667, + "value": 28.67, + "curve": [ 1.026, 28.67, 1.045, 53.14 ] + }, + { "time": 1.1, "value": 53.38 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.011, 4.5, 0.05, 11.42 ] + }, + { + "time": 0.0667, + "value": 11.42, + "curve": [ 0.1, 11.42, 0.136, -5.92 ] + }, + { + "time": 0.1667, + "value": -10.54, + "curve": [ 0.206, -16.51, 0.327, -22 ] + }, + { + "time": 0.3667, + "value": -24.47, + "curve": [ 0.413, -27.37, 0.467, -43.99 ] + }, + { + "time": 0.5, + "value": -43.99, + "curve": [ 0.533, -43.99, 0.552, 12.12 ] + }, + { + "time": 0.6333, + "value": 11.85, + "curve": [ 0.714, 11.59, 0.758, -34.13 ] + }, + { + "time": 0.8, + "value": -34.13, + "curve": [ 0.858, -34.13, 1.015, -12.47 ] + }, + { + "time": 1.0667, + "value": -8.85, + "curve": [ 1.121, -5.07, 1.219, -0.02 ] + }, + { + "time": 1.3333, + "value": 1.29, + "curve": [ 1.509, 3.3, 1.763, 2.75 ] + }, + { + "time": 1.8667, + "value": 2.78, + "curve": [ 1.974, 2.81, 2.108, 2.81 ] + }, + { + "time": 2.2, + "value": 2.78, + "curve": [ 2.315, 2.74, 2.374, 1.22 ] + }, + { + "time": 2.4667, + "value": 1.18, + "curve": [ 2.525, 1.18, 2.608, 10.79 ] + }, + { + "time": 2.6667, + "value": 10.79, + "curve": [ 2.725, 10.79, 2.893, 4.72 ] + }, + { + "time": 3.0333, + "value": 4.72, + "curve": [ 3.117, 4.72, 3.283, 7.93 ] + }, + { + "time": 3.3667, + "value": 7.93, + "curve": [ 3.492, 7.93, 3.775, 6.93 ] + }, + { + "time": 3.9, + "value": 6.93, + "curve": [ 3.981, 6.93, 4.094, 6.9 ] + }, + { + "time": 4.2, + "value": 8.44, + "curve": [ 4.267, 9.42, 4.401, 16.61 ] + }, + { + "time": 4.5, + "value": 16.33, + "curve": [ 4.582, 16.12, 4.709, 9.94 ] + }, + { + "time": 4.7333, + "value": 6.51, + "curve": [ 4.747, 4.57, 4.779, -1.76 ] + }, + { + "time": 4.8, + "value": -1.75, + "curve": [ 4.823, -1.73, 4.82, 4.47 ] + }, + { + "time": 4.8667, + "value": 6.04, + "curve": [ 4.899, 7.14, 4.913, 6.93 ] + }, + { "time": 4.9333, "value": 6.93 } + ] + }, + "hair2": { + "rotate": [ + { + "value": 10.61, + "curve": [ 0.075, 10.61, 0.05, 12.67 ] + }, + { + "time": 0.0667, + "value": 12.67, + "curve": [ 0.123, 12.67, 0.194, -16.51 ] + }, + { + "time": 0.2, + "value": -19.87, + "curve": [ 0.207, -23.48, 0.236, -31.68 ] + }, + { + "time": 0.3, + "value": -31.8, + "curve": [ 0.356, -31.9, 0.437, -25.61 ] + }, + { + "time": 0.4667, + "value": -19.29, + "curve": [ 0.485, -15.33, 0.529, 6.48 ] + }, + { + "time": 0.5667, + "value": 6.67, + "curve": [ 0.628, 6.97, 0.65, -46.39 ] + }, + { + "time": 0.7333, + "value": -46.3, + "curve": [ 0.843, -46.17, 0.941, -33.37 ] + }, + { + "time": 0.9667, + "value": -23.17, + "curve": [ 0.972, -20.98, 1.047, 15.21 ] + }, + { + "time": 1.1, + "value": 15.21, + "curve": [ 1.142, 15.21, 1.183, 10.73 ] + }, + { + "time": 1.2667, + "value": 10.61, + "curve": [ 1.45, 10.34, 1.817, 10.61 ] + }, + { + "time": 2, + "value": 10.61, + "curve": [ 2.075, 10.61, 2.225, 16.9 ] + }, + { + "time": 2.3, + "value": 16.9, + "curve": [ 2.327, 16.9, 2.347, 6.81 ] + }, + { + "time": 2.4, + "value": 6.83, + "curve": [ 2.492, 6.87, 2.602, 17.39 ] + }, + { + "time": 2.6667, + "value": 17.39, + "curve": [ 2.742, 17.39, 2.892, 10.67 ] + }, + { + "time": 2.9667, + "value": 10.64, + "curve": [ 3.187, 10.57, 3.344, 10.73 ] + }, + { + "time": 3.6, + "value": 11.4, + "curve": [ 3.766, 11.83, 3.874, 14.87 ] + }, + { + "time": 3.9333, + "value": 14.83, + "curve": [ 4.022, 14.76, 4.208, 9.49 ] + }, + { + "time": 4.3, + "value": 9.54, + "curve": [ 4.391, 9.58, 4.441, 14.82 ] + }, + { + "time": 4.5333, + "value": 14.84, + "curve": [ 4.642, 14.88, 4.692, 1.17 ] + }, + { + "time": 4.7667, + "value": 1.24, + "curve": [ 4.823, 1.3, 4.818, 18.35 ] + }, + { + "time": 4.8667, + "value": 18.38, + "curve": [ 4.905, 18.41, 4.901, 10.61 ] + }, + { "time": 4.9333, "value": 10.61 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.048, 0, 0.129, -12.73 ] + }, + { + "time": 0.1667, + "value": -15.95, + "curve": [ 0.221, -20.66, 0.254, -21.62 ] + }, + { + "time": 0.3, + "value": -21.59, + "curve": [ 0.458, -21.46, 0.46, -1.67 ] + }, + { + "time": 0.6333, + "value": -1.71, + "curve": [ 0.71, -1.73, 0.715, -4 ] + }, + { + "time": 0.7667, + "value": -3.97, + "curve": [ 0.866, -3.92, 0.84, 0.02 ] + }, + { "time": 1, "curve": "stepped" }, + { + "time": 2, + "curve": [ 2.275, 0, 2.867, -5.8 ] + }, + { + "time": 3.1, + "value": -6.44, + "curve": [ 3.327, -7.06, 3.71, -6.23 ] + }, + { + "time": 3.9333, + "value": -5.41, + "curve": [ 4.168, -4.53, 4.488, -2.83 ] + }, + { "time": 4.8 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.025, 0, 0.09, -3.66 ] + }, + { + "time": 0.1, + "value": -4.55, + "curve": [ 0.143, -8.4, 0.223, -17.07 ] + }, + { + "time": 0.2333, + "value": -18.31, + "curve": [ 0.282, -24.44, 0.35, -29 ] + }, + { + "time": 0.3667, + "value": -30.07, + "curve": [ 0.405, -32.58, 0.442, -33.03 ] + }, + { + "time": 0.4667, + "value": -32.99, + "curve": [ 0.491, -33.04, 0.505, -23.56 ] + }, + { + "time": 0.5333, + "value": -23.55, + "curve": [ 0.571, -23.67, 0.599, -27.21 ] + }, + { + "time": 0.6333, + "value": -27.21, + "curve": [ 0.669, -27.2, 0.742, -10.43 ] + }, + { + "time": 0.7667, + "value": -7.79, + "curve": [ 0.788, -5.53, 0.796, -4.42 ] + }, + { + "time": 0.8333, + "value": -2.9, + "curve": [ 0.875, -1.21, 0.933, 0 ] + }, + { "time": 0.9667, "curve": "stepped" }, + { + "time": 2.4333, + "curve": [ 2.517, 0, 2.683, 4.63 ] + }, + { + "time": 2.7667, + "value": 4.66, + "curve": [ 3.084, 4.76, 3.248, 4.37 ] + }, + { + "time": 3.4, + "value": 3.74, + "curve": [ 3.596, 2.92, 3.755, 2.18 ] + }, + { + "time": 3.8667, + "value": 1.72, + "curve": [ 4.136, 0.59, 4.471, 0 ] + }, + { "time": 4.8 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0, 0, 0.041, 10.74 ] + }, + { + "time": 0.0667, + "value": 14.16, + "curve": [ 0.075, 15.22, 0.148, 18.04 ] + }, + { + "time": 0.2, + "value": 18.13, + "curve": [ 0.251, 18.23, 0.307, -4.75 ] + }, + { + "time": 0.3667, + "value": -5.06, + "curve": [ 0.412, -5.3, 0.47, -0.96 ] + }, + { + "time": 0.5, + "value": 2.21, + "curve": [ 0.512, 3.48, 0.595, 20.31 ] + }, + { + "time": 0.6333, + "value": 24.87, + "curve": [ 0.647, 26.53, 0.719, 29.33 ] + }, + { + "time": 0.8, + "value": 29.22, + "curve": [ 0.859, 29.14, 0.9, 28.48 ] + }, + { + "time": 0.9333, + "value": 26.11, + "curve": [ 0.981, 22.72, 0.998, 2.06 ] + }, + { "time": 1.1, "value": 2.21 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.047, -0.21, 0.048, 7.86 ] + }, + { + "time": 0.0667, + "value": 13.27, + "curve": [ 0.083, 18.05, 0.135, 24.44 ] + }, + { + "time": 0.2, + "value": 24.02, + "curve": [ 0.225, 24.02, 0.28, 6.32 ] + }, + { + "time": 0.3, + "value": 3.1, + "curve": [ 0.323, -0.58, 0.382, -7.12 ] + }, + { + "time": 0.4667, + "value": -7.45, + "curve": [ 0.512, -7.66, 0.538, 12.13 ] + }, + { + "time": 0.5667, + "value": 16.46, + "curve": [ 0.609, 22.72, 0.672, 27.4 ] + }, + { + "time": 0.7333, + "value": 27.55, + "curve": [ 0.827, 27.4, 0.933, 23.23 ] + }, + { + "time": 0.9667, + "value": 19.11, + "curve": [ 0.998, 15.27, 1.092, -2.53 ] + }, + { + "time": 1.1333, + "value": -2.53, + "curve": [ 1.158, -2.53, 1.208, 0 ] + }, + { "time": 1.2333, "curve": "stepped" }, + { + "time": 2, + "curve": [ 2.075, 0, 2.248, 0.35 ] + }, + { + "time": 2.3333, + "value": 0.78, + "curve": [ 2.585, 2.06, 2.805, 3.46 ] + }, + { + "time": 3.2, + "value": 3.5, + "curve": [ 3.593, 3.54, 3.979, 2.36 ] + }, + { + "time": 4.1667, + "value": 1.55, + "curve": [ 4.391, 0.59, 4.447, 0.04 ] + }, + { + "time": 4.6, + "value": 0.04, + "curve": [ 4.642, 0.04, 4.742, 0 ] + }, + { "time": 4.9333 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.025, 0, 0.09, 1.43, 0.025, 0, 0.075, -34.76 ] + }, + { + "time": 0.1, + "x": 1.59, + "y": -34.76, + "curve": [ 0.214, 3.33, 0.375, 5.34, 0.192, -34.76, 0.441, -21.17 ] + }, + { + "time": 0.4667, + "x": 5.34, + "y": -12.57, + "curve": [ 0.492, 5.34, 0.55, 5.24, 0.482, -7.36, 0.504, 4.03 ] + }, + { + "time": 0.5667, + "x": 5.11, + "y": 4.01, + "curve": [ 0.658, 4.45, 0.679, 3.19, 0.649, 3.98, 0.642, -16.84 ] + }, + { + "time": 0.7, + "x": 2.8, + "y": -16.74, + "curve": [ 0.787, 1.15, 0.881, -1.29, 0.772, -16.62, 0.82, 8.95 ] + }, + { + "time": 0.9, + "x": -1.72, + "y": 8.91, + "curve": [ 0.961, -3.06, 1.025, -3.58, 0.975, 8.87, 0.951, -1.37 ] + }, + { + "time": 1.1, + "x": -3.58, + "y": -1.45, + "curve": [ 1.292, -3.58, 2.002, -2.4, 1.292, -1.56, 1.975, -1.45 ] + }, + { + "time": 2.1667, + "x": -1.39, + "y": -1.45, + "curve": [ 2.25, -0.88, 2.503, 1.38, 2.283, -1.45, 2.603, -12.44 ] + }, + { + "time": 2.6667, + "x": 2.13, + "y": -14.45, + "curve": [ 2.766, 2.59, 2.999, 2.81, 2.835, -19.73, 3.003, -25.2 ] + }, + { + "time": 3.1333, + "x": 2.91, + "y": -26.08, + "curve": [ 3.392, 3.1, 4.199, 4.05, 3.483, -28.44, 4.129, -27.23 ] + }, + { + "time": 4.3667, + "x": 4.81, + "y": -19.59, + "curve": [ 4.429, 5.1, 4.594, 8.54, 4.538, -14.08, 4.583, -7.88 ] + }, + { + "time": 4.6667, + "x": 8.65, + "y": -4.56, + "curve": [ 4.794, 8.86, 4.806, 5.93, 4.691, -3.59, 4.8, -1.61 ] + }, + { "time": 4.9333, "x": 5.8, "y": -1.99 } + ] + } + }, + "ik": { + "front-foot-ik": [ + { "mix": 0 } + ], + "front-leg-ik": [ + { "mix": 0, "bendPositive": false } + ], + "rear-foot-ik": [ + { "mix": 0.005 } + ], + "rear-leg-ik": [ + { "mix": 0.005, "bendPositive": false } + ] + } + }, + "hoverboard": { + "slots": { + "exhaust1": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "exhaust2": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "exhaust3": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "hoverboard-board": { + "attachment": [ + { "name": "hoverboard-board" } + ] + }, + "hoverboard-thruster-front": { + "attachment": [ + { "name": "hoverboard-thruster" } + ] + }, + "hoverboard-thruster-rear": { + "attachment": [ + { "name": "hoverboard-thruster" } + ] + }, + "hoverglow-front": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "hoverglow-rear": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "side-glow1": { + "attachment": [ + { "name": "hoverglow-small" }, + { "time": 0.9667 } + ] + }, + "side-glow2": { + "attachment": [ + { "time": 0.0667, "name": "hoverglow-small" }, + { "time": 1 } + ] + }, + "side-glow3": { + "attachment": [ + { "name": "hoverglow-small" }, + { "time": 0.9667 } + ] + } + }, + "bones": { + "hoverboard-controller": { + "translate": [ + { + "x": 319.55, + "y": -1.59, + "curve": [ 0.064, 319.55, 0.2, 347.85, 0.058, -1.2, 0.2, 23.11 ] + }, + { + "time": 0.2667, + "x": 347.66, + "y": 39.62, + "curve": [ 0.35, 347.41, 0.476, 341.47, 0.323, 53.58, 0.44, 85.82 ] + }, + { + "time": 0.5333, + "x": 338.47, + "y": 85.72, + "curve": [ 0.603, 334.83, 0.913, 319.65, 0.621, 85.62, 0.88, -1.53 ] + }, + { "time": 1, "x": 319.55, "y": -1.59 } + ] + }, + "hip": { + "translate": [ + { + "x": -53.49, + "y": 32.14, + "curve": [ 0.061, -53.77, 0.093, -51.81, 0.044, 16.34, 0.063, 9.67 ] + }, + { + "time": 0.1333, + "x": -49.31, + "y": 7.01, + "curve": [ 0.3, -35.27, 0.461, -20.06, 0.314, 9.52, 0.408, 121.09 ] + }, + { + "time": 0.5667, + "x": -20.06, + "y": 122.72, + "curve": [ 0.716, -20.09, 0.912, -53.29, 0.753, 121.8, 0.946, 51.85 ] + }, + { "time": 1, "x": -53.49, "y": 32.14 } + ] + }, + "exhaust1": { + "scale": [ + { + "x": 1.593, + "y": 0.964, + "curve": [ 0.033, 1.593, 0.1, 1, 0.033, 0.964, 0.1, 0.713 ] + }, + { + "time": 0.1333, + "y": 0.713, + "curve": [ 0.15, 1, 0.183, 1.774, 0.15, 0.713, 0.183, 0.883 ] + }, + { + "time": 0.2, + "x": 1.774, + "y": 0.883, + "curve": [ 0.242, 1.774, 0.325, 1.181, 0.242, 0.883, 0.325, 0.649 ] + }, + { + "time": 0.3667, + "x": 1.181, + "y": 0.649, + "curve": [ 0.408, 1.181, 0.492, 1.893, 0.408, 0.649, 0.492, 0.819 ] + }, + { + "time": 0.5333, + "x": 1.893, + "y": 0.819, + "curve": [ 0.558, 1.893, 0.608, 1.18, 0.558, 0.819, 0.608, 0.686 ] + }, + { + "time": 0.6333, + "x": 1.18, + "y": 0.686, + "curve": [ 0.658, 1.18, 0.708, 1.903, 0.658, 0.686, 0.708, 0.855 ] + }, + { + "time": 0.7333, + "x": 1.903, + "y": 0.855, + "curve": [ 0.767, 1.903, 0.833, 1.311, 0.767, 0.855, 0.833, 0.622 ] + }, + { + "time": 0.8667, + "x": 1.311, + "y": 0.622, + "curve": [ 0.9, 1.311, 0.967, 1.593, 0.9, 0.622, 0.967, 0.964 ] + }, + { "time": 1, "x": 1.593, "y": 0.964 } + ] + }, + "exhaust2": { + "scale": [ + { + "x": 1.88, + "y": 0.832, + "curve": [ 0.025, 1.88, 0.075, 1.311, 0.025, 0.832, 0.075, 0.686 ] + }, + { + "time": 0.1, + "x": 1.311, + "y": 0.686, + "curve": [ 0.133, 1.311, 0.2, 2.01, 0.133, 0.686, 0.208, 0.736 ] + }, + { + "time": 0.2333, + "x": 2.01, + "y": 0.769, + "curve": [ 0.267, 2.01, 0.333, 1, 0.282, 0.831, 0.333, 0.91 ] + }, + { + "time": 0.3667, + "y": 0.91, + "curve": [ 0.4, 1, 0.467, 1.699, 0.4, 0.91, 0.474, 0.891 ] + }, + { + "time": 0.5, + "x": 1.699, + "y": 0.86, + "curve": [ 0.517, 1.699, 0.55, 1.181, 0.54, 0.813, 0.55, 0.713 ] + }, + { + "time": 0.5667, + "x": 1.181, + "y": 0.713, + "curve": [ 0.617, 1.181, 0.717, 1.881, 0.617, 0.713, 0.717, 0.796 ] + }, + { + "time": 0.7667, + "x": 1.881, + "y": 0.796, + "curve": [ 0.8, 1.881, 0.867, 1.3, 0.8, 0.796, 0.867, 0.649 ] + }, + { + "time": 0.9, + "x": 1.3, + "y": 0.649, + "curve": [ 0.925, 1.3, 0.975, 1.88, 0.925, 0.649, 0.975, 0.832 ] + }, + { "time": 1, "x": 1.88, "y": 0.832 } + ] + }, + "hoverboard-thruster-front": { + "rotate": [ + { + "curve": [ 0.125, 0, 0.375, 24.06 ] + }, + { + "time": 0.5, + "value": 24.06, + "curve": [ 0.625, 24.06, 0.875, 0 ] + }, + { "time": 1 } + ] + }, + "hoverglow-front": { + "scale": [ + { + "x": 0.849, + "y": 1.764, + "curve": [ 0.017, 0.849, 0.05, 0.835, 0.017, 1.764, 0.05, 2.033 ] + }, + { + "time": 0.0667, + "x": 0.835, + "y": 2.033, + "curve": [ 0.092, 0.835, 0.142, 0.752, 0.092, 2.033, 0.142, 1.584 ] + }, + { + "time": 0.1667, + "x": 0.752, + "y": 1.584, + "curve": [ 0.183, 0.752, 0.217, 0.809, 0.183, 1.584, 0.217, 1.71 ] + }, + { + "time": 0.2333, + "x": 0.809, + "y": 1.71, + "curve": [ 0.25, 0.809, 0.283, 0.717, 0.25, 1.71, 0.283, 1.45 ] + }, + { + "time": 0.3, + "x": 0.717, + "y": 1.45, + "curve": [ 0.317, 0.717, 0.35, 0.777, 0.317, 1.45, 0.35, 1.698 ] + }, + { + "time": 0.3667, + "x": 0.777, + "y": 1.698, + "curve": [ 0.4, 0.781, 0.45, 0.685, 0.375, 1.698, 0.45, 1.173 ] + }, + { + "time": 0.4667, + "x": 0.685, + "y": 1.173, + "curve": [ 0.492, 0.685, 0.542, 0.825, 0.492, 1.173, 0.542, 1.572 ] + }, + { + "time": 0.5667, + "x": 0.825, + "y": 1.572, + "curve": [ 0.611, 0.816, 0.63, 0.727, 0.611, 1.577, 0.606, 1.255 ] + }, + { + "time": 0.6667, + "x": 0.725, + "y": 1.241, + "curve": [ 0.692, 0.725, 0.742, 0.895, 0.692, 1.241, 0.749, 1.799 ] + }, + { + "time": 0.7667, + "x": 0.895, + "y": 1.857, + "curve": [ 0.783, 0.895, 0.796, 0.892, 0.796, 1.955, 0.817, 1.962 ] + }, + { + "time": 0.8333, + "x": 0.845, + "y": 1.962, + "curve": [ 0.845, 0.831, 0.883, 0.802, 0.85, 1.962, 0.872, 1.704 ] + }, + { + "time": 0.9, + "x": 0.802, + "y": 1.491, + "curve": [ 0.917, 0.802, 0.95, 0.845, 0.907, 1.441, 0.936, 1.508 ] + }, + { + "time": 0.9667, + "x": 0.845, + "y": 1.627, + "curve": [ 0.975, 0.845, 0.992, 0.849, 0.973, 1.652, 0.992, 1.764 ] + }, + { "time": 1, "x": 0.849, "y": 1.764 } + ] + }, + "hoverboard-thruster-rear": { + "rotate": [ + { + "curve": [ 0.125, 0, 0.375, 24.06 ] + }, + { + "time": 0.5, + "value": 24.06, + "curve": [ 0.625, 24.06, 0.875, 0 ] + }, + { "time": 1 } + ] + }, + "hoverglow-rear": { + "scale": [ + { + "x": 0.845, + "y": 1.31, + "curve": [ 0.017, 0.845, 0.117, 0.899, 0.017, 1.31, 0.117, 2.033 ] + }, + { + "time": 0.1333, + "x": 0.899, + "y": 2.033, + "curve": [ 0.15, 0.899, 0.183, 0.752, 0.15, 2.033, 0.183, 1.574 ] + }, + { + "time": 0.2, + "x": 0.752, + "y": 1.574, + "curve": [ 0.225, 0.752, 0.275, 0.809, 0.225, 1.574, 0.275, 1.71 ] + }, + { + "time": 0.3, + "x": 0.809, + "y": 1.71, + "curve": [ 0.317, 0.809, 0.35, 0.717, 0.317, 1.71, 0.35, 1.397 ] + }, + { + "time": 0.3667, + "x": 0.717, + "y": 1.397, + "curve": [ 0.383, 0.717, 0.417, 0.777, 0.383, 1.397, 0.417, 1.45 ] + }, + { + "time": 0.4333, + "x": 0.777, + "y": 1.45, + "curve": [ 0.45, 0.777, 0.496, 0.689, 0.45, 1.45, 0.481, 1.168 ] + }, + { + "time": 0.5333, + "x": 0.685, + "y": 1.173, + "curve": [ 0.565, 0.682, 0.617, 0.758, 0.575, 1.177, 0.617, 1.297 ] + }, + { + "time": 0.6333, + "x": 0.758, + "y": 1.297, + "curve": [ 0.658, 0.758, 0.708, 0.725, 0.658, 1.297, 0.708, 1.241 ] + }, + { + "time": 0.7333, + "x": 0.725, + "y": 1.241, + "curve": [ 0.772, 0.732, 0.796, 0.893, 0.782, 1.238, 0.778, 1.854 ] + }, + { + "time": 0.8333, + "x": 0.895, + "y": 1.857, + "curve": [ 0.878, 0.9, 0.992, 0.845, 0.88, 1.86, 0.992, 1.31 ] + }, + { "time": 1, "x": 0.845, "y": 1.31 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -85.92, + "curve": [ 0.08, -85.59, 0.284, -62.7 ] + }, + { + "time": 0.3667, + "value": -55.14, + "curve": [ 0.438, -48.65, 0.551, -43.21 ] + }, + { + "time": 0.6333, + "value": -43.21, + "curve": [ 0.716, -43.22, 0.908, -85.92 ] + }, + { "time": 1, "value": -85.92 } + ], + "translate": [ + { + "x": -0.59, + "y": -2.94, + "curve": [ 0.1, -1.21, 0.275, -1.74, 0.092, -2.94, 0.275, -6.39 ] + }, + { + "time": 0.3667, + "x": -1.74, + "y": -6.39, + "curve": [ 0.433, -1.74, 0.567, 0.72, 0.433, -6.39, 0.587, -4.48 ] + }, + { + "time": 0.6333, + "x": 0.72, + "y": -4.21, + "curve": [ 0.725, 0.72, 0.908, -0.08, 0.743, -3.57, 0.908, -2.94 ] + }, + { "time": 1, "x": -0.59, "y": -2.94 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": 7.61, + "curve": [ 0.143, 7.62, 0.247, -23.17 ] + }, + { + "time": 0.2667, + "value": -26.56, + "curve": [ 0.281, -29.08, 0.351, -37.36 ] + }, + { + "time": 0.4333, + "value": -37.2, + "curve": [ 0.513, -37.05, 0.562, -29.88 ] + }, + { + "time": 0.6, + "value": -25.18, + "curve": [ 0.621, -22.58, 0.694, -3.98 ] + }, + { + "time": 0.8, + "value": 3.63, + "curve": [ 0.861, 8.03, 0.946, 7.57 ] + }, + { "time": 1, "value": 7.61 } + ], + "translate": [ + { + "curve": [ 0.117, 0, 0.35, 0.52, 0.117, 0, 0.35, -3.27 ] + }, + { + "time": 0.4667, + "x": 0.52, + "y": -3.27, + "curve": [ 0.6, 0.52, 0.867, 0, 0.6, -3.27, 0.867, 0 ] + }, + { "time": 1 } + ], + "shear": [ + { + "y": 19.83, + "curve": [ 0.117, 0, 0.35, 15.28, 0.117, 19.83, 0.35, 28.31 ] + }, + { + "time": 0.4667, + "x": 15.28, + "y": 28.31, + "curve": [ 0.6, 15.28, 0.867, 0, 0.6, 28.31, 0.867, 19.83 ] + }, + { "time": 1, "y": 19.83 } + ] + }, + "board-ik": { + "translate": [ + { + "x": 393.62, + "curve": [ 0.083, 393.62, 0.25, 393.48, 0.083, 0, 0.25, 117.69 ] + }, + { + "time": 0.3333, + "x": 393.48, + "y": 117.69, + "curve": [ 0.375, 393.48, 0.458, 393.62, 0.375, 117.69, 0.458, 83.82 ] + }, + { "time": 0.5, "x": 393.62, "y": 83.82 }, + { "time": 0.6667, "x": 393.62, "y": 30.15 }, + { "time": 1, "x": 393.62 } + ] + }, + "front-thigh": { + "translate": [ + { "x": -7.49, "y": 8.51 } + ] + }, + "front-leg-target": { + "translate": [ + { + "time": 0.3667, + "curve": [ 0.428, 10.83, 0.567, 12.78, 0.414, 7.29, 0.567, 8.79 ] + }, + { + "time": 0.6, + "x": 12.78, + "y": 8.79, + "curve": [ 0.692, 12.78, 0.772, 11.27, 0.692, 8.79, 0.766, 8.62 ] + }, + { "time": 0.8667 } + ] + }, + "rear-leg-target": { + "translate": [ + { + "time": 0.4667, + "curve": [ 0.492, 0, 0.534, 4.47, 0.492, 0, 0.542, 1.63 ] + }, + { + "time": 0.5667, + "x": 4.53, + "y": 1.77, + "curve": [ 0.622, 4.64, 0.717, 3.31, 0.615, 2.06, 0.71, 2.1 ] + }, + { "time": 0.8 } + ] + }, + "exhaust3": { + "scale": [ + { + "x": 1.882, + "y": 0.81, + "curve": [ 0.017, 1.882, 0.167, 1.3, 0.017, 0.81, 0.167, 0.649 ] + }, + { + "time": 0.2, + "x": 1.3, + "y": 0.649, + "curve": [ 0.225, 1.3, 0.275, 2.051, 0.225, 0.649, 0.275, 0.984 ] + }, + { + "time": 0.3, + "x": 2.051, + "y": 0.984, + "curve": [ 0.325, 2.051, 0.375, 1.311, 0.325, 0.984, 0.384, 0.715 ] + }, + { + "time": 0.4, + "x": 1.311, + "y": 0.686, + "curve": [ 0.433, 1.311, 0.5, 1.86, 0.426, 0.638, 0.5, 0.537 ] + }, + { + "time": 0.5333, + "x": 1.86, + "y": 0.537, + "curve": [ 0.567, 1.86, 0.633, 1.187, 0.567, 0.537, 0.604, 0.854 ] + }, + { + "time": 0.6667, + "x": 1.187, + "y": 0.854, + "curve": [ 0.7, 1.187, 0.767, 1.549, 0.707, 0.854, 0.774, 0.775 ] + }, + { + "time": 0.8, + "x": 1.549, + "y": 0.746, + "curve": [ 0.817, 1.549, 0.85, 1.181, 0.815, 0.729, 0.85, 0.713 ] + }, + { + "time": 0.8667, + "x": 1.181, + "y": 0.713, + "curve": [ 0.9, 1.181, 0.967, 1.882, 0.9, 0.713, 0.967, 0.81 ] + }, + { "time": 1, "x": 1.882, "y": 0.81 } + ] + }, + "side-glow1": { + "rotate": [ + { "value": 51.12, "curve": "stepped" }, + { "time": 0.0667, "value": 43.82, "curve": "stepped" }, + { "time": 0.1, "value": 40.95, "curve": "stepped" }, + { "time": 0.1667, "value": 27.78, "curve": "stepped" }, + { "time": 0.2, "value": 10.24, "curve": "stepped" }, + { "time": 0.2667, "curve": "stepped" }, + { "time": 0.8, "value": -25.81 } + ], + "translate": [ + { "x": 338.28, "y": 40.22, "curve": "stepped" }, + { "time": 0.0667, "x": 331.2, "y": 30.39, "curve": "stepped" }, + { "time": 0.1, "x": 318.63, "y": 20.59, "curve": "stepped" }, + { "time": 0.1667, "x": 302.45, "y": 9.64, "curve": "stepped" }, + { "time": 0.2, "x": 276.87, "y": 1.13, "curve": "stepped" }, + { "time": 0.2667, "x": 248.16, "curve": "stepped" }, + { "time": 0.3, "x": 221.36, "curve": "stepped" }, + { "time": 0.3667, "x": 195.69, "curve": "stepped" }, + { "time": 0.4, "x": 171.08, "curve": "stepped" }, + { "time": 0.4667, "x": 144.84, "curve": "stepped" }, + { "time": 0.5, "x": 121.22, "curve": "stepped" }, + { "time": 0.5667, "x": 91.98, "curve": "stepped" }, + { "time": 0.6, "x": 62.63, "curve": "stepped" }, + { "time": 0.6667, "x": 30.78, "curve": "stepped" }, + { "time": 0.7, "curve": "stepped" }, + { "time": 0.7667, "x": -28.45, "curve": "stepped" }, + { "time": 0.8, "x": -67.49, "y": 16.82, "curve": "stepped" }, + { "time": 0.8667, "x": -83.07, "y": 24.36, "curve": "stepped" }, + { "time": 0.9, "x": -93.81, "y": 29.55 } + ], + "scale": [ + { "x": 0.535, "curve": "stepped" }, + { "time": 0.0667, "x": 0.594, "curve": "stepped" }, + { "time": 0.1, "x": 0.844, "curve": "stepped" }, + { "time": 0.1667, "curve": "stepped" }, + { "time": 0.8, "x": 0.534, "curve": "stepped" }, + { "time": 0.8667, "x": 0.428, "y": 0.801, "curve": "stepped" }, + { "time": 0.9, "x": 0.349, "y": 0.654 } + ] + }, + "side-glow2": { + "rotate": [ + { "time": 0.0667, "value": 51.12, "curve": "stepped" }, + { "time": 0.1, "value": 43.82, "curve": "stepped" }, + { "time": 0.1667, "value": 40.95, "curve": "stepped" }, + { "time": 0.2, "value": 27.78, "curve": "stepped" }, + { "time": 0.2667, "value": 10.24, "curve": "stepped" }, + { "time": 0.3, "curve": "stepped" }, + { "time": 0.8667, "value": -25.81 } + ], + "translate": [ + { "time": 0.0667, "x": 338.28, "y": 40.22, "curve": "stepped" }, + { "time": 0.1, "x": 331.2, "y": 30.39, "curve": "stepped" }, + { "time": 0.1667, "x": 318.63, "y": 20.59, "curve": "stepped" }, + { "time": 0.2, "x": 302.45, "y": 9.64, "curve": "stepped" }, + { "time": 0.2667, "x": 276.87, "y": 1.13, "curve": "stepped" }, + { "time": 0.3, "x": 248.16, "curve": "stepped" }, + { "time": 0.3667, "x": 221.36, "curve": "stepped" }, + { "time": 0.4, "x": 195.69, "curve": "stepped" }, + { "time": 0.4667, "x": 171.08, "curve": "stepped" }, + { "time": 0.5, "x": 144.84, "curve": "stepped" }, + { "time": 0.5667, "x": 121.22, "curve": "stepped" }, + { "time": 0.6, "x": 91.98, "curve": "stepped" }, + { "time": 0.6667, "x": 62.63, "curve": "stepped" }, + { "time": 0.7, "x": 30.78, "curve": "stepped" }, + { "time": 0.7667, "curve": "stepped" }, + { "time": 0.8, "x": -28.45, "curve": "stepped" }, + { "time": 0.8667, "x": -67.49, "y": 16.82, "curve": "stepped" }, + { "time": 0.9, "x": -83.07, "y": 24.36, "curve": "stepped" }, + { "time": 0.9667, "x": -93.81, "y": 29.55 } + ], + "scale": [ + { "time": 0.0667, "x": 0.535, "curve": "stepped" }, + { "time": 0.1, "x": 0.594, "curve": "stepped" }, + { "time": 0.1667, "x": 0.844, "curve": "stepped" }, + { "time": 0.2, "curve": "stepped" }, + { "time": 0.8667, "x": 0.534, "curve": "stepped" }, + { "time": 0.9, "x": 0.428, "y": 0.801, "curve": "stepped" }, + { "time": 0.9667, "x": 0.349, "y": 0.654 } + ] + }, + "torso": { + "rotate": [ + { + "value": -34.73, + "curve": [ 0.034, -36.31, 0.162, -39.33 ] + }, + { + "time": 0.2667, + "value": -39.37, + "curve": [ 0.384, -39.37, 0.491, -29.52 ] + }, + { + "time": 0.5, + "value": -28.86, + "curve": [ 0.525, -26.95, 0.571, -21.01 ] + }, + { + "time": 0.6333, + "value": -21.01, + "curve": [ 0.725, -21.01, 0.969, -33.35 ] + }, + { "time": 1, "value": -34.73 } + ] + }, + "neck": { + "rotate": [ + { + "value": 10.2, + "curve": [ 0.07, 12.09, 0.189, 16.03 ] + }, + { + "time": 0.2667, + "value": 16.14, + "curve": [ 0.333, 16.14, 0.449, 8.03 ] + }, + { + "time": 0.5, + "value": 5.83, + "curve": [ 0.542, 4.02, 0.6, 2.68 ] + }, + { + "time": 0.6333, + "value": 2.68, + "curve": [ 0.725, 2.68, 0.943, 8.57 ] + }, + { "time": 1, "value": 10.2 } + ] + }, + "head": { + "rotate": [ + { + "value": 10.2, + "curve": [ 0.044, 11.52, 0.2, 16.12 ] + }, + { + "time": 0.2667, + "value": 16.14, + "curve": [ 0.375, 16.17, 0.492, 2.65 ] + }, + { + "time": 0.6333, + "value": 2.68, + "curve": [ 0.725, 2.7, 0.963, 9.26 ] + }, + { "time": 1, "value": 10.2 } + ], + "translate": [ + { + "curve": [ 0.03, -0.24, 0.2, -4.22, 0.051, -1.06, 0.2, -3.62 ] + }, + { + "time": 0.2667, + "x": -4.22, + "y": -3.62, + "curve": [ 0.358, -4.22, 0.542, 0.84, 0.358, -3.62, 0.542, 6.01 ] + }, + { + "time": 0.6333, + "x": 0.84, + "y": 6.01, + "curve": [ 0.725, 0.84, 0.939, 0.32, 0.725, 6.01, 0.945, 1.14 ] + }, + { "time": 1 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": -11.18, + "curve": [ 0.064, -14.82, 0.25, -20.01 ] + }, + { + "time": 0.3333, + "value": -20.01, + "curve": [ 0.429, -20.12, 0.58, 5.12 ] + }, + { + "time": 0.6, + "value": 8.67, + "curve": [ 0.617, 11.72, 0.687, 20.52 ] + }, + { + "time": 0.7667, + "value": 20.55, + "curve": [ 0.848, 20.7, 0.963, -9.43 ] + }, + { "time": 1, "value": -11.18 } + ] + }, + "hair3": { + "rotate": [ + { + "value": 9.61, + "curve": [ 0.014, 8.51, 0.075, 2.63 ] + }, + { + "time": 0.1, + "value": 2.63, + "curve": [ 0.15, 2.63, 0.25, 13.52 ] + }, + { + "time": 0.3, + "value": 13.52, + "curve": [ 0.35, 13.52, 0.45, 11.28 ] + }, + { + "time": 0.5, + "value": 11.28, + "curve": [ 0.575, 11.28, 0.725, 18.13 ] + }, + { + "time": 0.8, + "value": 18.13, + "curve": [ 0.85, 18.13, 0.978, 11.07 ] + }, + { "time": 1, "value": 9.61 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -17.7, + "curve": [ 0.008, -17.7, 0.025, -23.73 ] + }, + { + "time": 0.0333, + "value": -23.73, + "curve": [ 0.067, -23.73, 0.154, -4.4 ] + }, + { + "time": 0.1667, + "value": -1.92, + "curve": [ 0.197, 4.09, 0.236, 12.91 ] + }, + { + "time": 0.2667, + "value": 17.56, + "curve": [ 0.301, 22.68, 0.342, 27.97 ] + }, + { + "time": 0.3667, + "value": 27.97, + "curve": [ 0.4, 27.97, 0.467, -1.45 ] + }, + { + "time": 0.5, + "value": -1.45, + "curve": [ 0.517, -1.45, 0.55, 3.16 ] + }, + { + "time": 0.5667, + "value": 3.16, + "curve": [ 0.583, 3.16, 0.617, -8.9 ] + }, + { + "time": 0.6333, + "value": -8.9, + "curve": [ 0.642, -8.9, 0.658, -5.4 ] + }, + { + "time": 0.6667, + "value": -5.4, + "curve": [ 0.683, -5.4, 0.717, -15.32 ] + }, + { + "time": 0.7333, + "value": -15.32, + "curve": [ 0.75, -15.32, 0.783, -9.19 ] + }, + { + "time": 0.8, + "value": -9.19, + "curve": [ 0.817, -9.19, 0.85, -23.6 ] + }, + { + "time": 0.8667, + "value": -23.6, + "curve": [ 0.883, -23.6, 0.917, -17.38 ] + }, + { + "time": 0.9333, + "value": -17.38, + "curve": [ 0.942, -17.38, 0.958, -20.46 ] + }, + { + "time": 0.9667, + "value": -20.46, + "curve": [ 0.975, -20.46, 0.992, -17.7 ] + }, + { "time": 1, "value": -17.7 } + ] + }, + "hair1": { + "rotate": [ + { + "value": 9.61, + "curve": [ 0.06, 9.04, 0.25, 8.9 ] + }, + { + "time": 0.3333, + "value": 8.9, + "curve": [ 0.392, 8.9, 0.508, 14.58 ] + }, + { + "time": 0.5667, + "value": 14.58, + "curve": [ 0.675, 14.58, 0.956, 10.28 ] + }, + { "time": 1, "value": 9.61 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -3.82, + "curve": [ 0.017, -3.82, 0.064, -9.16 ] + }, + { + "time": 0.1333, + "value": -9.09, + "curve": [ 0.178, -9.04, 0.234, 1.29 ] + }, + { + "time": 0.2667, + "value": 5.98, + "curve": [ 0.276, 7.27, 0.336, 17.1 ] + }, + { + "time": 0.3667, + "value": 17.1, + "curve": [ 0.413, 17.1, 0.467, 1.59 ] + }, + { + "time": 0.5, + "value": 1.59, + "curve": [ 0.533, 1.59, 0.567, 13.63 ] + }, + { + "time": 0.6, + "value": 13.63, + "curve": [ 0.617, 13.63, 0.683, 0.78 ] + }, + { + "time": 0.7, + "value": 0.78, + "curve": [ 0.717, 0.78, 0.75, 12.01 ] + }, + { + "time": 0.7667, + "value": 11.9, + "curve": [ 0.792, 11.73, 0.817, -0.85 ] + }, + { + "time": 0.8333, + "value": -0.85, + "curve": [ 0.85, -0.85, 0.88, 1.99 ] + }, + { + "time": 0.9, + "value": 1.82, + "curve": [ 0.916, 1.68, 0.95, -6.9 ] + }, + { + "time": 0.9667, + "value": -6.9, + "curve": [ 0.975, -6.9, 0.992, -3.82 ] + }, + { "time": 1, "value": -3.82 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 31.65, + "curve": [ 0.108, 31.65, 0.325, 13.01 ] + }, + { + "time": 0.4333, + "value": 13.01, + "curve": [ 0.71, 13.01, 0.917, 31.65 ] + }, + { "time": 1, "value": 31.65 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 31, + "curve": [ 0.108, 31, 0.325, 12.76 ] + }, + { + "time": 0.4333, + "value": 12.79, + "curve": [ 0.587, 12.82, 0.917, 31 ] + }, + { "time": 1, "value": 31 } + ] + }, + "gun": { + "rotate": [ + { + "value": 1.95, + "curve": [ 0.083, 1.95, 0.245, 36.73 ] + }, + { + "time": 0.3333, + "value": 36.71, + "curve": [ 0.439, 36.69, 0.589, 10.68 ] + }, + { + "time": 0.6333, + "value": 8.75, + "curve": [ 0.701, 5.81, 0.917, 1.95 ] + }, + { "time": 1, "value": 1.95 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 2.35 ] + }, + { + "time": 0.1333, + "value": 2.35, + "curve": [ 0.225, 2.35, 0.408, -2.4 ] + }, + { + "time": 0.5, + "value": -2.4, + "curve": [ 0.567, -2.4, 0.7, 1.44 ] + }, + { + "time": 0.7667, + "value": 1.44, + "curve": [ 0.825, 1.44, 0.942, 0 ] + }, + { "time": 1 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.063, 0.77, 0.106, 1.42 ] + }, + { + "time": 0.1667, + "value": 1.42, + "curve": [ 0.259, 1.42, 0.344, -1.25 ] + }, + { + "time": 0.4667, + "value": -1.26, + "curve": [ 0.656, -1.26, 0.917, -0.78 ] + }, + { "time": 1 } + ] + }, + "head-control": { + "translate": [ + { + "x": 0.37, + "y": -11.17, + "curve": [ 0.133, 0.37, 0.335, -10.23, 0.133, -11.17, 0.335, 3.15 ] + }, + { + "time": 0.5333, + "x": -10.23, + "y": 3.15, + "curve": [ 0.71, -10.23, 0.883, 0.37, 0.71, 3.15, 0.883, -11.17 ] + }, + { "time": 1, "x": 0.37, "y": -11.17 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.46, + "y": 10.15, + "curve": [ 0.103, 1.46, 0.249, 1.36, 0.103, 10.15, 0.249, -4.39 ] + }, + { + "time": 0.4, + "x": 1.36, + "y": -4.39, + "curve": [ 0.621, 1.36, 0.85, 1.46, 0.621, -4.39, 0.85, 10.15 ] + }, + { "time": 1, "x": 1.46, "y": 10.15 } + ] + }, + "back-shoulder": { + "translate": [ + { + "x": 1.4, + "y": 0.44, + "curve": [ 0.088, 1.4, 0.208, -2.47, 0.088, 0.44, 0.208, 8.61 ] + }, + { + "time": 0.3333, + "x": -2.47, + "y": 8.61, + "curve": [ 0.572, -2.47, 0.833, 1.4, 0.572, 8.61, 0.833, 0.44 ] + }, + { "time": 1, "x": 1.4, "y": 0.44 } + ] + } + }, + "transform": { + "front-foot-board-transform": [ + { "mixRotate": 0.997 } + ], + "rear-foot-board-transform": [ + {} + ], + "toes-board": [ + { "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ] + }, + "attachments": { + "default": { + "front-foot": { + "front-foot": { + "deform": [ + { + "offset": 26, + "vertices": [ -0.02832, -5.37024, -0.02832, -5.37024, 3.8188, -3.7757, -0.02832, -5.37024, -3.82159, 3.77847 ] + } + ] + } + }, + "front-shin": { + "front-shin": { + "deform": [ + { + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + }, + { + "time": 0.3667, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -11.66571, -9.07211, -25.65866, -17.53735, -25.53217, -16.50978, -11.78232, -11.26097, 0, 0, 0.60487, -1.63589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0, 0, -2.64522, -7.35739, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0.60487, -1.63589, 0.60487, -1.63589, 0.60487, -1.63589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0, 0, -10.06873, -12.0999 ] + }, + { + "time": 0.5333, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -7.00775, -8.24771, -6.45482, -6.49312, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + }, + { + "time": 1, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + } + ] + } + }, + "hoverboard-board": { + "hoverboard-board": { + "deform": [ + { + "curve": [ 0.067, 0, 0.2, 1 ] + }, + { + "time": 0.2667, + "offset": 1, + "vertices": [ 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 3.55673, -3.0E-4, 3.55673, -3.0E-4, 0, 0, 0, 0, 0, 0, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, 0, 0, 0, 0, 0, 0, 0, 0, -4.90558, 0.11214, -9.40706, 6.2E-4, -6.34871, 4.3E-4, -6.34925, -6.57018, -6.34925, -6.57018, -6.34871, 4.3E-4, -2.3308, 1.7E-4, -2.33133, -6.57045, -2.33133, -6.57045, -2.3308, 1.7E-4, 0, 0, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 3.3297, 4.44005, 3.3297, 4.44005, 3.3297, 4.44005, 1.2E-4, 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, 1.2E-4, 2.45856, 1.2E-4, 2.45856, -9.40694, 2.45918, 1.88063, 0.44197, -2.9E-4, -3.54808, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.46227, 1.7E-4, 0, 0, 0, 0, 1.2E-4, 2.45856 ], + "curve": [ 0.45, 0, 0.817, 1 ] + }, + { "time": 1 } + ] + } + }, + "rear-foot": { + "rear-foot": { + "deform": [ + { + "offset": 28, + "vertices": [ -1.93078, 1.34782, -0.31417, 2.33363, 3.05122, 0.33946, 2.31472, -2.01678, 2.17583, -2.05795, -0.04277, -2.99459, 1.15429, 0.26328, 0.97501, -0.67169 ] + } + ] + } + } + } + } + }, + "idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-foot-target": { + "translate": [ + { "x": -69.06 } + ] + }, + "hip": { + "rotate": [ + { + "curve": [ 0.073, 0.35, 0.303, 1.27 ] + }, + { + "time": 0.4, + "value": 1.28, + "curve": [ 0.615, 1.3, 0.847, -1.41 ] + }, + { + "time": 1.2, + "value": -1.38, + "curve": [ 1.344, -1.37, 1.602, -0.28 ] + }, + { "time": 1.6667 } + ], + "translate": [ + { + "x": -11.97, + "y": -23.15, + "curve": [ 0.059, -12.96, 0.258, -15.19, 0.142, -23.15, 0.341, -24.89 ] + }, + { + "time": 0.4667, + "x": -15.14, + "y": -26.74, + "curve": [ 0.62, -15.1, 0.788, -13.28, 0.597, -28.66, 0.75, -30.01 ] + }, + { + "time": 0.9, + "x": -12.02, + "y": -30.01, + "curve": [ 0.978, -11.13, 1.175, -9.05, 1.036, -29.94, 1.234, -28.08 ] + }, + { + "time": 1.3333, + "x": -9.06, + "y": -26.64, + "curve": [ 1.501, -9.06, 1.614, -10.95, 1.454, -24.89, 1.609, -23.15 ] + }, + { "time": 1.6667, "x": -11.97, "y": -23.15 } + ] + }, + "rear-foot-target": { + "translate": [ + { "x": 48.87 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -60.87, + "curve": [ 0.154, -60.85, 0.452, -68.65 ] + }, + { + "time": 0.8333, + "value": -68.65, + "curve": [ 1.221, -68.65, 1.542, -60.87 ] + }, + { "time": 1.6667, "value": -60.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 42.46, + "curve": [ 0.029, 42.97, 0.134, 45.28 ] + }, + { + "time": 0.3333, + "value": 45.27, + "curve": [ 0.578, 45.26, 0.798, 40.07 ] + }, + { + "time": 0.8333, + "value": 39.74, + "curve": [ 0.878, 39.32, 1.019, 38.23 ] + }, + { + "time": 1.2, + "value": 38.22, + "curve": [ 1.377, 38.22, 1.619, 41.68 ] + }, + { "time": 1.6667, "value": 42.46 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 39.2, + "curve": [ 0.185, 39.22, 0.5, 29.37 ] + }, + { + "time": 0.6667, + "value": 29.37, + "curve": [ 0.917, 29.37, 1.417, 39.2 ] + }, + { "time": 1.6667, "value": 39.2 } + ] + }, + "head": { + "rotate": [ + { + "value": -6.75, + "curve": [ 0.176, -7.88, 0.349, -8.95 ] + }, + { + "time": 0.4667, + "value": -8.95, + "curve": [ 0.55, -8.95, 0.697, -6.77 ] + }, + { + "time": 0.8333, + "value": -5.44, + "curve": [ 0.88, -4.98, 1.05, -4.12 ] + }, + { + "time": 1.1333, + "value": -4.12, + "curve": [ 1.266, -4.12, 1.469, -5.48 ] + }, + { "time": 1.6667, "value": -6.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "curve": [ 0.086, 0, 0.233, 2.48 ] + }, + { + "time": 0.3333, + "value": 4.13, + "curve": [ 0.429, 5.7, 0.711, 10.06 ] + }, + { + "time": 0.8333, + "value": 10.06, + "curve": [ 0.926, 10.06, 1.092, 4.21 ] + }, + { + "time": 1.2, + "value": 2.78, + "curve": [ 1.349, 0.8, 1.551, 0 ] + }, + { "time": 1.6667 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "curve": [ 0.063, 0.54, 0.367, 3.39 ] + }, + { + "time": 0.5333, + "value": 3.39, + "curve": [ 0.696, 3.39, 0.939, -1.63 ] + }, + { + "time": 1.2, + "value": -1.61, + "curve": [ 1.42, -1.59, 1.574, -0.67 ] + }, + { "time": 1.6667 } + ] + }, + "gun": { + "rotate": [ + { + "curve": [ 0.099, 0.27, 0.367, 1.23 ] + }, + { + "time": 0.5333, + "value": 1.23, + "curve": [ 0.665, 1.23, 0.937, -0.56 ] + }, + { + "time": 1.1333, + "value": -0.55, + "curve": [ 1.316, -0.55, 1.582, -0.21 ] + }, + { "time": 1.6667 } + ] + }, + "torso": { + "rotate": [ + { + "value": -22.88, + "curve": [ 0.099, -23.45, 0.363, -24.74 ] + }, + { + "time": 0.5333, + "value": -24.74, + "curve": [ 0.706, -24.74, 0.961, -20.97 ] + }, + { + "time": 1.1333, + "value": -20.97, + "curve": [ 1.355, -20.97, 1.567, -22.28 ] + }, + { "time": 1.6667, "value": -22.88 } + ] + }, + "neck": { + "rotate": [ + { + "value": 3.78, + "curve": [ 0.167, 3.78, 0.5, 5.45 ] + }, + { + "time": 0.6667, + "value": 5.45, + "curve": [ 0.917, 5.45, 1.417, 3.78 ] + }, + { "time": 1.6667, "value": 3.78 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.067, 0.33, 0.341, 2.54 ] + }, + { + "time": 0.5333, + "value": 2.54, + "curve": [ 0.734, 2.55, 0.982, -0.94 ] + }, + { + "time": 1.1333, + "value": -0.93, + "curve": [ 1.365, -0.91, 1.549, -0.56 ] + }, + { "time": 1.6667 } + ] + }, + "torso3": { + "rotate": [ + { + "value": -2.15, + "curve": [ 0.052, -1.9, 0.384, -0.15 ] + }, + { + "time": 0.5333, + "value": -0.14, + "curve": [ 0.762, -0.13, 0.895, -3.1 ] + }, + { + "time": 1.1333, + "value": -3.1, + "curve": [ 1.348, -3.1, 1.592, -2.46 ] + }, + { "time": 1.6667, "value": -2.15 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.067, 0, 0.213, 2.86 ] + }, + { + "time": 0.2667, + "value": 3.65, + "curve": [ 0.358, 4.99, 0.535, 7.92 ] + }, + { + "time": 0.6667, + "value": 7.92, + "curve": [ 0.809, 7.92, 1.067, 5.49 ] + }, + { + "time": 1.1333, + "value": 4.7, + "curve": [ 1.245, 3.34, 1.525, 0 ] + }, + { "time": 1.6667 } + ] + }, + "hair2": { + "rotate": [ + { + "curve": [ 0.067, 0, 0.225, -7.97 ] + }, + { + "time": 0.2667, + "value": -9.75, + "curve": [ 0.316, -11.84, 0.519, -16.66 ] + }, + { + "time": 0.6667, + "value": -16.66, + "curve": [ 0.817, -16.66, 1.029, -11.43 ] + }, + { + "time": 1.1333, + "value": -9.14, + "curve": [ 1.25, -6.56, 1.525, 0 ] + }, + { "time": 1.6667 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.1, 0, 0.3, 1.32 ] + }, + { + "time": 0.4, + "value": 1.32, + "curve": [ 0.55, 1.32, 0.866, 0.93 ] + }, + { + "time": 1, + "value": 0.73, + "curve": [ 1.189, 0.46, 1.5, 0 ] + }, + { "time": 1.6667 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.118, -0.44, 0.3, -8.52 ] + }, + { + "time": 0.4, + "value": -8.52, + "curve": [ 0.55, -8.52, 0.85, 1.96 ] + }, + { + "time": 1, + "value": 1.96, + "curve": [ 1.167, 1.96, 1.577, 0.38 ] + }, + { "time": 1.6667 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.098, 1.46, 0.3, 4.49, 0.17, 0.13, 0.316, -3.28 ] + }, + { + "time": 0.4, + "x": 4.55, + "y": -5.95, + "curve": [ 0.53, 4.64, 0.776, 2.59, 0.492, -8.89, 0.668, -14.21 ] + }, + { + "time": 0.8667, + "x": 1.42, + "y": -14.26, + "curve": [ 0.966, 0.15, 1.109, -2.91, 0.994, -14.26, 1.144, -10.58 ] + }, + { + "time": 1.2333, + "x": -3.02, + "y": -8.26, + "curve": [ 1.342, -3.02, 1.568, -1.48, 1.317, -6.1, 1.558, 0 ] + }, + { "time": 1.6667 } + ] + }, + "front-shoulder": { + "translate": [ + { + "curve": [ 0.21, 0, 0.525, -1.72, 0.21, 0, 0.525, 4.08 ] + }, + { + "time": 0.8333, + "x": -1.72, + "y": 4.08, + "curve": [ 1.15, -1.72, 1.46, 0, 1.15, 4.08, 1.46, 0 ] + }, + { "time": 1.6667 } + ] + } + } + }, + "idle-turn": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-upper-arm": { + "rotate": [ + { + "value": -302.77, + "curve": [ 0, -406.9, 0.125, -420.87 ] + }, + { "time": 0.2667, "value": -420.87 } + ], + "translate": [ + { + "x": 2.24, + "y": -4.98, + "curve": [ 0.067, 2.24, 0.111, 0, 0.067, -4.98, 0.111, 0 ] + }, + { "time": 0.2667 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 248.56, + "curve": [ 0, 371.28, 0.062, 399.2 ] + }, + { "time": 0.1333, "value": 399.2 } + ], + "translate": [ + { + "x": -2.84, + "y": 37.28, + "curve": [ 0.033, -2.84, 0.069, 0, 0.033, 37.28, 0.069, 0 ] + }, + { "time": 0.1333 } + ] + }, + "gun": { + "rotate": [ + { + "value": -3.95, + "curve": [ 0, -10.4, 0.019, -20.43 ] + }, + { + "time": 0.0333, + "value": -20.45, + "curve": [ 0.044, -20.47, 0.125, 0 ] + }, + { "time": 0.2 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.2, + "curve": [ 0, 6.27, 0.125, 3.78 ] + }, + { "time": 0.2667, "value": 3.78 } + ] + }, + "hip": { + "translate": [ + { + "x": -2.69, + "y": -6.79, + "curve": [ 0.067, -2.69, 0.2, -11.97, 0.067, -6.79, 0.2, -23.15 ] + }, + { "time": 0.2667, "x": -11.97, "y": -23.15 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -15.54, + "curve": [ 0, -3.08, 0.034, 18.44 ] + }, + { + "time": 0.0667, + "value": 19.02, + "curve": [ 0.108, 19.75, 0.169, 0 ] + }, + { "time": 0.2667 } + ], + "scale": [ + { + "x": 0.94, + "curve": [ 0, 0.962, 0.024, 1.237, 0, 1, 0.026, 0.947 ] + }, + { + "time": 0.0667, + "x": 1.236, + "y": 0.947, + "curve": [ 0.117, 1.235, 0.189, 1, 0.117, 0.947, 0.189, 1 ] + }, + { "time": 0.2667 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 11.75, + "curve": [ 0, -7.97, 0.017, -33.4 ] + }, + { + "time": 0.0333, + "value": -33.39, + "curve": [ 0.049, -33.37, 0.131, 0 ] + }, + { "time": 0.2 } + ] + }, + "torso": { + "rotate": [ + { + "value": -18.25, + "curve": [ 0, -10.59, 0.125, -22.88 ] + }, + { "time": 0.2667, "value": -22.88 } + ], + "scale": [ + { + "y": 1.03, + "curve": [ 0.067, 1, 0.132, 1, 0.067, 1.03, 0.132, 1 ] + }, + { "time": 0.2667 } + ] + }, + "head": { + "rotate": [ + { + "value": 5.12, + "curve": [ 0, -6.34, 0.125, -6.75 ] + }, + { "time": 0.2667, "value": -6.75 } + ], + "scale": [ + { + "y": 1.03, + "curve": [ 0.067, 1, 0.107, 1, 0.067, 1.03, 0.107, 1 ] + }, + { "time": 0.2667 } + ] + }, + "rear-foot-target": { + "translate": [ + { + "x": -58.39, + "y": 30.48, + "curve": [ 0, -7.15, 0.047, 16.62, 0, 12.71, 0.039, 0.22 ] + }, + { + "time": 0.1, + "x": 34.14, + "y": -0.19, + "curve": [ 0.136, 45.79, 0.163, 48.87, 0.133, -0.41, 0.163, 0 ] + }, + { "time": 0.2, "x": 48.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 6.69, + "curve": [ 0, 19.76, 0.039, 56.53 ] + }, + { + "time": 0.0667, + "value": 56.63, + "curve": [ 0.114, 56.79, 0.189, 42.46 ] + }, + { "time": 0.2667, "value": 42.46 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": -1.85, + "curve": [ 0.014, -8.91, 0.047, -28.4 ] + }, + { + "time": 0.1, + "value": -28.89, + "curve": [ 0.144, -29.29, 0.262, -21.77 ] + }, + { "time": 0.2667 } + ], + "translate": [ + { + "x": 9.97, + "y": 0.82, + "curve": [ 0, -54.41, 0.078, -69.06, 0, 0.15, 0.078, 0 ] + }, + { "time": 0.1667, "x": -69.06 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -9.01, + "curve": [ 0.044, -9.01, 0.072, 7.41 ] + }, + { + "time": 0.1333, + "value": 10.08, + "curve": [ 0.166, 11.47, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -16.49, + "curve": [ 0.044, -16.49, 0.101, -5.98 ] + }, + { + "time": 0.1333, + "value": -2.95, + "curve": [ 0.162, -0.34, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -3.85, + "curve": [ 0.044, -3.85, 0.072, 6.91 ] + }, + { + "time": 0.1333, + "value": 8.05, + "curve": [ 0.166, 8.65, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair2": { + "rotate": [ + { + "value": 1.25, + "curve": [ 0.044, 1.25, 0.072, 8.97 ] + }, + { + "time": 0.1333, + "value": 8.6, + "curve": [ 0.166, 8.4, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "front-thigh": { + "translate": [ + { + "x": 12.21, + "y": 1.89, + "curve": [ 0.033, 12.21, 0.1, 0, 0.033, 1.89, 0.1, 0 ] + }, + { "time": 0.1333 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -16.11, + "y": -1.38, + "curve": [ 0.033, -16.11, 0.1, 0, 0.033, -1.38, 0.1, 0 ] + }, + { "time": 0.1333 } + ] + }, + "torso3": { + "rotate": [ + { "time": 0.2667, "value": -2.15 } + ] + }, + "head-control": { + "translate": [ + { + "x": -13.72, + "y": -34.7, + "curve": [ 0.067, -13.72, 0.2, 0, 0.067, -34.7, 0.2, 0 ] + }, + { "time": 0.2667 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.13, + "y": -14.31, + "curve": [ 0.067, 1.13, 0.2, 0, 0.067, -14.31, 0.2, 0 ] + }, + { "time": 0.2667 } + ] + } + } + }, + "jump": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" }, + { "time": 0.1, "name": "front-fist-closed" }, + { "time": 0.8333, "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { + "value": 55.08, + "curve": [ 0.007, 46.66, 0.043, 26.3 ] + }, + { + "time": 0.0667, + "value": 22.84, + "curve": [ 0.1, 17.99, 0.165, 15.78 ] + }, + { + "time": 0.2333, + "value": 15.71, + "curve": [ 0.309, 15.63, 0.408, 46.67 ] + }, + { + "time": 0.5, + "value": 63.6, + "curve": [ 0.56, 74.72, 0.762, 91.48 ] + }, + { + "time": 0.9667, + "value": 91.81, + "curve": [ 1.068, 92.01, 1.096, 22.05 ] + }, + { + "time": 1.1667, + "value": 22.25, + "curve": [ 1.18, 22.29, 1.176, 56.17 ] + }, + { + "time": 1.2, + "value": 56.16, + "curve": [ 1.246, 56.15, 1.263, 54.94 ] + }, + { "time": 1.3333, "value": 55.08 } + ], + "translate": [ + { "x": -5.13, "y": 11.55 } + ] + }, + "torso": { + "rotate": [ + { + "value": -45.57, + "curve": [ 0.022, -44.61, 0.03, -39.06 ] + }, + { + "time": 0.0667, + "value": -35.29, + "curve": [ 0.12, -29.77, 0.28, -19.95 ] + }, + { + "time": 0.4333, + "value": -19.95, + "curve": [ 0.673, -19.95, 0.871, -22.38 ] + }, + { + "time": 0.9667, + "value": -27.08, + "curve": [ 1.094, -33.33, 1.176, -44.93 ] + }, + { "time": 1.3333, "value": -45.57 } + ], + "translate": [ + { "x": -3.79, "y": -0.77 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 12.81, + "curve": [ 0.067, 12.81, 0.242, 67.88 ] + }, + { + "time": 0.2667, + "value": 74.11, + "curve": [ 0.314, 86.02, 0.454, 92.23 ] + }, + { + "time": 0.5667, + "value": 92.24, + "curve": [ 0.753, 92.26, 0.966, 67.94 ] + }, + { + "time": 1, + "value": 61.32, + "curve": [ 1.039, 53.75, 1.218, 12.68 ] + }, + { "time": 1.3333, "value": 12.81 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -115.64, + "curve": [ 0.067, -117.17, 0.125, -117.15 ] + }, + { + "time": 0.1667, + "value": -117.15, + "curve": [ 0.225, -117.15, 0.332, -108.76 ] + }, + { + "time": 0.4, + "value": -107.15, + "curve": [ 0.48, -105.26, 0.685, -103.49 ] + }, + { + "time": 0.7667, + "value": -101.97, + "curve": [ 0.826, -100.87, 0.919, -92.3 ] + }, + { + "time": 1, + "value": -92.28, + "curve": [ 1.113, -92.26, 1.297, -114.22 ] + }, + { "time": 1.3333, "value": -115.64 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -40.21, + "curve": [ 0.054, -35.46, 0.15, -31.12 ] + }, + { + "time": 0.2, + "value": -31.12, + "curve": [ 0.308, -31.12, 0.547, -80.12 ] + }, + { + "time": 0.6333, + "value": -96.56, + "curve": [ 0.697, -108.56, 0.797, -112.54 ] + }, + { + "time": 0.8667, + "value": -112.6, + "curve": [ 1.137, -112.84, 1.274, -49.19 ] + }, + { "time": 1.3333, "value": -40.21 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 20.54, + "curve": [ 0.054, 32.23, 0.192, 55.84 ] + }, + { + "time": 0.2333, + "value": 62.58, + "curve": [ 0.29, 71.87, 0.375, 79.28 ] + }, + { + "time": 0.4333, + "value": 79.18, + "curve": [ 0.555, 78.98, 0.684, 27.54 ] + }, + { + "time": 0.7333, + "value": 13.28, + "curve": [ 0.786, -1.85, 0.874, -24.76 ] + }, + { + "time": 1, + "value": -25.45, + "curve": [ 1.165, -26.36, 1.303, 9.1 ] + }, + { "time": 1.3333, "value": 20.54 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16, + "curve": [ 0.114, -39.59, 0.3, -45.61 ] + }, + { + "time": 0.4, + "value": -45.61, + "curve": [ 0.442, -45.61, 0.537, -21.54 ] + }, + { + "time": 0.5667, + "value": -15.4, + "curve": [ 0.592, -10.23, 0.692, 11.89 ] + }, + { + "time": 0.7333, + "value": 11.73, + "curve": [ 0.783, 11.54, 0.831, 1.8 ] + }, + { + "time": 0.8667, + "value": -5.78, + "curve": [ 0.897, -12.22, 0.901, -14.22 ] + }, + { + "time": 0.9333, + "value": -14.51, + "curve": [ 0.974, -14.89, 0.976, 10.38 ] + }, + { + "time": 1, + "value": 10.55, + "curve": [ 1.027, 10.74, 1.023, -8.44 ] + }, + { + "time": 1.0333, + "value": -8.42, + "curve": [ 1.059, -8.36, 1.074, 10.12 ] + }, + { + "time": 1.1, + "value": 10.22, + "curve": [ 1.168, 10.48, 1.27, -36.07 ] + }, + { "time": 1.3333, "value": -36.16 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.5, + "curve": [ 0.048, 36.1, 0.168, 20.45 ] + }, + { + "time": 0.3, + "value": 20.45, + "curve": [ 0.476, 20.45, 0.571, 33.76 ] + }, + { + "time": 0.6, + "value": 38.67, + "curve": [ 0.642, 45.8, 0.681, 57.44 ] + }, + { + "time": 0.7333, + "value": 62.91, + "curve": [ 0.829, 72.8, 0.996, 77.61 ] + }, + { + "time": 1.0333, + "value": 80.37, + "curve": [ 1.082, 83.94, 1.148, 90.6 ] + }, + { + "time": 1.2, + "value": 90.6, + "curve": [ 1.248, 90.46, 1.317, 53.07 ] + }, + { "time": 1.3333, "value": 49.06 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.022, 25.12, 0.187, -0.89 ] + }, + { + "time": 0.2, + "value": -2.52, + "curve": [ 0.257, -9.92, 0.372, -17.38 ] + }, + { + "time": 0.4333, + "value": -17.41, + "curve": [ 0.54, -17.47, 0.659, -16.91 ] + }, + { + "time": 0.7667, + "value": -12.1, + "curve": [ 0.907, -5.79, 1.025, 14.58 ] + }, + { + "time": 1.1, + "value": 20.58, + "curve": [ 1.191, 27.85, 1.283, 29.67 ] + }, + { "time": 1.3333, "value": 29.67 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.88, + "curve": [ 0.104, 11.82, 0.179, 11.15 ] + }, + { + "time": 0.2, + "value": 10.08, + "curve": [ 0.255, 7.29, 0.405, -8.15 ] + }, + { + "time": 0.4333, + "value": -9.35, + "curve": [ 0.508, -12.48, 0.595, -13.14 ] + }, + { + "time": 0.6667, + "value": -12.61, + "curve": [ 0.714, -12.26, 0.815, -5.57 ] + }, + { + "time": 0.8333, + "value": -4.08, + "curve": [ 0.883, -0.07, 1.045, 12.77 ] + }, + { + "time": 1.1, + "value": 15.06, + "curve": [ 1.208, 19.6, 1.279, 20.64 ] + }, + { "time": 1.3333, "value": 20.73 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.14, + "curve": [ 0.008, 12.19, 0.197, -23.53 ] + }, + { + "time": 0.3333, + "value": -23.95, + "curve": [ 0.509, -23.95, 0.667, -2.66 ] + }, + { + "time": 0.7333, + "value": -2.66, + "curve": [ 0.792, -2.66, 0.908, -13.32 ] + }, + { + "time": 0.9667, + "value": -13.32, + "curve": [ 1.158, -13.11, 1.241, -1.58 ] + }, + { "time": 1.3333, "value": -1.58 } + ], + "scale": [ + { + "curve": [ 0.041, 1, 0.052, 0.962, 0.041, 1, 0.052, 1.137 ] + }, + { + "time": 0.1, + "x": 0.954, + "y": 1.137, + "curve": [ 0.202, 0.962, 0.318, 1, 0.202, 1.137, 0.252, 1.002 ] + }, + { "time": 0.4667 }, + { + "time": 1.0667, + "x": 1.002, + "curve": [ 1.092, 1.002, 1.126, 1.143, 1.092, 1, 1.128, 0.975 ] + }, + { + "time": 1.1667, + "x": 1.144, + "y": 0.973, + "curve": [ 1.204, 1.145, 1.233, 0.959, 1.206, 0.972, 1.227, 1.062 ] + }, + { + "time": 1.2667, + "x": 0.958, + "y": 1.063, + "curve": [ 1.284, 0.958, 1.292, 1.001, 1.288, 1.063, 1.288, 1.001 ] + }, + { "time": 1.3333 } + ] + }, + "hip": { + "translate": [ + { + "y": -45.46, + "curve": [ 0.042, -0.09, 0.15, 15.22, 0.031, 44.98, 0.123, 289.73 ] + }, + { + "time": 0.2, + "x": 15.22, + "y": 415.85, + "curve": [ 0.332, 15.22, 0.539, -34.52, 0.271, 532.93, 0.483, 720.5 ] + }, + { + "time": 0.7667, + "x": -34.52, + "y": 721.6, + "curve": [ 0.888, -34.52, 1.057, -21.95, 1.049, 721.17, 1.098, 379.84 ] + }, + { + "time": 1.1333, + "x": -15.67, + "y": 266.77, + "curve": [ 1.144, -14.77, 1.188, -10.53, 1.15, 213.72, 1.172, -61.32 ] + }, + { + "time": 1.2333, + "x": -6.53, + "y": -61.34, + "curve": [ 1.272, -3.22, 1.311, 0.05, 1.291, -61.36, 1.296, -44.8 ] + }, + { "time": 1.3333, "y": -45.46 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -74.19, + "curve": [ 0, -51.14, 0.042, -12.54 ] + }, + { + "time": 0.1667, + "value": -12.28, + "curve": [ 0.285, -12.32, 0.37, -74.44 ] + }, + { + "time": 0.4333, + "value": -92.92, + "curve": [ 0.498, -111.86, 0.617, -140.28 ] + }, + { + "time": 0.9, + "value": -140.84, + "curve": [ 1.004, -141.04, 1.09, -47.87 ] + }, + { + "time": 1.1, + "value": -37.44, + "curve": [ 1.108, -29.83, 1.14, -21.18 ] + }, + { + "time": 1.1667, + "value": -21.08, + "curve": [ 1.18, -21.03, 1.191, -50.65 ] + }, + { + "time": 1.2, + "value": -53.17, + "curve": [ 1.22, -58.53, 1.271, -73.38 ] + }, + { "time": 1.3333, "value": -74.19 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 7.35, + "curve": [ 0, 4.8, 0.05, -26.64 ] + }, + { + "time": 0.0667, + "value": -26.64, + "curve": [ 0.192, -26.64, 0.442, -11.77 ] + }, + { + "time": 0.5667, + "value": -11.77, + "curve": [ 0.692, -11.77, 0.942, -19.36 ] + }, + { + "time": 1.0667, + "value": -19.36, + "curve": [ 1.133, -19.36, 1.32, 3.82 ] + }, + { "time": 1.3333, "value": 7.35 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": -7.14 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.36, + "curve": [ 0.022, 16.28, 0.15, 30.81 ] + }, + { + "time": 0.2, + "value": 30.81, + "curve": [ 0.258, 30.81, 0.375, 13.26 ] + }, + { + "time": 0.4333, + "value": 13.26, + "curve": [ 0.508, 13.26, 0.658, 15.05 ] + }, + { + "time": 0.7333, + "value": 14.98, + "curve": [ 0.789, 14.94, 0.828, 13.62 ] + }, + { + "time": 0.8667, + "value": 12.72, + "curve": [ 0.887, 12.25, 0.984, 9.83 ] + }, + { + "time": 1.0333, + "value": 8.6, + "curve": [ 1.045, 8.31, 1.083, 7.55 ] + }, + { + "time": 1.1333, + "value": 7.13, + "curve": [ 1.175, 6.78, 1.283, 6.18 ] + }, + { "time": 1.3333, "value": 6.18 } + ] + }, + "front-leg-target": { + "translate": [ + { "x": -13.95, "y": -30.34 } + ] + }, + "rear-leg-target": { + "rotate": [ + { "value": -38.43 } + ], + "translate": [ + { "x": 85, "y": -33.59 } + ] + }, + "front-foot-target": { + "rotate": [ + { "value": -62.54 } + ], + "translate": [ + { "x": 16.34, "y": 0.18 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": 18.55 } + ], + "translate": [ + { "x": -176.39, "y": 134.12 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "value": -143.73, + "curve": [ 0.083, -144.24, 0.167, -74.26 ] + }, + { + "time": 0.2667, + "value": -52.76, + "curve": [ 0.342, -36.57, 0.513, -36.57 ] + }, + { + "time": 0.6333, + "value": -30.97, + "curve": [ 0.724, -26.78, 0.848, -17.06 ] + }, + { + "time": 0.9667, + "value": -16.74, + "curve": [ 1.167, -16.2, 1.272, -144.17 ] + }, + { "time": 1.3333, "value": -143.73 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -1.57, + "curve": [ 0, -24.71, 0.162, -60.88 ] + }, + { + "time": 0.2667, + "value": -60.83, + "curve": [ 0.342, -60.8, 0.582, -43.5 ] + }, + { + "time": 0.7, + "value": -39.45, + "curve": [ 0.773, -36.94, 0.832, -36.78 ] + }, + { + "time": 0.9667, + "value": -36.6, + "curve": [ 1.054, -36.49, 1.092, -37.37 ] + }, + { + "time": 1.1667, + "value": -33.26, + "curve": [ 1.237, -29.37, 1.147, -1.41 ] + }, + { "time": 1.2, "value": -1.57 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0, 13.59, 0.117, 18.21 ] + }, + { + "time": 0.1333, + "value": 18.21, + "curve": [ 0.167, 18.21, 0.26, 12.95 ] + }, + { + "time": 0.3, + "value": 11.56, + "curve": [ 0.382, 8.7, 0.55, 9.43 ] + }, + { + "time": 0.6667, + "value": 9.32, + "curve": [ 0.843, 9.15, 0.918, -7.34 ] + }, + { "time": 1.3333, "value": -6.81 } + ], + "translate": [ + { + "time": 0.6667, + "curve": [ 0.781, 0, 0.972, 16.03, 0.781, 0, 0.972, 0.92 ] + }, + { + "time": 1.1333, + "x": 16.03, + "y": 0.92, + "curve": [ 1.211, 16.03, 1.281, 0, 1.211, 0.92, 1.281, 0 ] + }, + { "time": 1.3333 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.001, -3.88, 0.063, 16.18 ] + }, + { + "time": 0.1667, + "value": 16.14, + "curve": [ 0.242, 16.1, 0.249, 16.07 ] + }, + { + "time": 0.3333, + "value": 13.46, + "curve": [ 0.442, 10.09, 0.573, -2.2 ] + }, + { + "time": 0.6, + "value": -6.04, + "curve": [ 0.614, -8.05, 0.717, -33.44 ] + }, + { + "time": 0.7667, + "value": -33.44, + "curve": [ 0.809, -33.44, 0.835, -31.32 ] + }, + { + "time": 0.8667, + "value": -27.36, + "curve": [ 0.874, -26.47, 0.903, -14.28 ] + }, + { + "time": 0.9333, + "value": -14.47, + "curve": [ 0.956, -14.62, 0.944, -25.91 ] + }, + { + "time": 1, + "value": -25.96, + "curve": [ 1.062, -26.02, 1.051, -1.87 ] + }, + { + "time": 1.0667, + "value": -1.87, + "curve": [ 1.096, -1.87, 1.096, -16.09 ] + }, + { + "time": 1.1333, + "value": -16.08, + "curve": [ 1.169, -16.08, 1.153, -3.38 ] + }, + { + "time": 1.2, + "value": -3.38, + "curve": [ 1.234, -3.38, 1.271, -6.07 ] + }, + { "time": 1.3333, "value": -6.07 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0, -3.17, 0.042, 16.33 ] + }, + { + "time": 0.0667, + "value": 16.33, + "curve": [ 0.21, 15.74, 0.208, -12.06 ] + }, + { + "time": 0.3333, + "value": -12.21, + "curve": [ 0.417, -12.3, 0.552, -3.98 ] + }, + { + "time": 0.6667, + "value": 1.52, + "curve": [ 0.726, 4.35, 0.817, 4.99 ] + }, + { + "time": 0.8667, + "value": 4.99, + "curve": [ 0.901, 4.99, 0.912, -29.05 ] + }, + { + "time": 0.9667, + "value": -27.45, + "curve": [ 0.987, -26.83, 1.018, -5.42 ] + }, + { + "time": 1.0667, + "value": -5.46, + "curve": [ 1.107, -5.22, 1.095, -33.51 ] + }, + { + "time": 1.1333, + "value": -33.28, + "curve": [ 1.162, -33.57, 1.192, 8.04 ] + }, + { + "time": 1.2667, + "value": 7.86, + "curve": [ 1.302, 7.77, 1.313, 2.7 ] + }, + { "time": 1.3333, "value": 2.7 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.001, -3.12, 0.074, 14.66 ] + }, + { + "time": 0.1333, + "value": 14.66, + "curve": [ 0.188, 14.8, 0.293, 9.56 ] + }, + { + "time": 0.3333, + "value": 5.99, + "curve": [ 0.381, 1.72, 0.55, -11.11 ] + }, + { + "time": 0.6667, + "value": -11.11, + "curve": [ 0.833, -11.11, 0.933, 22.54 ] + }, + { + "time": 1.1, + "value": 22.54, + "curve": [ 1.158, 22.54, 1.275, -6.81 ] + }, + { "time": 1.3333, "value": -6.81 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 4.52, + "curve": [ 0.013, 2.33, 0.092, -9.75 ] + }, + { + "time": 0.1333, + "value": -9.75, + "curve": [ 0.175, -9.75, 0.291, -1.26 ] + }, + { + "time": 0.3333, + "value": 0.96, + "curve": [ 0.359, 2.3, 0.543, 4.25 ] + }, + { + "time": 0.6, + "value": 4.68, + "curve": [ 0.683, 5.3, 0.771, 5.92 ] + }, + { + "time": 0.8333, + "value": 6.48, + "curve": [ 0.871, 6.82, 1.083, 11.37 ] + }, + { + "time": 1.1667, + "value": 11.37, + "curve": [ 1.208, 11.37, 1.317, 6.18 ] + }, + { "time": 1.3333, "value": 4.52 } + ], + "translate": [ + { + "curve": [ 0, 0, 0.082, -2.24, 0, 0, 0.082, -0.42 ] + }, + { + "time": 0.1667, + "x": -2.98, + "y": -0.56, + "curve": [ 0.232, -2.24, 0.298, 0, 0.232, -0.42, 0.298, 0 ] + }, + { "time": 0.3333, "curve": "stepped" }, + { + "time": 0.8667, + "curve": [ 0.889, 0, 0.912, 0.26, 0.889, 0, 0.912, 0.06 ] + }, + { + "time": 0.9333, + "x": 0.68, + "y": 0.23, + "curve": [ 1.016, 2.22, 1.095, 5.9, 1.023, 0.97, 1.095, 1.99 ] + }, + { + "time": 1.1667, + "x": 6.47, + "y": 2.18, + "curve": [ 1.23, 5.75, 1.286, 0, 1.23, 1.94, 1.286, 0 ] + }, + { "time": 1.3333 } + ] + }, + "torso3": { + "rotate": [ + { + "value": 4.52, + "curve": [ 0.025, 4.52, 0.075, -6.17 ] + }, + { + "time": 0.1, + "value": -6.17, + "curve": [ 0.175, -6.17, 0.381, -0.71 ] + }, + { + "time": 0.4, + "value": -0.25, + "curve": [ 0.447, 0.87, 0.775, 4.84 ] + }, + { + "time": 0.9, + "value": 4.84, + "curve": [ 1.008, 4.84, 1.225, 4.52 ] + }, + { "time": 1.3333, "value": 4.52 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.138, -2.4, 0.227, -10.44, 0.123, 1.05, 0.227, 2.7 ] + }, + { + "time": 0.3667, + "x": -10.44, + "y": 2.7, + "curve": [ 0.484, -10.44, 0.585, -5.63, 0.484, 2.7, 0.629, -23.62 ] + }, + { + "time": 0.7333, + "x": -2.29, + "y": -26.61, + "curve": [ 0.818, -0.39, 0.962, 1.21, 0.858, -30.17, 0.972, -28.75 ] + }, + { + "time": 1.1, + "x": 1.25, + "y": -28.75, + "curve": [ 1.192, 1.28, 1.234, 0.98, 1.224, -28.75, 1.235, -2.15 ] + }, + { "time": 1.3333 } + ] + }, + "front-shoulder": { + "translate": [ + { + "curve": [ 0.031, -2.22, 0.065, -3.73, 0.02, -3.25, 0.065, -14.74 ] + }, + { + "time": 0.1, + "x": -3.73, + "y": -14.74, + "curve": [ 0.216, -3.73, 0.384, -0.17, 0.216, -14.74, 0.402, -12.51 ] + }, + { + "time": 0.5, + "x": 1.63, + "y": -9.51, + "curve": [ 0.632, 3.69, 0.935, 7.41, 0.585, -6.91, 0.909, 10.86 ] + }, + { + "time": 1.1, + "x": 7.45, + "y": 10.99, + "curve": [ 1.18, 7.46, 1.265, 2.86, 1.193, 11.05, 1.294, 3.38 ] + }, + { "time": 1.3333 } + ] + } + }, + "ik": { + "front-foot-ik": [ + { + "mix": 0, + "curve": [ 0.3, 0, 0.9, 1, 0.3, 0, 0.9, 0 ] + }, + { "time": 1.2 } + ], + "front-leg-ik": [ + { + "mix": 0, + "bendPositive": false, + "curve": [ 0.3, 0, 0.9, 1, 0.3, 0, 0.9, 0 ] + }, + { "time": 1.2, "bendPositive": false } + ], + "rear-foot-ik": [ + { "mix": 0 } + ], + "rear-leg-ik": [ + { "mix": 0, "bendPositive": false } + ] + }, + "events": [ + { "time": 1.2, "name": "footstep" } + ] + }, + "portal": { + "slots": { + "clipping": { + "attachment": [ + { "name": "clipping" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "time": 0.9, "name": "mouth-grind" }, + { "time": 2.2667, "name": "mouth-smile" } + ] + }, + "portal-bg": { + "attachment": [ + { "name": "portal-bg" }, + { "time": 3 } + ] + }, + "portal-flare1": { + "attachment": [ + { "time": 1.1, "name": "portal-flare1" }, + { "time": 1.1333, "name": "portal-flare2" }, + { "time": 1.1667, "name": "portal-flare3" }, + { "time": 1.2, "name": "portal-flare1" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3333 } + ] + }, + "portal-flare2": { + "attachment": [ + { "time": 1.1, "name": "portal-flare2" }, + { "time": 1.1333, "name": "portal-flare3" }, + { "time": 1.1667, "name": "portal-flare1" }, + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667 } + ] + }, + "portal-flare3": { + "attachment": [ + { "time": 1.2, "name": "portal-flare3" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667 } + ] + }, + "portal-flare4": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare1" }, + { "time": 1.2667, "name": "portal-flare2" }, + { "time": 1.3333 } + ] + }, + "portal-flare5": { + "attachment": [ + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3333 } + ] + }, + "portal-flare6": { + "attachment": [ + { "time": 1.2667, "name": "portal-flare3" }, + { "time": 1.3333 } + ] + }, + "portal-flare7": { + "attachment": [ + { "time": 1.1333, "name": "portal-flare2" }, + { "time": 1.1667 } + ] + }, + "portal-flare8": { + "attachment": [ + { "time": 1.2, "name": "portal-flare3" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667 } + ] + }, + "portal-flare9": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3 } + ] + }, + "portal-flare10": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare1" }, + { "time": 1.2667, "name": "portal-flare3" }, + { "time": 1.3 } + ] + }, + "portal-shade": { + "attachment": [ + { "name": "portal-shade" }, + { "time": 3 } + ] + }, + "portal-streaks1": { + "attachment": [ + { "name": "portal-streaks1" }, + { "time": 3 } + ] + }, + "portal-streaks2": { + "attachment": [ + { "name": "portal-streaks2" }, + { "time": 3 } + ] + } + }, + "bones": { + "portal-root": { + "translate": [ + { + "x": -458.35, + "y": 105.19, + "curve": [ 0.333, -458.22, 0.669, -457.86, 0.934, 105.19, 0.671, 105.19 ] + }, + { + "time": 1, + "x": -456.02, + "y": 105.19, + "curve": [ 1.339, -454.14, 2.208, -447.28, 1.35, 105.19, 2.05, 105.19 ] + }, + { + "time": 2.4, + "x": -439.12, + "y": 105.19, + "curve": [ 2.463, -436.44, 2.502, -432.92, 2.487, 105.19, 2.512, 105.09 ] + }, + { + "time": 2.6, + "x": -432.58, + "y": 105.09, + "curve": [ 2.784, -431.94, 2.978, -446.6, 2.772, 105.09, 2.933, 105.19 ] + }, + { "time": 3.0333, "x": -457.42, "y": 105.19 } + ], + "scale": [ + { + "x": 0.003, + "y": 0.006, + "curve": [ 0.329, 0.044, 0.347, 0.117, 0.329, 0.097, 0.37, 0.249 ] + }, + { + "time": 0.4, + "x": 0.175, + "y": 0.387, + "curve": [ 0.63, 0.619, 0.663, 0.723, 0.609, 1.338, 0.645, 1.524 ] + }, + { + "time": 0.7333, + "x": 0.724, + "y": 1.52, + "curve": [ 0.798, 0.725, 0.907, 0.647, 0.797, 1.517, 0.895, 1.424 ] + }, + { + "time": 1, + "x": 0.645, + "y": 1.426, + "curve": [ 1.095, 0.643, 1.139, 0.688, 1.089, 1.428, 1.115, 1.513 ] + }, + { + "time": 1.2333, + "x": 0.685, + "y": 1.516, + "curve": [ 1.325, 0.683, 1.508, 0.636, 1.343, 1.518, 1.467, 1.4 ] + }, + { + "time": 1.6, + "x": 0.634, + "y": 1.401, + "curve": [ 1.728, 0.631, 1.946, 0.687, 1.722, 1.402, 1.924, 1.522 ] + }, + { + "time": 2.0667, + "x": 0.688, + "y": 1.522, + "curve": [ 2.189, 0.69, 2.289, 0.649, 2.142, 1.522, 2.265, 1.417 ] + }, + { + "time": 2.4, + "x": 0.65, + "y": 1.426, + "curve": [ 2.494, 0.651, 2.504, 0.766, 2.508, 1.434, 2.543, 1.566 ] + }, + { + "time": 2.6, + "x": 0.766, + "y": 1.568, + "curve": [ 2.73, 0.765, 3.006, 0.098, 2.767, 1.564, 2.997, 0.1 ] + }, + { "time": 3.0333, "x": 0.007, "y": 0.015 } + ] + }, + "portal-streaks1": { + "rotate": [ + {}, + { "time": 3.1667, "value": 1200 } + ], + "translate": [ + { + "x": 15.15, + "curve": [ 0.162, 15.15, 0.432, 12.6, 0.162, 0, 0.432, -3.86 ] + }, + { + "time": 0.6667, + "x": 10.9, + "y": -6.44, + "curve": [ 0.794, 9.93, 0.912, 9.21, 0.794, -7.71, 0.912, -8.66 ] + }, + { + "time": 1, + "x": 9.21, + "y": -8.66, + "curve": [ 1.083, 9.21, 1.25, 21.53, 1.083, -8.66, 1.265, -4.9 ] + }, + { + "time": 1.3333, + "x": 21.53, + "y": -3.19, + "curve": [ 1.5, 21.53, 1.939, 12.3, 1.446, -0.37, 1.9, 6.26 ] + }, + { + "time": 2.0667, + "x": 11.26, + "y": 6.26, + "curve": [ 2.239, 9.85, 2.389, 9.68, 2.208, 6.26, 2.523, 0.51 ] + }, + { + "time": 2.5667, + "x": 9.39, + "y": -0.8, + "curve": [ 2.657, 9.24, 2.842, 9.21, 2.646, -3.2, 2.842, -8.91 ] + }, + { "time": 2.9333, "x": 9.21, "y": -8.91 } + ], + "scale": [ + { + "curve": [ 0.167, 1, 0.5, 1.053, 0.167, 1, 0.5, 1.053 ] + }, + { + "time": 0.6667, + "x": 1.053, + "y": 1.053, + "curve": [ 0.833, 1.053, 1.167, 0.986, 0.833, 1.053, 1.167, 0.986 ] + }, + { + "time": 1.3333, + "x": 0.986, + "y": 0.986, + "curve": [ 1.5, 0.986, 1.833, 1.053, 1.5, 0.986, 1.833, 1.053 ] + }, + { "time": 2, "x": 1.053, "y": 1.053 } + ] + }, + "portal-streaks2": { + "rotate": [ + {}, + { "time": 3.1667, "value": 600 } + ], + "translate": [ + { "x": -2.11 }, + { "time": 1, "x": -2.11, "y": 6.63 }, + { "time": 1.9333, "x": -2.11 } + ], + "scale": [ + { + "x": 1.014, + "y": 1.014, + "curve": [ 0.229, 0.909, 0.501, 0.755, 0.242, 0.892, 0.502, 0.768 ] + }, + { + "time": 0.8667, + "x": 0.745, + "y": 0.745, + "curve": [ 1.282, 0.733, 2.021, 0.699, 1.27, 0.719, 2.071, 0.709 ] + }, + { + "time": 2.2, + "x": 0.7, + "y": 0.704, + "curve": [ 2.315, 0.7, 2.421, 0.794, 2.311, 0.701, 2.485, 0.797 ] + }, + { + "time": 2.5667, + "x": 0.794, + "y": 0.794, + "curve": [ 2.734, 0.794, 2.99, 0.323, 2.714, 0.789, 3.019, 0.341 ] + }, + { "time": 3.1667, "x": 0, "y": 0 } + ] + }, + "portal-shade": { + "translate": [ + { "x": -29.68 } + ], + "scale": [ + { "x": 0.714, "y": 0.714 } + ] + }, + "portal": { + "rotate": [ + {}, + { "time": 3.1667, "value": 600 } + ] + }, + "clipping": { + "translate": [ + { "x": -476.55, "y": 2.27 } + ], + "scale": [ + { "x": 0.983, "y": 1.197 } + ] + }, + "hip": { + "rotate": [ + { + "time": 1.0667, + "value": 22.74, + "curve": [ 1.163, 18.84, 1.77, 8.77 ] + }, + { + "time": 1.9, + "value": 7.82, + "curve": [ 2.271, 5.1, 2.89, 0 ] + }, + { "time": 3.1667 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { + "time": 1.0667, + "x": -694.16, + "y": 183.28, + "curve": [ 1.091, -602.08, 1.138, -427.59, 1.115, 185.6, 1.171, 133.18 ] + }, + { + "time": 1.2333, + "x": -316.97, + "y": 55.29, + "curve": [ 1.317, -220.27, 1.512, -123.21, 1.271, 8.68, 1.461, -83.18 ] + }, + { + "time": 1.6, + "x": -95.53, + "y": -112.23, + "curve": [ 1.718, -58.25, 2.037, -22.54, 1.858, -166.17, 2.109, -31.4 ] + }, + { + "time": 2.1667, + "x": -14.82, + "y": -31.12, + "curve": [ 2.294, -7.28, 2.442, -7.2, 2.274, -30.6, 2.393, -36.76 ] + }, + { + "time": 2.6, + "x": -7.2, + "y": -36.96, + "curve": [ 2.854, -7.2, 3.071, -11.87, 2.786, -36.27, 3.082, -22.98 ] + }, + { "time": 3.1667, "x": -11.97, "y": -23.15 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "time": 1.0667, "value": 41.6, "curve": "stepped" }, + { + "time": 1.2333, + "value": 41.6, + "curve": [ 1.258, 41.6, 1.379, 35.46 ] + }, + { + "time": 1.4, + "value": 30.09, + "curve": [ 1.412, 27.04, 1.433, 10.65 ] + }, + { "time": 1.4333, "value": -0.28 }, + { "time": 1.6, "value": 2.44 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { + "time": 1.0667, + "x": -591.13, + "y": 438.46, + "curve": [ 1.076, -539.77, 1.206, -268.1, 1.117, 418.44, 1.21, 333.18 ] + }, + { + "time": 1.2333, + "x": -225.28, + "y": 304.53, + "curve": [ 1.265, -175.22, 1.393, -74.21, 1.296, 226.52, 1.401, 49.61 ] + }, + { + "time": 1.4333, + "x": -52.32, + "y": 0.2, + "curve": [ 1.454, -40.85, 1.616, 40.87, 1.466, 0.17, 1.614, 0.04 ] + }, + { "time": 1.6667, "x": 45.87, "y": 0.01 }, + { "time": 1.9333, "x": 48.87 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "time": 1.0667, + "value": 32.08, + "curve": [ 1.108, 32.08, 1.192, 35.16 ] + }, + { + "time": 1.2333, + "value": 35.16, + "curve": [ 1.258, 35.16, 1.317, 2.23 ] + }, + { + "time": 1.3333, + "value": -4.74, + "curve": [ 1.351, -12.14, 1.429, -34.96 ] + }, + { + "time": 1.6, + "value": -34.77, + "curve": [ 1.765, -34.58, 1.897, -17.25 ] + }, + { "time": 1.9333 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { + "time": 1.0667, + "x": -533.93, + "y": 363.75, + "curve": [ 1.074, -480.85, 1.18, -261.31, 1.094, 362.3, 1.195, 267.77 ] + }, + { + "time": 1.2333, + "x": -201.23, + "y": 199.93, + "curve": [ 1.269, -161.38, 1.294, -140.32, 1.274, 126.67, 1.308, 77.12 ] + }, + { + "time": 1.3333, + "x": -124.08, + "y": 0.2, + "curve": [ 1.426, -85.6, 1.633, -69.06, 1.45, 0.48, 1.633, 0 ] + }, + { "time": 1.7333, "x": -69.06 } + ] + }, + "torso": { + "rotate": [ + { + "time": 1.0667, + "value": 27.02, + "curve": [ 1.187, 26.86, 1.291, 7.81 ] + }, + { + "time": 1.3333, + "value": -2.62, + "curve": [ 1.402, -19.72, 1.429, -48.64 ] + }, + { + "time": 1.4667, + "value": -56.31, + "curve": [ 1.509, -64.87, 1.62, -77.14 ] + }, + { + "time": 1.7333, + "value": -77.34, + "curve": [ 1.837, -76.89, 1.895, -71.32 ] + }, + { + "time": 2, + "value": -57.52, + "curve": [ 2.104, -43.83, 2.189, -28.59 ] + }, + { + "time": 2.3, + "value": -29.03, + "curve": [ 2.413, -29.48, 2.513, -36.79 ] + }, + { + "time": 2.6667, + "value": -36.79, + "curve": [ 2.814, -36.95, 2.947, -22.88 ] + }, + { "time": 3.1667, "value": -22.88 } + ] + }, + "neck": { + "rotate": [ + { + "time": 1.0667, + "value": -3.57, + "curve": [ 1.146, -3.66, 1.15, -13.5 ] + }, + { + "time": 1.2333, + "value": -13.5, + "curve": [ 1.428, -13.5, 1.443, 11.58 ] + }, + { + "time": 1.5667, + "value": 11.42, + "curve": [ 1.658, 11.3, 1.775, 3.78 ] + }, + { + "time": 1.8667, + "value": 3.78, + "curve": [ 1.92, 3.78, 2.036, 8.01 ] + }, + { + "time": 2.1, + "value": 7.93, + "curve": [ 2.266, 7.72, 2.42, 3.86 ] + }, + { + "time": 2.5333, + "value": 3.86, + "curve": [ 2.783, 3.86, 3.004, 3.78 ] + }, + { "time": 3.1667, "value": 3.78 } + ] + }, + "head": { + "rotate": [ + { + "time": 1.0667, + "value": 16.4, + "curve": [ 1.133, 9.9, 1.207, 1.87 ] + }, + { + "time": 1.3333, + "value": 1.67, + "curve": [ 1.46, 1.56, 1.547, 47.54 ] + }, + { + "time": 1.7333, + "value": 47.55, + "curve": [ 1.897, 47.56, 2.042, 5.68 ] + }, + { + "time": 2.0667, + "value": 0.86, + "curve": [ 2.074, -0.61, 2.086, -2.81 ] + }, + { + "time": 2.1, + "value": -5.31, + "curve": [ 2.145, -13.07, 2.216, -23.65 ] + }, + { + "time": 2.2667, + "value": -23.71, + "curve": [ 2.334, -23.79, 2.426, -13.43 ] + }, + { + "time": 2.4667, + "value": -9.18, + "curve": [ 2.498, -5.91, 2.604, 2.53 ] + }, + { + "time": 2.6667, + "value": 2.52, + "curve": [ 2.738, 2.24, 2.85, -8.76 ] + }, + { + "time": 2.9333, + "value": -8.67, + "curve": [ 3.036, -8.55, 3.09, -7.09 ] + }, + { "time": 3.1667, "value": -6.75 } + ], + "scale": [ + { + "time": 1.3333, + "curve": [ 1.392, 1, 1.526, 1, 1.392, 1, 1.508, 1.043 ] + }, + { + "time": 1.5667, + "x": 0.992, + "y": 1.043, + "curve": [ 1.598, 0.985, 1.676, 0.955, 1.584, 1.043, 1.672, 1.04 ] + }, + { + "time": 1.7333, + "x": 0.954, + "y": 1.029, + "curve": [ 1.843, 0.954, 1.933, 1, 1.825, 1.013, 1.933, 1 ] + }, + { "time": 2 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "time": 0.9, + "value": 39.24, + "curve": [ 0.968, 39.93, 1.267, 85.31 ] + }, + { + "time": 1.4667, + "value": 112.27, + "curve": [ 1.555, 124.24, 1.576, 126.44 ] + }, + { + "time": 1.6333, + "value": 126.44, + "curve": [ 1.782, 126.44, 1.992, 94.55 ] + }, + { + "time": 2.1, + "value": 79.96, + "curve": [ 2.216, 64.26, 2.407, 34.36 ] + }, + { + "time": 2.5667, + "value": 33.38, + "curve": [ 2.815, 31.87, 3.1, 39.2 ] + }, + { "time": 3.1667, "value": 39.2 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "time": 1.0667, + "value": 56.07, + "curve": [ 1.138, 59.21, 1.192, 59.65 ] + }, + { + "time": 1.2333, + "value": 59.46, + "curve": [ 1.295, 59.17, 1.45, 22.54 ] + }, + { "time": 1.4667, "value": -0.84 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "time": 1.0667, + "value": 118.03, + "curve": [ 1.075, 93.64, 1.358, -34.03 ] + }, + { + "time": 1.6667, + "value": -33.94, + "curve": [ 1.808, -33.89, 1.879, -25 ] + }, + { + "time": 1.9667, + "value": -25.19, + "curve": [ 2.09, -25.46, 2.312, -34.58 ] + }, + { + "time": 2.3667, + "value": -38.36, + "curve": [ 2.465, -45.18, 2.557, -60.1 ] + }, + { + "time": 2.8333, + "value": -61.1, + "curve": [ 2.843, -61.06, 3.16, -60.87 ] + }, + { "time": 3.1667, "value": -60.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "time": 1.0667, + "value": 0.66, + "curve": [ 1.108, 0.66, 1.221, 44.95 ] + }, + { + "time": 1.2333, + "value": 49.25, + "curve": [ 1.263, 59.42, 1.342, 68.06 ] + }, + { + "time": 1.3667, + "value": 68.34, + "curve": [ 1.409, 68.8, 1.476, 4.9 ] + }, + { + "time": 1.5, + "value": -2.05, + "curve": [ 1.529, -10.3, 1.695, -15.95 ] + }, + { + "time": 1.7333, + "value": -17.38, + "curve": [ 1.807, -20.1, 1.878, -21.19 ] + }, + { + "time": 1.9333, + "value": -21.08, + "curve": [ 2.073, -20.8, 2.146, -7.63 ] + }, + { + "time": 2.1667, + "value": -3.64, + "curve": [ 2.186, 0.12, 2.275, 15.28 ] + }, + { + "time": 2.3333, + "value": 21.78, + "curve": [ 2.392, 28.31, 2.575, 37.66 ] + }, + { + "time": 2.7, + "value": 39.43, + "curve": [ 2.947, 42.93, 3.02, 42.46 ] + }, + { "time": 3.1667, "value": 42.46 } + ] + }, + "front-thigh": { + "translate": [ + { "time": 1.1, "x": -6.41, "y": 18.23, "curve": "stepped" }, + { "time": 1.1333, "x": -6.41, "y": 18.23 }, + { "time": 1.2, "x": 1.61, "y": 3.66 }, + { "time": 1.2333, "x": 4.5, "y": -3.15 }, + { "time": 1.3667, "x": -3.79, "y": 2.94 }, + { "time": 1.4, "x": -8.37, "y": 8.72 }, + { "time": 1.4333, "x": -11.26, "y": 16.99 }, + { "time": 1.4667, "x": -9.89, "y": 24.73, "curve": "stepped" }, + { "time": 1.8667, "x": -9.89, "y": 24.73 }, + { "time": 2.1 } + ] + }, + "front-foot-tip": { + "rotate": [ + { "time": 1.0667, "value": 42.55, "curve": "stepped" }, + { "time": 1.1333, "value": 42.55 }, + { "time": 1.2333, "value": 17.71 }, + { "time": 1.3667, "value": 3.63 }, + { "time": 1.4333 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "time": 1.0667, + "value": 108.71, + "curve": [ 1.082, 108.29, 1.437, 50.73 ] + }, + { + "time": 1.5667, + "value": 24.87, + "curve": [ 1.62, 14.2, 1.66, -11.74 ] + }, + { + "time": 1.7333, + "value": -11.74, + "curve": [ 1.961, -11.73, 2.172, 1.66 ] + }, + { + "time": 2.2667, + "value": 7.88, + "curve": [ 2.331, 12.13, 2.439, 18.65 ] + }, + { + "time": 2.5333, + "value": 18.72, + "curve": [ 2.788, 18.91, 3.145, -0.3 ] + }, + { "time": 3.1667 } + ] + }, + "front-fist": { + "rotate": [ + { + "time": 1.1, + "value": 6.32, + "curve": [ 1.11, 3.31, 1.153, -5.07 ] + }, + { + "time": 1.2333, + "value": -5.13, + "curve": [ 1.311, -5.19, 1.364, 34.65 ] + }, + { + "time": 1.4667, + "value": 34.53, + "curve": [ 1.574, 34.41, 1.547, -55.78 ] + }, + { + "time": 1.8667, + "value": -54.7, + "curve": [ 1.947, -54.7, 2.03, -53.94 ] + }, + { + "time": 2.1333, + "value": -42.44, + "curve": [ 2.215, -33.42, 2.358, -4.43 ] + }, + { + "time": 2.4, + "value": 0.03, + "curve": [ 2.444, 4.66, 2.536, 8.2 ] + }, + { + "time": 2.6333, + "value": 8.2, + "curve": [ 2.733, 8.19, 2.804, -0.67 ] + }, + { + "time": 2.9, + "value": -0.82, + "curve": [ 3.127, -1.16, 3.093, 0 ] + }, + { "time": 3.1667 } + ] + }, + "gun": { + "rotate": [ + { + "time": 1.2667, + "curve": [ 1.35, 0, 1.549, 7.49 ] + }, + { + "time": 1.6, + "value": 9.5, + "curve": [ 1.663, 12.02, 1.846, 19.58 ] + }, + { + "time": 1.9333, + "value": 19.43, + "curve": [ 1.985, 19.4, 2.057, 2.98 ] + }, + { + "time": 2.2, + "value": 2.95, + "curve": [ 2.304, 3.55, 2.458, 10.8 ] + }, + { + "time": 2.5, + "value": 10.8, + "curve": [ 2.642, 10.8, 2.873, -2.54 ] + }, + { + "time": 2.9333, + "value": -2.55, + "curve": [ 3.09, -2.57, 3.08, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair2": { + "rotate": [ + { + "time": 1.0667, + "value": 26.19, + "curve": [ 1.158, 26.19, 1.368, 26 ] + }, + { + "time": 1.4333, + "value": 24.43, + "curve": [ 1.534, 22.03, 2, -29.14 ] + }, + { + "time": 2.2, + "value": -29.14, + "curve": [ 2.292, -29.14, 2.475, 6.71 ] + }, + { + "time": 2.5667, + "value": 6.71, + "curve": [ 2.675, 6.71, 2.814, -5.06 ] + }, + { + "time": 2.9, + "value": -5.06, + "curve": [ 2.973, -5.06, 3.123, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair4": { + "rotate": [ + { + "time": 1.0667, + "value": 5.21, + "curve": [ 1.108, 5.21, 1.192, 26.19 ] + }, + { + "time": 1.2333, + "value": 26.19, + "curve": [ 1.317, 26.19, 1.483, 10.63 ] + }, + { + "time": 1.5667, + "value": 10.63, + "curve": [ 1.627, 10.63, 1.642, 17.91 ] + }, + { + "time": 1.7, + "value": 17.94, + "curve": [ 1.761, 17.97, 1.774, 8.22 ] + }, + { + "time": 1.8, + "value": 3.33, + "curve": [ 1.839, -4.21, 1.95, -22.67 ] + }, + { + "time": 2, + "value": -22.67, + "curve": [ 2.025, -22.67, 2.123, -21.86 ] + }, + { + "time": 2.1667, + "value": -18.71, + "curve": [ 2.228, -14.31, 2.294, -0.3 ] + }, + { + "time": 2.3667, + "value": 6.36, + "curve": [ 2.433, 12.45, 2.494, 19.21 ] + }, + { + "time": 2.6, + "value": 19.21, + "curve": [ 2.729, 19.21, 2.854, 6.75 ] + }, + { + "time": 2.9333, + "value": 4.62, + "curve": [ 3.09, 0.45, 3.062, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair3": { + "rotate": [ + { + "time": 1.4333, + "curve": [ 1.45, 0, 1.452, 11.29 ] + }, + { + "time": 1.5, + "value": 11.21, + "curve": [ 1.596, 11.06, 1.573, -14.17 ] + }, + { + "time": 1.7333, + "value": -20.4, + "curve": [ 1.851, -24.98, 1.943, -28.45 ] + }, + { + "time": 2.2, + "value": -28.75, + "curve": [ 2.317, -28.75, 2.55, 7.04 ] + }, + { + "time": 2.6667, + "value": 7.04, + "curve": [ 2.792, 7.04, 2.885, -5.19 ] + }, + { + "time": 2.9667, + "value": -5.19, + "curve": [ 3.037, -5.19, 3.096, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair1": { + "rotate": [ + { + "time": 1.2333, + "curve": [ 1.283, 0, 1.349, 3.99 ] + }, + { + "time": 1.4333, + "value": 6.58, + "curve": [ 1.497, 8.54, 1.683, 9.35 ] + }, + { + "time": 1.7667, + "value": 9.35, + "curve": [ 1.825, 9.35, 1.945, -8.71 ] + }, + { + "time": 2, + "value": -11.15, + "curve": [ 2.058, -13.71, 2.2, -14.97 ] + }, + { + "time": 2.2667, + "value": -14.97, + "curve": [ 2.367, -14.97, 2.567, 18.77 ] + }, + { + "time": 2.6667, + "value": 18.77, + "curve": [ 2.733, 18.77, 2.817, 8.29 ] + }, + { + "time": 2.8667, + "value": 6.51, + "curve": [ 2.988, 2.17, 3.058, 0 ] + }, + { "time": 3.1667 } + ] + }, + "flare1": { + "rotate": [ + { "time": 1.1, "value": 8.2 } + ], + "translate": [ + { "time": 1.1, "x": -19.97, "y": 149.68 }, + { "time": 1.2, "x": 3.85, "y": 152.43 }, + { "time": 1.2333, "x": -15.42, "y": 152.29 } + ], + "scale": [ + { + "time": 1.1, + "x": 0.805, + "y": 0.805, + "curve": [ 1.119, 0.763, 1.16, 1.162, 1.117, 0.805, 1.15, 0.605 ] + }, + { + "time": 1.1667, + "x": 1.279, + "y": 0.605, + "curve": [ 1.177, 1.47, 1.192, 2.151, 1.175, 0.605, 1.192, 0.911 ] + }, + { + "time": 1.2, + "x": 2.151, + "y": 0.911, + "curve": [ 1.208, 2.151, 1.231, 1.668, 1.208, 0.911, 1.227, 0.844 ] + }, + { + "time": 1.2333, + "x": 1.608, + "y": 0.805, + "curve": [ 1.249, 1.205, 1.283, 0.547, 1.254, 0.685, 1.283, 0.416 ] + }, + { "time": 1.3, "x": 0.547, "y": 0.416 } + ], + "shear": [ + { "time": 1.1, "y": 4.63 }, + { "time": 1.2333, "x": -5.74, "y": 4.63 } + ] + }, + "flare2": { + "rotate": [ + { "time": 1.1, "value": 12.29 } + ], + "translate": [ + { "time": 1.1, "x": -8.63, "y": 132.96 }, + { "time": 1.2, "x": 4.35, "y": 132.93 } + ], + "scale": [ + { "time": 1.1, "x": 0.864, "y": 0.864 }, + { "time": 1.1667, "x": 0.945, "y": 0.945 }, + { "time": 1.2, "x": 1.511, "y": 1.081 } + ], + "shear": [ + { "time": 1.1, "y": 24.03 } + ] + }, + "flare3": { + "rotate": [ + { "time": 1.1667, "value": 2.88 } + ], + "translate": [ + { "time": 1.1667, "x": 3.24, "y": 114.81 } + ], + "scale": [ + { "time": 1.1667, "x": 0.668, "y": 0.668 } + ], + "shear": [ + { "time": 1.1667, "y": 38.59 } + ] + }, + "flare4": { + "rotate": [ + { "time": 1.1667, "value": -8.64 } + ], + "translate": [ + { "time": 1.1667, "x": -3.82, "y": 194.06 }, + { "time": 1.2667, "x": -1.82, "y": 198.47, "curve": "stepped" }, + { "time": 1.3, "x": -1.94, "y": 187.81 } + ], + "scale": [ + { "time": 1.1667, "x": 0.545, "y": 0.545 }, + { "time": 1.2667, "x": 0.757, "y": 0.757 } + ], + "shear": [ + { "time": 1.1667, "x": 7.42, "y": -22.04 } + ] + }, + "flare5": { + "translate": [ + { "time": 1.2, "x": -11.17, "y": 176.42 }, + { "time": 1.2333, "x": -8.56, "y": 179.04, "curve": "stepped" }, + { "time": 1.3, "x": -14.57, "y": 168.69 } + ], + "scale": [ + { "time": 1.2333, "x": 1.146 }, + { "time": 1.3, "x": 0.703, "y": 0.61 } + ], + "shear": [ + { "time": 1.2, "x": 6.9 } + ] + }, + "flare6": { + "rotate": [ + { "time": 1.2333, "value": -5.36 }, + { "time": 1.2667, "value": -0.54 } + ], + "translate": [ + { "time": 1.2333, "x": 14.52, "y": 204.67 }, + { "time": 1.2667, "x": 19.16, "y": 212.9, "curve": "stepped" }, + { "time": 1.3, "x": 9.23, "y": 202.85 } + ], + "scale": [ + { "time": 1.2333, "x": 0.777, "y": 0.49 }, + { "time": 1.2667, "x": 0.777, "y": 0.657 }, + { "time": 1.3, "x": 0.475, "y": 0.401 } + ] + }, + "flare7": { + "rotate": [ + { "time": 1.1, "value": 5.98 }, + { "time": 1.1333, "value": 32.82 } + ], + "translate": [ + { "time": 1.1, "x": -6.34, "y": 112.98 }, + { "time": 1.1333, "x": 2.66, "y": 111.6 } + ], + "scale": [ + { "time": 1.1, "x": 0.588, "y": 0.588 } + ], + "shear": [ + { "time": 1.1333, "x": -19.93 } + ] + }, + "flare8": { + "rotate": [ + { "time": 1.2333, "value": -6.85 } + ], + "translate": [ + { "time": 1.1667, "x": 66.67, "y": 125.52, "curve": "stepped" }, + { "time": 1.2, "x": 58.24, "y": 113.53, "curve": "stepped" }, + { "time": 1.2333, "x": 40.15, "y": 114.69 } + ], + "scale": [ + { "time": 1.1667, "x": 1.313, "y": 1.203 }, + { "time": 1.2333, "x": 1.038, "y": 0.95 } + ], + "shear": [ + { "time": 1.2, "y": -13.01 } + ] + }, + "flare9": { + "rotate": [ + { "time": 1.1667, "value": 2.9 } + ], + "translate": [ + { "time": 1.1667, "x": 28.45, "y": 151.35, "curve": "stepped" }, + { "time": 1.2, "x": 48.8, "y": 191.09, "curve": "stepped" }, + { "time": 1.2333, "x": 52, "y": 182.52, "curve": "stepped" }, + { "time": 1.2667, "x": 77.01, "y": 195.96 } + ], + "scale": [ + { "time": 1.1667, "x": 0.871, "y": 1.073 }, + { "time": 1.2, "x": 0.927, "y": 0.944 }, + { "time": 1.2333, "x": 1.165, "y": 1.336 } + ], + "shear": [ + { "time": 1.1667, "x": 7.95, "y": 25.48 } + ] + }, + "flare10": { + "rotate": [ + { "time": 1.1667, "value": 2.18 } + ], + "translate": [ + { "time": 1.1667, "x": 55.64, "y": 137.64, "curve": "stepped" }, + { "time": 1.2, "x": 90.49, "y": 151.07, "curve": "stepped" }, + { "time": 1.2333, "x": 114.06, "y": 153.05, "curve": "stepped" }, + { "time": 1.2667, "x": 90.44, "y": 164.61 } + ], + "scale": [ + { "time": 1.1667, "x": 2.657, "y": 0.891 }, + { "time": 1.2, "x": 3.314, "y": 1.425 }, + { "time": 1.2333, "x": 2.871, "y": 0.924 }, + { "time": 1.2667, "x": 2.317, "y": 0.775 } + ], + "shear": [ + { "time": 1.1667, "x": -1.35 } + ] + }, + "torso2": { + "rotate": [ + { + "time": 1, + "curve": [ 1.117, 0, 1.255, 24.94 ] + }, + { + "time": 1.4, + "value": 24.94, + "curve": [ 1.477, 24.94, 1.59, -17.62 ] + }, + { + "time": 1.6333, + "value": -19.48, + "curve": [ 1.717, -23.1, 1.784, -26.12 ] + }, + { + "time": 1.9333, + "value": -26.14, + "curve": [ 2.067, -26.15, 2.158, 4.3 ] + }, + { + "time": 2.3, + "value": 4.22, + "curve": [ 2.45, 4.13, 2.579, -1.76 ] + }, + { + "time": 2.7333, + "value": -1.8, + "curve": [ 2.816, -1.82, 2.857, -2.94 ] + }, + { + "time": 2.9333, + "value": -2.99, + "curve": [ 3.056, -3.08, 3.09, 0 ] + }, + { "time": 3.1667 } + ] + }, + "torso3": { + "rotate": [ + { + "time": 1.3, + "curve": [ 1.352, 0, 1.408, 6.47 ] + }, + { + "time": 1.4667, + "value": 6.43, + "curve": [ 1.55, 6.39, 1.723, -5.05 ] + }, + { + "time": 1.7333, + "value": -5.53, + "curve": [ 1.782, -7.72, 1.843, -16.94 ] + }, + { + "time": 1.9667, + "value": -16.86, + "curve": [ 2.111, -16.78, 2.259, -3.97 ] + }, + { + "time": 2.4, + "value": -2.43, + "curve": [ 2.525, -1.12, 2.639, -0.5 ] + }, + { + "time": 2.7333, + "value": -0.49, + "curve": [ 2.931, -0.47, 2.999, -2.15 ] + }, + { "time": 3.1667, "value": -2.15 } + ] + }, + "head-control": { + "translate": [ + { + "time": 1.2333, + "curve": [ 1.25, 0, 1.474, 6.89, 1.25, 0, 1.496, 0.98 ] + }, + { + "time": 1.6667, + "x": 11.99, + "y": -6.42, + "curve": [ 1.743, 14.01, 1.86, 14.33, 1.785, -11.55, 1.86, -27.1 ] + }, + { + "time": 1.9667, + "x": 13.91, + "y": -26.88, + "curve": [ 2.074, 13.49, 2.244, 8.13, 2.074, -26.65, 2.215, -21.78 ] + }, + { + "time": 2.3, + "x": 6.07, + "y": -16.64, + "curve": [ 2.416, 1.84, 2.497, -1.41, 2.417, -9.57, 2.526, -1.72 ] + }, + { + "time": 2.5667, + "x": -3.78, + "y": -1.71, + "curve": [ 2.661, -6.98, 2.76, -8.76, 2.692, -1.68, 2.821, -15.75 ] + }, + { + "time": 2.9, + "x": -8.32, + "y": -16.7, + "curve": [ 2.962, -8.12, 3.082, -0.04, 2.958, -17.39, 3.089, 0 ] + }, + { "time": 3.1667 } + ] + }, + "front-shoulder": { + "translate": [ + { + "time": 1.3333, + "curve": [ 1.488, 0, 1.717, 0.21, 1.488, 0, 1.688, -30.29 ] + }, + { + "time": 1.9, + "x": 0.83, + "y": -30.29, + "curve": [ 2.078, 1.43, 2.274, 2.88, 2.071, -30.29, 2.289, 4.48 ] + }, + { + "time": 2.4333, + "x": 2.89, + "y": 4.59, + "curve": [ 2.604, 2.89, 2.677, -0.68, 2.57, 4.7, 2.694, -2.43 ] + }, + { + "time": 2.7667, + "x": -0.67, + "y": -2.47, + "curve": [ 2.866, -0.67, 2.986, -0.07, 2.882, -2.47, 3.036, -0.06 ] + }, + { "time": 3.1667 } + ] + } + }, + "ik": { + "rear-leg-ik": [ + { "time": 3.1667, "softness": 10, "bendPositive": false } + ] + } + }, + "run": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" } + ] + } + }, + "bones": { + "front-thigh": { + "translate": [ + { + "x": -5.14, + "y": 11.13, + "curve": [ 0.033, -7.77, 0.112, -9.03, 0.034, 11.13, 0.108, 9.74 ] + }, + { + "time": 0.1667, + "x": -9.03, + "y": 7.99, + "curve": [ 0.23, -9.05, 0.314, -1.34, 0.236, 5.93, 0.28, 3.22 ] + }, + { + "time": 0.3333, + "x": 0.41, + "y": 3.19, + "curve": [ 0.352, 2.09, 0.449, 11.16, 0.384, 3.16, 0.449, 4.98 ] + }, + { + "time": 0.5, + "x": 11.17, + "y": 6.76, + "curve": [ 0.571, 10.79, 0.621, -1.83, 0.542, 8.21, 0.625, 11.13 ] + }, + { "time": 0.6667, "x": -5.14, "y": 11.13 } + ] + }, + "torso": { + "rotate": [ + { + "value": -37.66, + "curve": [ 0.034, -37.14, 0.107, -36.21 ] + }, + { + "time": 0.1333, + "value": -36.21, + "curve": [ 0.158, -36.21, 0.209, -38.8 ] + }, + { + "time": 0.2333, + "value": -38.79, + "curve": [ 0.259, -38.78, 0.313, -38.03 ] + }, + { + "time": 0.3333, + "value": -37.66, + "curve": [ 0.357, -37.21, 0.4, -36.21 ] + }, + { + "time": 0.4333, + "value": -36.21, + "curve": [ 0.458, -36.21, 0.539, -38.8 ] + }, + { + "time": 0.5667, + "value": -38.8, + "curve": [ 0.592, -38.8, 0.645, -38 ] + }, + { "time": 0.6667, "value": -37.66 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -16.41, + "y": 1.55, + "curve": [ 0.013, -15.67, 0.183, -8.55, 0.03, 2.39, 0.183, 6.17 ] + }, + { + "time": 0.2333, + "x": -8.55, + "y": 6.17, + "curve": [ 0.308, -8.55, 0.492, -19.75, 0.308, 6.17, 0.492, 0.61 ] + }, + { + "time": 0.5667, + "x": -19.75, + "y": 0.61, + "curve": [ 0.592, -19.75, 0.641, -18.06, 0.592, 0.61, 0.632, 0.78 ] + }, + { "time": 0.6667, "x": -16.41, "y": 1.55 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -39.03, + "curve": [ 0.051, -0.1, 0.145, 88.36 ] + }, + { + "time": 0.2333, + "value": 88.36, + "curve": [ 0.28, 88.76, 0.324, 59.52 ] + }, + { + "time": 0.3333, + "value": 51.13, + "curve": [ 0.358, 30.2, 0.445, -74.91 ] + }, + { + "time": 0.5667, + "value": -75.82, + "curve": [ 0.599, -76.06, 0.642, -55.72 ] + }, + { "time": 0.6667, "value": -39.03 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 20.54, + "curve": [ 0.052, 11.42, 0.089, 0.13 ] + }, + { + "time": 0.1333, + "value": 0.15, + "curve": [ 0.186, 0.17, 0.221, 26.29 ] + }, + { + "time": 0.2333, + "value": 32.37, + "curve": [ 0.247, 39.19, 0.286, 61.45 ] + }, + { + "time": 0.3333, + "value": 61.58, + "curve": [ 0.371, 61.69, 0.42, 55.79 ] + }, + { "time": 0.4667, "value": 49.68 }, + { "time": 0.6667, "value": 20.54 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16, + "curve": [ 0.014, -38.8, 0.036, -43.27 ] + }, + { + "time": 0.0667, + "value": -43.37, + "curve": [ 0.102, -43.49, 0.182, -28.46 ] + }, + { + "time": 0.2, + "value": -23.04, + "curve": [ 0.23, -13.87, 0.264, 3.86 ] + }, + { + "time": 0.3333, + "value": 3.7, + "curve": [ 0.38, 3.64, 0.535, -16.22 ] + }, + { "time": 0.5667, "value": -21.29 }, + { "time": 0.6667, "value": -36.16 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.5, + "curve": [ 0.028, 23.74, 0.128, -79.86 ] + }, + { + "time": 0.2333, + "value": -79.87, + "curve": [ 0.38, -79.88, 0.403, 63.25 ] + }, + { + "time": 0.5667, + "value": 64.13, + "curve": [ 0.607, 64.35, 0.644, 53.1 ] + }, + { "time": 0.6667, "value": 40.5 } + ], + "translate": [ + { + "x": -3.79, + "y": -0.77, + "curve": [ 0.044, -4.58, 0.169, -5.48, 0.044, 0.93, 0.169, 2.85 ] + }, + { + "time": 0.2333, + "x": -5.48, + "y": 2.85, + "curve": [ 0.346, -5.48, 0.475, -2.68, 0.346, 2.85, 0.475, -3.13 ] + }, + { + "time": 0.5667, + "x": -2.68, + "y": -3.13, + "curve": [ 0.611, -2.68, 0.642, -3.34, 0.611, -3.13, 0.642, -1.73 ] + }, + { "time": 0.6667, "x": -3.79, "y": -0.77 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": 28.28 }, + { + "time": 0.2333, + "value": -11.12, + "curve": [ 0.252, -14.12, 0.297, -19.37 ] + }, + { + "time": 0.3333, + "value": -19.38, + "curve": [ 0.435, -19.41, 0.522, 38.96 ] + }, + { + "time": 0.5667, + "value": 38.87, + "curve": [ 0.619, 38.76, 0.644, 32.01 ] + }, + { "time": 0.6667, "value": 28.28 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.88, + "curve": [ 0.024, 11.4, 0.075, 9.74 ] + }, + { + "time": 0.1, + "value": 9.74, + "curve": [ 0.125, 9.74, 0.208, 13.36 ] + }, + { + "time": 0.2333, + "value": 13.36, + "curve": [ 0.258, 13.36, 0.321, 12.2 ] + }, + { + "time": 0.3333, + "value": 11.88, + "curve": [ 0.365, 11.06, 0.408, 9.72 ] + }, + { + "time": 0.4333, + "value": 9.72, + "curve": [ 0.458, 9.72, 0.542, 13.36 ] + }, + { + "time": 0.5667, + "value": 13.36, + "curve": [ 0.592, 13.36, 0.636, 12.48 ] + }, + { "time": 0.6667, "value": 11.88 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.14, + "curve": [ 0.02, 11.99, 0.039, 8.94 ] + }, + { + "time": 0.0667, + "value": 8.93, + "curve": [ 0.122, 8.9, 0.232, 15.8 ] + }, + { + "time": 0.2667, + "value": 15.81, + "curve": [ 0.325, 15.82, 0.357, 8.95 ] + }, + { + "time": 0.4, + "value": 8.93, + "curve": [ 0.444, 8.91, 0.568, 15.8 ] + }, + { + "time": 0.6, + "value": 15.77, + "curve": [ 0.632, 15.74, 0.649, 14.05 ] + }, + { "time": 0.6667, "value": 13.14 } + ], + "scale": [ + { + "curve": [ 0.014, 0.996, 0.068, 0.991, 0.027, 1.005, 0.083, 1.012 ] + }, + { + "time": 0.1, + "x": 0.991, + "y": 1.012, + "curve": [ 0.128, 0.991, 0.205, 1.018, 0.128, 1.012, 0.197, 0.988 ] + }, + { + "time": 0.2333, + "x": 1.018, + "y": 0.988, + "curve": [ 0.272, 1.018, 0.305, 1.008, 0.262, 0.988, 0.311, 0.995 ] + }, + { + "time": 0.3333, + "curve": [ 0.351, 0.995, 0.417, 0.987, 0.359, 1.006, 0.417, 1.013 ] + }, + { + "time": 0.4333, + "x": 0.987, + "y": 1.013, + "curve": [ 0.467, 0.987, 0.533, 1.02, 0.467, 1.013, 0.533, 0.989 ] + }, + { + "time": 0.5667, + "x": 1.02, + "y": 0.989, + "curve": [ 0.592, 1.02, 0.652, 1.004, 0.592, 0.989, 0.644, 0.996 ] + }, + { "time": 0.6667 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.36, + "curve": [ 0.022, 16.28, 0.087, 20.25 ] + }, + { + "time": 0.1333, + "value": 20.19, + "curve": [ 0.168, 20.32, 0.254, -8.82 ] + }, + { + "time": 0.2667, + "value": -11.88, + "curve": [ 0.291, -17.91, 0.344, -24.11 ] + }, + { + "time": 0.4, + "value": -23.88, + "curve": [ 0.448, -23.69, 0.533, -15.47 ] + }, + { "time": 0.5667, "value": -8.69 }, + { "time": 0.6667, "value": 12.36 } + ] + }, + "hip": { + "rotate": [ + { "value": -8.24 } + ], + "translate": [ + { + "x": -3.6, + "y": -34.1, + "curve": [ 0.042, -3.84, 0.118, 7.62, 0.042, -33.74, 0.112, 20.55 ] + }, + { + "time": 0.1667, + "x": 7.61, + "y": 20.36, + "curve": [ 0.194, 7.6, 0.21, 5.06, 0.204, 20.65, 0.217, -8.69 ] + }, + { + "time": 0.2333, + "x": 1.68, + "y": -18.48, + "curve": [ 0.279, -4.99, 0.297, -5.64, 0.254, -31.08, 0.292, -34.55 ] + }, + { + "time": 0.3333, + "x": -5.76, + "y": -35, + "curve": [ 0.379, -5.9, 0.451, 6.8, 0.384, -35.56, 0.428, 17.6 ] + }, + { + "time": 0.5, + "x": 6.61, + "y": 17.01, + "curve": [ 0.536, 6.47, 0.545, 3.56, 0.533, 16.75, 0.548, -8.71 ] + }, + { + "time": 0.5667, + "x": 0.35, + "y": -18.81, + "curve": [ 0.597, -4.07, 0.642, -3.45, 0.584, -28.58, 0.642, -34.32 ] + }, + { "time": 0.6667, "x": -3.6, "y": -34.1 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": -62.54, + "curve": [ 0.015, -74.19, 0.056, -103.19 ] + }, + { + "time": 0.0667, + "value": -111.08, + "curve": [ 0.092, -129.44, 0.189, -146.55 ] + }, + { + "time": 0.2333, + "value": -146.32, + "curve": [ 0.285, -146.06, 0.32, -125.1 ] + }, + { "time": 0.3333, "value": -117.24 }, + { + "time": 0.5, + "value": -35.07, + "curve": [ 0.522, -28.64, 0.546, -24.84 ] + }, + { + "time": 0.5667, + "value": -24.9, + "curve": [ 0.595, -25, 0.623, -40.82 ] + }, + { "time": 0.6667, "value": -62.54 } + ], + "translate": [ + { "x": 16.34, "y": 0.18 }, + { + "time": 0.0667, + "x": -101.43, + "y": 8.04, + "curve": [ 0.085, -131.35, 0.129, -207.69, 0.08, 14.9, 0.124, 113.28 ] + }, + { + "time": 0.1667, + "x": -207.92, + "y": 145.81, + "curve": [ 0.196, -208.13, 0.21, -202.91, 0.186, 160.26, 0.206, 163.48 ] + }, + { + "time": 0.2333, + "x": -189.94, + "y": 163.85, + "curve": [ 0.27, -169.94, 0.31, -126.19, 0.269, 164.35, 0.316, 85.97 ] + }, + { + "time": 0.3333, + "x": -90.56, + "y": 78.57, + "curve": [ 0.355, -57.99, 0.376, -29.14, 0.35, 71.55, 0.376, 66.4 ] + }, + { + "time": 0.4, + "x": 2.87, + "y": 66.38, + "curve": [ 0.412, 19.24, 0.469, 90.73, 0.429, 66.37, 0.469, 70.66 ] + }, + { + "time": 0.5, + "x": 117.18, + "y": 70.46, + "curve": [ 0.522, 136.24, 0.542, 151.33, 0.539, 70.2, 0.555, 38.25 ] + }, + { + "time": 0.5667, + "x": 151.49, + "y": 25.29, + "curve": [ 0.578, 146.76, 0.586, 133.13, 0.572, 19.7, 0.582, 12.23 ] + }, + { "time": 0.6, "x": 115.02, "y": 0.1 }, + { "time": 0.6667, "x": 16.34, "y": 0.18 } + ] + }, + "front-leg-target": { + "translate": [ + { "x": -13.95, "y": -30.34 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": 18.55 }, + { + "time": 0.2333, + "value": 167.84, + "curve": [ 0.246, 153.66, 0.256, 129.74 ] + }, + { + "time": 0.2667, + "value": 124.32, + "curve": [ 0.296, 124.43, 0.313, 129.93 ] + }, + { + "time": 0.3667, + "value": 129.87, + "curve": [ 0.421, 128.32, 0.519, 0.98 ] + }, + { + "time": 0.5667, + "curve": [ 0.6, 0.27, 0.642, 4.73 ] + }, + { "time": 0.6667, "value": 18.55 } + ], + "translate": [ + { + "x": -176.39, + "y": 134.12, + "curve": [ 0.018, -142.26, 0.054, -94.41, 0.01, 120.96, 0.044, 84.08 ] + }, + { + "time": 0.0667, + "x": -73.56, + "y": 76.68, + "curve": [ 0.086, -42.82, 0.194, 101.2, 0.098, 66.73, 0.198, 60.88 ] + }, + { "time": 0.2333, "x": 98.32, "y": 32.17 }, + { "time": 0.2667, "x": 49.13, "y": -0.63 }, + { + "time": 0.4, + "x": -147.9, + "y": 0.32, + "curve": [ 0.414, -168.78, 0.478, -284.76, 0.43, 30.09, 0.478, 129.14 ] + }, + { + "time": 0.5, + "x": -283.37, + "y": 167.12, + "curve": [ 0.526, -285.66, 0.548, -280.54, 0.516, 194.84, 0.55, 216.53 ] + }, + { + "time": 0.5667, + "x": -266.98, + "y": 216.12, + "curve": [ 0.581, -256.27, 0.643, -206.54, 0.61, 214.82, 0.65, 145.33 ] + }, + { "time": 0.6667, "x": -176.39, "y": 134.12 } + ] + }, + "rear-leg-target": { + "translate": [ + { "x": 85, "y": -33.59 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "value": -147.04, + "curve": [ 0.033, -113.4, 0.161, 44.34 ] + }, + { + "time": 0.2333, + "value": 43.48, + "curve": [ 0.24, 43.41, 0.282, 35.72 ] + }, + { + "time": 0.3, + "value": 0.29, + "curve": [ 0.347, 0.28, 0.396, 4.27 ] + }, + { + "time": 0.4, + "curve": [ 0.424, -23.8, 0.525, -181.39 ] + }, + { + "time": 0.5667, + "value": -181.39, + "curve": [ 0.592, -181.39, 0.642, -169.09 ] + }, + { "time": 0.6667, "value": -147.04 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -0.25, + "curve": [ 0.008, -0.25, 0.056, 1.73 ] + }, + { + "time": 0.0667, + "value": -7.68, + "curve": [ 0.075, -43.13, 0.15, -130.44 ] + }, + { + "time": 0.2, + "value": -130.08, + "curve": [ 0.239, -129.79, 0.272, -126.8 ] + }, + { + "time": 0.3, + "value": -116.24, + "curve": [ 0.333, -103.91, 0.348, -86.1 ] + }, + { + "time": 0.3667, + "value": -71.08, + "curve": [ 0.386, -55.25, 0.415, -32.44 ] + }, + { + "time": 0.4333, + "value": -21.63, + "curve": [ 0.47, -0.01, 0.542, 33.42 ] + }, + { + "time": 0.5667, + "value": 33.2, + "curve": [ 0.622, 32.7, 0.569, 0.64 ] + }, + { "time": 0.6667, "value": -0.25 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.087, -6.81, 0.143, -5.75 ] + }, + { + "time": 0.1667, + "value": -4.3, + "curve": [ 0.183, -3.28, 0.209, 2.79 ] + }, + { + "time": 0.2333, + "value": 2.78, + "curve": [ 0.262, 2.77, 0.305, -6.63 ] + }, + { + "time": 0.3333, + "value": -6.64, + "curve": [ 0.419, -6.68, 0.49, -4.84 ] + }, + { + "time": 0.5, + "value": -4.38, + "curve": [ 0.518, -3.56, 0.574, 2.32 ] + }, + { + "time": 0.6, + "value": 2.33, + "curve": [ 0.643, 2.35, 0.633, -6.81 ] + }, + { "time": 0.6667, "value": -6.81 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.014, -3.17, 0.109, 43.93 ] + }, + { + "time": 0.1333, + "value": 43.95, + "curve": [ 0.177, 43.97, 0.192, -13.76 ] + }, + { + "time": 0.2667, + "value": -13.83, + "curve": [ 0.302, -13.72, 0.322, -8.86 ] + }, + { + "time": 0.3333, + "value": -6.6, + "curve": [ 0.349, -3.5, 0.436, 41.1 ] + }, + { + "time": 0.4667, + "value": 41.05, + "curve": [ 0.51, 40.99, 0.549, -14.06 ] + }, + { + "time": 0.6, + "value": -14.18, + "curve": [ 0.63, -14.26, 0.656, -9.04 ] + }, + { "time": 0.6667, "value": -6.81 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.079, -6.83, 0.108, 0.3 ] + }, + { + "time": 0.1333, + "value": 1.96, + "curve": [ 0.177, 4.89, 0.208, 6.28 ] + }, + { + "time": 0.2333, + "value": 6.29, + "curve": [ 0.313, 6.31, 0.383, 3.49 ] + }, + { + "time": 0.4, + "value": 2.58, + "curve": [ 0.442, 0.28, 0.523, -6.81 ] + }, + { "time": 0.6, "value": -6.81 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.011, -4.06, 0.108, 24.92 ] + }, + { + "time": 0.1333, + "value": 24.92, + "curve": [ 0.158, 24.92, 0.208, -10.62 ] + }, + { + "time": 0.2333, + "value": -10.62, + "curve": [ 0.254, -10.62, 0.312, -9.73 ] + }, + { + "time": 0.3333, + "value": -6.4, + "curve": [ 0.356, -2.95, 0.438, 24.93 ] + }, + { + "time": 0.4667, + "value": 24.93, + "curve": [ 0.492, 24.93, 0.575, -9.78 ] + }, + { + "time": 0.6, + "value": -9.78, + "curve": [ 0.617, -9.78, 0.655, -8.63 ] + }, + { "time": 0.6667, "value": -6.81 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 3.5, + "curve": [ 0.07, 3.51, 0.075, 8.69 ] + }, + { + "time": 0.1, + "value": 8.69, + "curve": [ 0.139, 8.69, 0.214, 6.9 ] + }, + { + "time": 0.2333, + "value": 6.33, + "curve": [ 0.266, 5.34, 0.285, 3.48 ] + }, + { + "time": 0.3333, + "value": 3.48, + "curve": [ 0.398, 3.48, 0.408, 8.68 ] + }, + { + "time": 0.4333, + "value": 8.68, + "curve": [ 0.458, 8.68, 0.551, 6.8 ] + }, + { + "time": 0.5667, + "value": 6.26, + "curve": [ 0.598, 5.17, 0.642, 3.49 ] + }, + { "time": 0.6667, "value": 3.5 } + ] + }, + "torso3": { + "rotate": [ + { + "value": 4.52, + "curve": [ 0.067, 4.54, 0.075, -7.27 ] + }, + { + "time": 0.1, + "value": -7.27, + "curve": [ 0.125, -7.27, 0.227, 0.84 ] + }, + { + "time": 0.2333, + "value": 1.24, + "curve": [ 0.254, 2.5, 0.301, 4.51 ] + }, + { + "time": 0.3333, + "value": 4.52, + "curve": [ 0.386, 4.54, 0.408, -7.35 ] + }, + { + "time": 0.4333, + "value": -7.35, + "curve": [ 0.458, -7.35, 0.549, -0.14 ] + }, + { + "time": 0.5667, + "value": 0.95, + "curve": [ 0.586, 2.18, 0.632, 4.54 ] + }, + { "time": 0.6667, "value": 4.52 } + ] + }, + "aim-constraint-target": { + "rotate": [ + { "value": 30.57 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": -6.5 } + ] + }, + "front-foot": { + "rotate": [ + { "value": 4.5 } + ] + }, + "head-control": { + "translate": [ + { + "y": -9.94, + "curve": [ 0.058, 0, 0.175, -15.32, 0.044, -4.19, 0.175, 5 ] + }, + { + "time": 0.2333, + "x": -15.32, + "y": 5, + "curve": [ 0.317, -15.32, 0.429, -9.74, 0.317, 5, 0.382, -31.71 ] + }, + { + "time": 0.4667, + "x": -7.81, + "y": -31.59, + "curve": [ 0.507, -5.76, 0.617, 0, 0.549, -31.47, 0.628, -13.33 ] + }, + { "time": 0.6667, "y": -9.94 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": -0.74, + "y": 11.22, + "curve": [ 0.061, -0.74, 0.144, 1.17, 0.061, 11.22, 0.143, -17.93 ] + }, + { + "time": 0.2333, + "x": 1.19, + "y": -17.9, + "curve": [ 0.54, 1.25, 0.558, -0.74, 0.545, -17.8, 0.558, 11.22 ] + }, + { "time": 0.6667, "x": -0.74, "y": 11.22 } + ] + }, + "back-shoulder": { + "translate": [ + { + "curve": [ 0.083, 0, 0.25, 0, 0.083, 0, 0.25, 8.93 ] + }, + { + "time": 0.3333, + "y": 8.93, + "curve": [ 0.417, 0, 0.583, 0, 0.417, 8.93, 0.583, 0 ] + }, + { "time": 0.6667 } + ] + } + }, + "ik": { + "front-leg-ik": [ + { "softness": 10, "bendPositive": false }, + { "time": 0.5667, "softness": 14.8, "bendPositive": false }, + { "time": 0.6, "softness": 48.2, "bendPositive": false }, + { "time": 0.6667, "softness": 10, "bendPositive": false } + ], + "rear-leg-ik": [ + { "bendPositive": false }, + { "time": 0.1667, "softness": 22.5, "bendPositive": false }, + { "time": 0.3, "softness": 61.4, "bendPositive": false }, + { "time": 0.6667, "bendPositive": false } + ] + }, + "events": [ + { "time": 0.2333, "name": "footstep" }, + { "time": 0.5667, "name": "footstep" } + ] + }, + "run-to-idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-foot-target": { + "translate": [ + { + "x": -16.5, + "y": 3.41, + "curve": [ 0.033, -16.5, 0.1, -69.06, 0.033, 3.41, 0.1, 0 ] + }, + { "time": 0.1333, "x": -69.06 } + ] + }, + "hip": { + "translate": [ + { + "x": -28.78, + "y": -72.96, + "curve": [ 0.036, -28.63, 0.2, -10.85, 0.135, -62.35, 0.2, -23.15 ] + }, + { "time": 0.2667, "x": -11.97, "y": -23.15 } + ] + }, + "rear-foot-target": { + "translate": [ + { + "x": 33.15, + "y": 31.61, + "curve": [ 0.017, 33.15, 0.05, 24.41, 0.017, 31.61, 0.041, 20.73 ] + }, + { + "time": 0.0667, + "x": 24.41, + "y": 0.19, + "curve": [ 0.117, 24.41, 0.217, 48.87, 0.117, 0.19, 0.217, 0 ] + }, + { "time": 0.2667, "x": 48.87 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -80.61, + "curve": [ 0.067, -80.61, 0.2, -60.87 ] + }, + { "time": 0.2667, "value": -60.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 8.79, + "curve": [ 0.041, 8.79, 0.115, 6.3 ] + }, + { + "time": 0.1667, + "value": 6.41, + "curve": [ 0.201, 6.48, 0.241, 42.46 ] + }, + { "time": 0.2667, "value": 42.46 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 55.3, + "curve": [ 0.067, 55.3, 0.2, 39.2 ] + }, + { "time": 0.2667, "value": 39.2 } + ] + }, + "head": { + "rotate": [ + { + "curve": [ 0.05, 0, 0.083, 2.67 ] + }, + { + "time": 0.1333, + "value": 2.67, + "curve": [ 0.15, 2.67, 0.25, -6.75 ] + }, + { "time": 0.2667, "value": -6.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": 38.26, + "curve": [ 0.041, 38.26, 0.127, -2.19 ] + }, + { + "time": 0.1667, + "value": -3, + "curve": [ 0.209, -3.84, 0.241, 0 ] + }, + { "time": 0.2667 } + ], + "scale": [ + { + "x": 0.844, + "curve": [ 0.067, 0.844, 0.2, 1, 0.067, 1, 0.2, 1 ] + }, + { "time": 0.2667 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 57.24, + "curve": [ 0.067, 57.24, 0.2, 0 ] + }, + { "time": 0.2667 } + ] + }, + "gun": { + "rotate": [ + { + "value": 2.28, + "curve": [ 0.041, 2.28, 0.105, 15.34 ] + }, + { + "time": 0.1667, + "value": 15.32, + "curve": [ 0.205, 15.31, 0.241, 0 ] + }, + { "time": 0.2667 } + ] + }, + "torso": { + "rotate": [ + { + "value": -12.98, + "curve": [ 0.033, -12.98, 0.103, -14.81 ] + }, + { + "time": 0.1333, + "value": -16.63, + "curve": [ 0.168, -18.69, 0.233, -22.88 ] + }, + { "time": 0.2667, "value": -22.88 } + ], + "scale": [ + { + "x": 0.963, + "y": 1.074, + "curve": [ 0.067, 0.963, 0.132, 1, 0.067, 1.074, 0.132, 1 ] + }, + { "time": 0.2667 } + ] + }, + "neck": { + "rotate": [ + {}, + { "time": 0.2667, "value": 3.78 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 0.88 ] + }, + { + "time": 0.1333, + "value": 0.88, + "curve": [ 0.167, 0.88, 0.233, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 15.97 ] + }, + { + "time": 0.1333, + "value": 15.97, + "curve": [ 0.167, 15.97, 0.233, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 10.76 ] + }, + { + "time": 0.1333, + "value": 10.76, + "curve": [ 0.167, 10.76, 0.233, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair2": { + "rotate": [ + { + "curve": [ 0.014, -2.28, 0.042, -7.84 ] + }, + { + "time": 0.0667, + "value": -7.82, + "curve": [ 0.108, -7.79, 0.166, 6.57 ] + }, + { + "time": 0.2, + "value": 6.67, + "curve": [ 0.222, 6.73, 0.255, 1.98 ] + }, + { "time": 0.2667 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.041, 0, 0.107, 3.03 ] + }, + { + "time": 0.1667, + "value": 3.03, + "curve": [ 0.205, 3.03, 0.241, 0 ] + }, + { "time": 0.2667 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.049, 0, 0.166, 0.66 ] + }, + { + "time": 0.2, + "value": 0.66, + "curve": [ 0.232, 0.65, 0.249, -2.15 ] + }, + { "time": 0.2667, "value": -2.15 } + ] + }, + "head-control": { + "translate": [ + { "x": -10.12, "y": 8.71 }, + { "time": 0.2667 } + ] + }, + "front-shoulder": { + "translate": [ + { "x": 4.91, "y": 11.54 }, + { "time": 0.2667 } + ] + } + } + }, + "shoot": { + "slots": { + "muzzle": { + "rgba": [ + { "time": 0.1333, "color": "ffffffff" }, + { "time": 0.2, "color": "ffffff62" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle01" }, + { "time": 0.0667, "name": "muzzle02" }, + { "time": 0.1, "name": "muzzle03" }, + { "time": 0.1333, "name": "muzzle04" }, + { "time": 0.1667, "name": "muzzle05" }, + { "time": 0.2 } + ] + }, + "muzzle-glow": { + "rgba": [ + { "color": "ff0c0c00" }, + { + "time": 0.0333, + "color": "ffc9adff", + "curve": [ 0.255, 1, 0.273, 1, 0.255, 0.76, 0.273, 0.4, 0.255, 0.65, 0.273, 0.22, 0.255, 1, 0.273, 1 ] + }, + { "time": 0.3, "color": "ff400cff" }, + { "time": 0.6333, "color": "ff0c0c00" } + ], + "attachment": [ + { "name": "muzzle-glow" } + ] + }, + "muzzle-ring": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.202, 0.85, 0.214, 0.84, 0.202, 0.73, 0.214, 0.73, 0.202, 1, 0.214, 1, 0.202, 1, 0.214, 0.21 ] + }, + { "time": 0.2333, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2333 } + ] + }, + "muzzle-ring2": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.174, 0.85, 0.184, 0.84, 0.174, 0.73, 0.184, 0.73, 0.174, 1, 0.184, 1, 0.174, 1, 0.184, 0.21 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2 } + ] + }, + "muzzle-ring3": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.174, 0.85, 0.184, 0.84, 0.174, 0.73, 0.184, 0.73, 0.174, 1, 0.184, 1, 0.174, 1, 0.184, 0.21 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2 } + ] + }, + "muzzle-ring4": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.174, 0.85, 0.184, 0.84, 0.174, 0.73, 0.184, 0.73, 0.174, 1, 0.184, 1, 0.174, 1, 0.184, 0.21 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2 } + ] + } + }, + "bones": { + "gun": { + "rotate": [ + { + "time": 0.0667, + "curve": [ 0.094, 25.89, 0.112, 45.27 ] + }, + { + "time": 0.1333, + "value": 45.35, + "curve": [ 0.192, 45.28, 0.18, -0.09 ] + }, + { "time": 0.6333 } + ] + }, + "muzzle": { + "translate": [ + { "x": -11.02, "y": 25.16 } + ] + }, + "rear-upper-arm": { + "translate": [ + { + "time": 0.0333, + "curve": [ 0.045, 0.91, 0.083, 3.46, 0.044, 0.86, 0.083, 3.32 ] + }, + { + "time": 0.1, + "x": 3.46, + "y": 3.32, + "curve": [ 0.133, 3.46, 0.176, -0.1, 0.133, 3.32, 0.169, 0 ] + }, + { "time": 0.2333 } + ] + }, + "rear-bracer": { + "translate": [ + { + "time": 0.0333, + "curve": [ 0.075, -3.78, 0.083, -4.36, 0.08, -2.7, 0.083, -2.88 ] + }, + { + "time": 0.1, + "x": -4.36, + "y": -2.88, + "curve": [ 0.133, -4.36, 0.168, 0.18, 0.133, -2.88, 0.167, 0 ] + }, + { "time": 0.2333 } + ] + }, + "gun-tip": { + "translate": [ + {}, + { "time": 0.3, "x": 3.15, "y": 0.39 } + ], + "scale": [ + { "x": 0.366, "y": 0.366 }, + { "time": 0.0333, "x": 1.453, "y": 1.453 }, + { "time": 0.3, "x": 0.366, "y": 0.366 } + ] + }, + "muzzle-ring": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2333, "x": 64.47 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2333, "x": 5.951, "y": 5.951 } + ] + }, + "muzzle-ring2": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 172.57 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 4, "y": 4 } + ] + }, + "muzzle-ring3": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 277.17 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 2, "y": 2 } + ] + }, + "muzzle-ring4": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 392.06 } + ] + } + } + }, + "walk": { + "bones": { + "rear-foot-target": { + "rotate": [ + { + "value": -32.82, + "curve": [ 0.035, -42.69, 0.057, -70.49 ] + }, + { + "time": 0.1, + "value": -70.59, + "curve": [ 0.236, -70.78, 0.335, -9.87 ] + }, + { + "time": 0.3667, + "value": -1.56, + "curve": [ 0.393, 5.5, 0.477, 13.96 ] + }, + { + "time": 0.5, + "value": 13.96, + "curve": [ 0.519, 13.96, 0.508, 0.13 ] + }, + { "time": 0.5667, "value": -0.28 }, + { + "time": 0.7333, + "value": -0.28, + "curve": [ 0.827, -0.06, 0.958, -21.07 ] + }, + { "time": 1, "value": -32.82 } + ], + "translate": [ + { + "x": -167.32, + "y": 0.58, + "curve": [ 0.022, -180.55, 0.075, -235.51, 0.045, 0.58, 0.075, 30.12 ] + }, + { + "time": 0.1, + "x": -235.51, + "y": 39.92, + "curve": [ 0.142, -235.51, 0.208, -201.73, 0.138, 54.94, 0.18, 60.78 ] + }, + { + "time": 0.2333, + "x": -176.33, + "y": 61.48, + "curve": [ 0.272, -136.61, 0.321, -45.18, 0.275, 62.02, 0.321, 56.6 ] + }, + { + "time": 0.3667, + "x": 8.44, + "y": 49.67, + "curve": [ 0.403, 51.03, 0.486, 66.86, 0.401, 44.37, 0.48, 23.11 ] + }, + { "time": 0.5, "x": 66.57, "y": 14.22 }, + { "time": 0.5333, "x": 52.58, "y": 0.6 }, + { "time": 1, "x": -167.32, "y": 0.58 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": 18.19, + "curve": [ 0.01, 11.17, 0.043, 1.37 ] + }, + { "time": 0.1, "value": 0.47 }, + { + "time": 0.2333, + "value": 0.55, + "curve": [ 0.364, 0.3, 0.515, -80.48 ] + }, + { + "time": 0.7333, + "value": -80.78, + "curve": [ 0.788, -80.38, 0.921, 17.42 ] + }, + { "time": 1, "value": 18.19 } + ], + "translate": [ + { + "x": 139.21, + "y": 22.94, + "curve": [ 0.025, 139.21, 0.069, 111.46, 0.031, 3.25, 0.075, 0.06 ] + }, + { "time": 0.1, "x": 96.69, "y": 0.06 }, + { + "time": 0.5, + "x": -94.87, + "y": -0.03, + "curve": [ 0.518, -106.82, 0.575, -152.56, 0.534, 5.42, 0.557, 38.46 ] + }, + { + "time": 0.6, + "x": -152.56, + "y": 57.05, + "curve": [ 0.633, -152.56, 0.688, -128.05, 0.643, 75.61, 0.7, 84.14 ] + }, + { + "time": 0.7333, + "x": -109.42, + "y": 84.14, + "curve": [ 0.771, -93.91, 0.832, -30.64, 0.787, 84.14, 0.799, 89.65 ] + }, + { + "time": 0.8667, + "x": 17, + "y": 75.25, + "curve": [ 0.903, 66.18, 0.967, 139.21, 0.932, 61.53, 0.967, 44.02 ] + }, + { "time": 1, "x": 139.21, "y": 22.94 } + ] + }, + "hip": { + "rotate": [ + { "value": -4.35 } + ], + "translate": [ + { + "x": -2.86, + "y": -13.86, + "curve": [ 0.025, -2.84, 0.067, -2.82, 0.028, -19.14, 0.054, -24.02 ] + }, + { + "time": 0.1, + "x": -2.61, + "y": -24.19, + "curve": [ 0.143, -2.34, 0.202, -1.79, 0.152, -23.98, 0.213, -14.81 ] + }, + { + "time": 0.2667, + "x": -1.21, + "y": -7.12, + "curve": [ 0.308, -0.86, 0.345, -0.51, 0.306, -1.63, 0.341, 3.15 ] + }, + { + "time": 0.3667, + "x": -0.33, + "y": 3.15, + "curve": [ 0.41, 0.02, 0.458, 0.26, 0.427, 3.3, 0.481, -6.75 ] + }, + { + "time": 0.5, + "x": 0.26, + "y": -10.59, + "curve": [ 0.553, 0.26, 0.559, 0.2, 0.519, -14.41, 0.548, -23.88 ] + }, + { + "time": 0.6, + "x": -0.17, + "y": -23.71, + "curve": [ 0.663, -0.72, 0.798, -2.09, 0.702, -23.36, 0.802, 3.53 ] + }, + { + "time": 0.8667, + "x": -2.46, + "y": 3.48, + "curve": [ 0.901, -2.63, 0.967, -2.87, 0.913, 3.45, 0.967, -7.64 ] + }, + { "time": 1, "x": -2.86, "y": -13.86 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": 28.96, + "curve": [ 0.056, 28.74, 0.049, 19.6 ] + }, + { "time": 0.0667, "value": 1.68 }, + { + "time": 0.5, + "value": -10, + "curve": [ 0.525, -10, 0.592, -54.69 ] + }, + { + "time": 0.6, + "value": -59.66, + "curve": [ 0.623, -74.54, 0.674, -101.78 ] + }, + { + "time": 0.7333, + "value": -101.78, + "curve": [ 0.812, -101.78, 0.855, -84.67 ] + }, + { + "time": 0.8667, + "value": -63.53, + "curve": [ 0.869, -58.38, 0.975, 28.96 ] + }, + { "time": 1, "value": 28.96 } + ] + }, + "torso": { + "rotate": [ + { + "value": -20.72, + "curve": [ 0.025, -20.57, 0.071, -20.04 ] + }, + { + "time": 0.1333, + "value": -20.04, + "curve": [ 0.187, -20.04, 0.285, -21.16 ] + }, + { + "time": 0.3667, + "value": -21.16, + "curve": [ 0.405, -21.16, 0.47, -20.9 ] + }, + { + "time": 0.5, + "value": -20.71, + "curve": [ 0.518, -20.6, 0.582, -20.03 ] + }, + { + "time": 0.6333, + "value": -20.04, + "curve": [ 0.709, -20.05, 0.815, -21.18 ] + }, + { + "time": 0.8667, + "value": -21.18, + "curve": [ 0.908, -21.18, 0.971, -20.93 ] + }, + { "time": 1, "value": -20.72 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.78, + "curve": [ 0.025, 17.93, 0.071, 18.46 ] + }, + { + "time": 0.1333, + "value": 18.46, + "curve": [ 0.187, 18.46, 0.285, 17.34 ] + }, + { + "time": 0.3667, + "value": 17.34, + "curve": [ 0.405, 17.34, 0.47, 17.6 ] + }, + { + "time": 0.5, + "value": 17.79, + "curve": [ 0.518, 17.9, 0.582, 18.47 ] + }, + { + "time": 0.6333, + "value": 18.46, + "curve": [ 0.709, 18.45, 0.815, 17.32 ] + }, + { + "time": 0.8667, + "value": 17.32, + "curve": [ 0.908, 17.32, 0.971, 17.57 ] + }, + { "time": 1, "value": 17.78 } + ] + }, + "head": { + "rotate": [ + { + "value": -12.23, + "curve": [ 0.061, -12.23, 0.191, -7.45 ] + }, + { + "time": 0.2667, + "value": -7.43, + "curve": [ 0.341, -7.42, 0.421, -12.23 ] + }, + { + "time": 0.5, + "value": -12.23, + "curve": [ 0.567, -12.26, 0.694, -7.46 ] + }, + { + "time": 0.7667, + "value": -7.47, + "curve": [ 0.853, -7.49, 0.943, -12.23 ] + }, + { "time": 1, "value": -12.23 } + ], + "scale": [ + { + "curve": [ 0.039, 1, 0.084, 0.991, 0.039, 1, 0.084, 1.019 ] + }, + { + "time": 0.1333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.205, 0.991, 0.318, 1.019, 0.205, 1.019, 0.337, 0.992 ] + }, + { + "time": 0.4, + "x": 1.019, + "y": 0.992, + "curve": [ 0.456, 1.019, 0.494, 1.001, 0.483, 0.991, 0.493, 0.999 ] + }, + { + "time": 0.5, + "curve": [ 0.508, 0.998, 0.584, 0.991, 0.51, 1.002, 0.584, 1.019 ] + }, + { + "time": 0.6333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.705, 0.991, 0.818, 1.019, 0.705, 1.019, 0.837, 0.992 ] + }, + { + "time": 0.9, + "x": 1.019, + "y": 0.992, + "curve": [ 0.956, 1.019, 0.955, 1, 0.983, 0.991, 0.955, 1 ] + }, + { "time": 1 } + ] + }, + "back-foot-tip": { + "rotate": [ + { "value": 4.09 }, + { "time": 0.0333, "value": 3.05 }, + { + "time": 0.1, + "value": -59.01, + "curve": [ 0.124, -72.97, 0.169, -100.05 ] + }, + { + "time": 0.2333, + "value": -99.71, + "curve": [ 0.326, -99.21, 0.349, -37.4 ] + }, + { + "time": 0.3667, + "value": -17.85, + "curve": [ 0.388, 4.74, 0.451, 32.35 ] + }, + { + "time": 0.5, + "value": 32.4, + "curve": [ 0.537, 32.44, 0.566, 6.43 ] + }, + { "time": 0.5667, "value": 2 }, + { "time": 1, "value": 4.09 } + ] + }, + "front-thigh": { + "translate": [ + { + "x": 17.15, + "y": -0.09, + "curve": [ 0.178, 17.14, 0.295, -4.26, 0.009, -0.09, 0.475, 0.02 ] + }, + { + "time": 0.5, + "x": -4.26, + "y": 0.02, + "curve": [ 0.705, -4.27, 0.848, 17.15, 0.525, 0.02, 0.975, -0.09 ] + }, + { "time": 1, "x": 17.15, "y": -0.09 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -17.71, + "y": -4.63, + "curve": [ 0.036, -19.81, 0.043, -20.86, 0.036, -4.63, 0.05, -7.03 ] + }, + { + "time": 0.1, + "x": -20.95, + "y": -7.06, + "curve": [ 0.162, -21.05, 0.4, 7.79, 0.2, -7.13, 0.4, -1.9 ] + }, + { + "time": 0.5, + "x": 7.79, + "y": -1.94, + "curve": [ 0.612, 7.69, 0.875, -10.49, 0.592, -1.97, 0.917, -3.25 ] + }, + { "time": 1, "x": -17.71, "y": -4.63 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 1, + "curve": [ 0.006, 1.2, 0.084, 2.88 ] + }, + { + "time": 0.1333, + "value": 2.88, + "curve": [ 0.205, 2.88, 0.284, -1.17 ] + }, + { + "time": 0.3667, + "value": -1.17, + "curve": [ 0.411, -1.17, 0.481, 0.57 ] + }, + { + "time": 0.5, + "value": 1, + "curve": [ 0.515, 1.33, 0.59, 2.83 ] + }, + { + "time": 0.6333, + "value": 2.85, + "curve": [ 0.683, 2.86, 0.796, -1.2 ] + }, + { + "time": 0.8667, + "value": -1.2, + "curve": [ 0.916, -1.2, 0.984, 0.62 ] + }, + { "time": 1, "value": 1 } + ] + }, + "torso3": { + "rotate": [ + { "value": -1.81 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -9.51, + "curve": [ 0.021, -13.32, 0.058, -19.4 ] + }, + { + "time": 0.1, + "value": -19.4, + "curve": [ 0.238, -19.69, 0.337, 7.78 ] + }, + { + "time": 0.3667, + "value": 16.2, + "curve": [ 0.399, 25.42, 0.497, 60.19 ] + }, + { + "time": 0.6, + "value": 60.26, + "curve": [ 0.719, 60.13, 0.845, 27.61 ] + }, + { + "time": 0.8667, + "value": 22.45, + "curve": [ 0.892, 16.38, 0.979, -3.27 ] + }, + { "time": 1, "value": -9.51 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 13.57, + "curve": [ 0.022, 9.71, 0.147, -3.78 ] + }, + { + "time": 0.3667, + "value": -3.69, + "curve": [ 0.457, -3.66, 0.479, 0.83 ] + }, + { + "time": 0.5, + "value": 4.05, + "curve": [ 0.513, 6.08, 0.635, 30.8 ] + }, + { + "time": 0.8, + "value": 30.92, + "curve": [ 0.974, 31, 0.98, 18.35 ] + }, + { "time": 1, "value": 13.57 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -28.72, + "curve": [ 0.024, -31.74, 0.176, -43.4 ] + }, + { + "time": 0.3667, + "value": -43.6, + "curve": [ 0.403, -43.65, 0.47, -40.15 ] + }, + { + "time": 0.5, + "value": -35.63, + "curve": [ 0.547, -28.59, 0.624, -4.57 ] + }, + { + "time": 0.7333, + "value": -4.59, + "curve": [ 0.891, -4.62, 0.954, -24.28 ] + }, + { "time": 1, "value": -28.48 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.034, 30.94, 0.068, 32.05 ] + }, + { + "time": 0.1, + "value": 31.88, + "curve": [ 0.194, 31.01, 0.336, -0.11 ] + }, + { + "time": 0.3667, + "value": -7.11, + "curve": [ 0.421, -19.73, 0.53, -46.21 ] + }, + { + "time": 0.6, + "value": -45.75, + "curve": [ 0.708, -45.03, 0.844, -13.56 ] + }, + { + "time": 0.8667, + "value": -6.48, + "curve": [ 0.909, 6.59, 0.958, 24.21 ] + }, + { "time": 1, "value": 28.28 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -2.79, + "curve": [ 0.074, -2.84, 0.121, 25.08 ] + }, + { + "time": 0.2333, + "value": 24.99, + "curve": [ 0.35, 24.89, 0.427, -2.86 ] + }, + { + "time": 0.5, + "value": -2.8, + "curve": [ 0.575, -2.73, 0.652, 24.5 ] + }, + { + "time": 0.7333, + "value": 24.55, + "curve": [ 0.828, 24.6, 0.932, -2.69 ] + }, + { "time": 1, "value": -2.79 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.01, + "curve": [ 0.106, -5.97, 0.151, 18.62 ] + }, + { + "time": 0.2333, + "value": 18.72, + "curve": [ 0.336, 18.7, 0.405, -11.37 ] + }, + { + "time": 0.5, + "value": -11.45, + "curve": [ 0.626, -11.46, 0.629, 18.94 ] + }, + { + "time": 0.7333, + "value": 18.92, + "curve": [ 0.833, 18.92, 0.913, -6.06 ] + }, + { "time": 1, "value": -6.01 } + ], + "translate": [ + { "x": 0.03, "y": 1.35 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.06, + "curve": [ 0.044, 11.16, 0.063, 11.49 ] + }, + { + "time": 0.1, + "value": 11.49, + "curve": [ 0.215, 11.49, 0.336, 2.92 ] + }, + { + "time": 0.3667, + "value": 0.84, + "curve": [ 0.416, -2.52, 0.498, -10.84 ] + }, + { + "time": 0.6, + "value": -10.83, + "curve": [ 0.762, -10.71, 0.845, -3.05 ] + }, + { + "time": 0.8667, + "value": -1.34, + "curve": [ 0.917, 2.54, 0.977, 8.81 ] + }, + { "time": 1, "value": 10.06 } + ] + }, + "gun": { + "rotate": [ + { + "value": -14.67, + "curve": [ 0.086, -14.67, 0.202, 8.31 ] + }, + { + "time": 0.2333, + "value": 12.14, + "curve": [ 0.279, 17.71, 0.391, 25.79 ] + }, + { + "time": 0.5, + "value": 25.77, + "curve": [ 0.631, 25.74, 0.694, 4.53 ] + }, + { + "time": 0.7333, + "value": -0.65, + "curve": [ 0.768, -5.21, 0.902, -14.4 ] + }, + { "time": 1, "value": -14.67 } + ] + }, + "front-leg-target": { + "translate": [ + { + "x": -2.83, + "y": -8.48, + "curve": [ 0.008, -2.83, 0.058, 0.09, 0.001, 4.97, 0.058, 6.68 ] + }, + { + "time": 0.0667, + "x": 0.09, + "y": 6.68, + "curve": [ 0.3, 0.09, 0.767, -2.83, 0.3, 6.68, 0.767, -8.48 ] + }, + { "time": 1, "x": -2.83, "y": -8.48 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.028, 1.24, 0.016, 3.46 ] + }, + { + "time": 0.1, + "value": 3.45, + "curve": [ 0.159, 3.45, 0.189, 0.23 ] + }, + { + "time": 0.2333, + "value": -2.29, + "curve": [ 0.265, -4.32, 0.305, -5.92 ] + }, + { + "time": 0.3667, + "value": -5.94, + "curve": [ 0.446, -5.96, 0.52, 3.41 ] + }, + { + "time": 0.6, + "value": 3.42, + "curve": [ 0.717, 3.42, 0.772, -5.93 ] + }, + { + "time": 0.8667, + "value": -5.97, + "curve": [ 0.933, -5.99, 0.982, -0.94 ] + }, + { "time": 1 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.067, 0, 0.159, -10.48 ] + }, + { + "time": 0.2333, + "value": -10.49, + "curve": [ 0.334, -10.5, 0.439, -0.09 ] + }, + { + "time": 0.5, + "value": -0.09, + "curve": [ 0.569, -0.09, 0.658, -10.75 ] + }, + { + "time": 0.7333, + "value": -10.7, + "curve": [ 0.833, -10.63, 0.947, 0 ] + }, + { "time": 1 } + ] + }, + "gun-tip": { + "rotate": [ + { "time": 0.2333, "value": 0.11 } + ] + }, + "muzzle-ring": { + "rotate": [ + { "time": 0.2333, "value": 0.11 } + ] + }, + "muzzle-ring2": { + "rotate": [ + { "time": 0.2667, "value": 0.11 } + ] + }, + "muzzle-ring3": { + "rotate": [ + { "time": 0.2667, "value": 0.11 } + ] + }, + "muzzle-ring4": { + "rotate": [ + { "time": 0.2667, "value": 0.11 } + ] + }, + "back-shoulder": { + "translate": [ + { + "x": -0.18, + "y": -4.49, + "curve": [ 0.133, -0.18, 0.333, 7.69, 0.133, -4.49, 0.333, 2.77 ] + }, + { + "time": 0.4667, + "x": 7.69, + "y": 2.77, + "curve": [ 0.6, 7.69, 0.858, -0.18, 0.6, 2.77, 0.858, -4.49 ] + }, + { "time": 1, "x": -0.18, "y": -4.49 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.46, + "y": 9.37, + "curve": [ 0.162, 1.41, 0.333, -1.66, 0.162, 9.37, 0.301, -7.23 ] + }, + { + "time": 0.5, + "x": -1.6, + "y": -7.27, + "curve": [ 0.735, -1.5, 0.847, 1.46, 0.723, -7.31, 0.838, 9.32 ] + }, + { "time": 1, "x": 1.46, "y": 9.37 } + ] + }, + "head-control": { + "translate": [ + { + "x": -6.46, + "y": -8.4, + "curve": [ 0.053, -5.31, 0.167, -3.64, 0.093, -8.4, 0.196, -3.81 ] + }, + { + "time": 0.2333, + "x": -3.64, + "y": -1.32, + "curve": [ 0.309, -3.64, 0.436, -5.84, 0.275, 1.43, 0.38, 10.3 ] + }, + { + "time": 0.5, + "x": -7.03, + "y": 10.29, + "curve": [ 0.538, -7.75, 0.66, -10.54, 0.598, 10.27, 0.694, 1.56 ] + }, + { + "time": 0.7333, + "x": -10.54, + "y": -1.26, + "curve": [ 0.797, -10.54, 0.933, -7.91, 0.768, -3.79, 0.875, -8.4 ] + }, + { "time": 1, "x": -6.46, "y": -8.4 } + ] + } + }, + "ik": { + "front-leg-ik": [ + { + "softness": 25.7, + "bendPositive": false, + "curve": [ 0.008, 1, 0.025, 1, 0.008, 25.7, 0.025, 9.9 ] + }, + { + "time": 0.0333, + "softness": 9.9, + "bendPositive": false, + "curve": [ 0.15, 1, 0.383, 1, 0.15, 9.9, 0.383, 43.2 ] + }, + { + "time": 0.5, + "softness": 43.2, + "bendPositive": false, + "curve": [ 0.625, 1, 0.875, 1, 0.625, 43.2, 0.846, 45.57 ] + }, + { "time": 1, "softness": 25.7, "bendPositive": false } + ], + "rear-leg-ik": [ + { "softness": 5, "bendPositive": false }, + { "time": 0.4333, "softness": 4.9, "bendPositive": false }, + { "time": 0.5, "softness": 28.81, "bendPositive": false }, + { "time": 0.6, "softness": 43.8, "bendPositive": false }, + { "time": 1, "softness": 5, "bendPositive": false } + ] + }, + "events": [ + { "name": "footstep" }, + { "time": 0.5, "name": "footstep" } + ] + } +} +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-pro.skel b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-pro.skel new file mode 100644 index 0000000..09e564b Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-pro.skel differ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-run.atlas b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-run.atlas new file mode 100644 index 0000000..7c0a3b9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-run.atlas @@ -0,0 +1,50 @@ +spineboy-run.png + size: 1177, 685 + filter: Linear, Linear + pma: true +spineboy-pro-run + index: 8 + bounds: 2, 369, 302, 314 + offsets: 12, 22, 316, 341 +spineboy-pro-run + index: 9 + bounds: 2, 42, 278, 325 + offsets: 30, 2, 316, 341 +spineboy-pro-run + index: 0 + bounds: 306, 438, 245, 320 + offsets: 67, 1, 316, 341 + rotate: 90 +spineboy-pro-run + index: 3 + bounds: 628, 441, 242, 319 + offsets: 12, 21, 316, 341 + rotate: 90 +spineboy-pro-run + index: 2 + bounds: 949, 377, 226, 306 + offsets: 34, 26, 316, 341 +spineboy-pro-run + index: 4 + bounds: 306, 196, 240, 319 + offsets: 3, 5, 316, 341 + rotate: 90 +spineboy-pro-run + index: 1 + bounds: 282, 2, 192, 318 + offsets: 69, 3, 316, 341 + rotate: 90 +spineboy-pro-run + index: 5 + bounds: 628, 198, 241, 316 + offsets: 8, 3, 316, 341 + rotate: 90 +spineboy-pro-run + index: 7 + bounds: 946, 79, 226, 296 + offsets: 37, 33, 316, 341 +spineboy-pro-run + index: 6 + bounds: 627, 2, 194, 315 + offsets: 68, 5, 316, 341 + rotate: 90 diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-run.png b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-run.png new file mode 100644 index 0000000..151454a Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy-run.png differ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy.atlas b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy.atlas new file mode 100644 index 0000000..eca542b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy.atlas @@ -0,0 +1,94 @@ +spineboy.png + size: 1024, 256 + filter: Linear, Linear + scale: 0.5 +crosshair + bounds: 352, 7, 45, 45 +eye-indifferent + bounds: 862, 105, 47, 45 +eye-surprised + bounds: 505, 79, 47, 45 +front-bracer + bounds: 826, 66, 29, 40 +front-fist-closed + bounds: 786, 65, 38, 41 +front-fist-open + bounds: 710, 51, 43, 44 + rotate: 90 +front-foot + bounds: 210, 6, 63, 35 +front-shin + bounds: 665, 128, 41, 92 + rotate: 90 +front-thigh + bounds: 2, 2, 23, 56 + rotate: 90 +front-upper-arm + bounds: 250, 205, 23, 49 +goggles + bounds: 665, 171, 131, 83 +gun + bounds: 798, 152, 105, 102 +head + bounds: 2, 27, 136, 149 +hoverboard-board + bounds: 2, 178, 246, 76 +hoverboard-thruster + bounds: 722, 96, 30, 32 + rotate: 90 +hoverglow-small + bounds: 275, 81, 137, 38 +mouth-grind + bounds: 614, 97, 47, 30 +mouth-oooo + bounds: 612, 65, 47, 30 +mouth-smile + bounds: 661, 64, 47, 30 +muzzle-glow + bounds: 382, 54, 25, 25 +muzzle-ring + bounds: 275, 54, 25, 105 + rotate: 90 +muzzle01 + bounds: 911, 95, 67, 40 + rotate: 90 +muzzle02 + bounds: 792, 108, 68, 42 +muzzle03 + bounds: 956, 171, 83, 53 + rotate: 90 +muzzle04 + bounds: 275, 7, 75, 45 +muzzle05 + bounds: 140, 3, 68, 38 +neck + bounds: 250, 182, 18, 21 +portal-bg + bounds: 140, 43, 133, 133 +portal-flare1 + bounds: 554, 65, 56, 30 +portal-flare2 + bounds: 759, 112, 57, 31 + rotate: 90 +portal-flare3 + bounds: 554, 97, 58, 30 +portal-shade + bounds: 275, 121, 133, 133 +portal-streaks1 + bounds: 410, 126, 126, 128 +portal-streaks2 + bounds: 538, 129, 125, 125 +rear-bracer + bounds: 857, 67, 28, 36 +rear-foot + bounds: 663, 96, 57, 30 +rear-shin + bounds: 414, 86, 38, 89 + rotate: 90 +rear-thigh + bounds: 756, 63, 28, 47 +rear-upper-arm + bounds: 60, 5, 20, 44 + rotate: 90 +torso + bounds: 905, 164, 49, 90 diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy.png b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy.png new file mode 100644 index 0000000..0ea9737 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/export/spineboy.png differ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/license.txt b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/license.txt new file mode 100644 index 0000000..ba9fe3d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/license.txt @@ -0,0 +1,8 @@ +Copyright (c) 2013, Esoteric Software LLC + +The images in this project may be redistributed as long as they are accompanied +by this license file. The images may not be used for commercial use of any +kind. + +The project file is released into the public domain. It may be used as the basis +for derivative work. \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/spineboy-ess.spine b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/spineboy-ess.spine new file mode 100644 index 0000000..1594eac Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/spineboy-ess.spine differ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/spineboy-pro.spine b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/spineboy-pro.spine new file mode 100644 index 0000000..63190b5 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.2/examples/spineboy/spineboy-pro.spine differ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/flags.cmake b/DateToSpine/third_party/spine-runtimes/4.2/flags.cmake new file mode 100644 index 0000000..2ca71ca --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/flags.cmake @@ -0,0 +1,19 @@ +option(SPINE_SANITIZE "Build with sanitization" OFF) +option(SPINE_SET_COMPILER_FLAGS "Set compiler flags" ON) + +if (NOT SPINE_SET_COMPILER_FLAGS) + return() +endif() + +if(MSVC) + message("MSCV detected") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS") +else() + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic -Wno-unused-parameter -std=c99") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wnon-virtual-dtor -pedantic -Wno-unused-parameter -std=c++11 -fno-exceptions -fno-rtti") + if (${SPINE_SANITIZE}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize=undefined") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize=undefined") + endif() +endif() diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/CMakeLists.txt b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/CMakeLists.txt new file mode 100644 index 0000000..9829b42 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.10) +project(spine-cpp) + +include(${CMAKE_CURRENT_LIST_DIR}/../flags.cmake) + +include_directories(include) +file(GLOB INCLUDES "spine-cpp/include/**/*.h") +file(GLOB SOURCES "spine-cpp/src/**/*.cpp") + +add_library(spine-cpp STATIC ${SOURCES} ${INCLUDES}) +target_include_directories(spine-cpp PUBLIC spine-cpp/include) + +add_library(spine-cpp-lite STATIC ${SOURCES} ${INCLUDES} spine-cpp-lite/spine-cpp-lite.cpp) +target_include_directories(spine-cpp-lite PUBLIC spine-cpp/include spine-cpp-lite) + +# Install target +install(TARGETS spine-cpp EXPORT spine-cpp_TARGETS DESTINATION dist/lib) +install(FILES ${INCLUDES} DESTINATION dist/include) + +# Export target +export( + EXPORT spine-cpp_TARGETS + FILE ${CMAKE_CURRENT_BINARY_DIR}/spine-cppTargets.cmake + NAMESPACE "Spine::") \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/LICENSE b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/LICENSE new file mode 100644 index 0000000..517ff9f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/LICENSE @@ -0,0 +1,26 @@ +Spine Runtimes License Agreement +Last updated April 5, 2025. Replaces all prior versions. + +Copyright (c) 2013-2025, Esoteric Software LLC + +Integration of the Spine Runtimes into software or otherwise creating +derivative works of the Spine Runtimes is permitted under the terms and +conditions of Section 2 of the Spine Editor License Agreement: +https://esotericsoftware.com/spine-editor-license + +Otherwise, it is permitted to integrate the Spine Runtimes into software +or otherwise create derivative works of the Spine Runtimes (collectively, +"Products"), provided that each user of the Products must obtain their own +Spine Editor license and redistribution of the Products in any form must +include this license and copyright notice. + +THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, +BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/README.md b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/README.md new file mode 100644 index 0000000..8a512f6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/README.md @@ -0,0 +1,56 @@ +# spine-cpp + +The spine-cpp runtime provides basic functionality to load and manipulate [spine](http://esotericsoftware.com) skeletal animation data using C++. It does not perform rendering but can be extended to enable spine animations for other projects that utilize C++. + +## Licensing + +You are welcome to evaluate the Spine Runtimes and the examples we provide in this repository free of charge. + +You can integrate the Spine Runtimes into your software free of charge, but users of your software must have their own [Spine license](https://esotericsoftware.com/spine-purchase). Please make your users aware of this requirement! This option is often chosen by those making development tools, such as an SDK, game toolkit, or software library. + +In order to distribute your software containing the Spine Runtimes to others that don't have a Spine license, you need a [Spine license](https://esotericsoftware.com/spine-purchase) at the time of integration. Then you can distribute your software containing the Spine Runtimes however you like, provided others don't modify it or use it to create new software. If others want to do that, they'll need their own Spine license. + +For the official legal terms governing the Spine Runtimes, please read the [Spine Runtimes License Agreement](http://esotericsoftware.com/spine-runtimes-license) and Section 2 of the [Spine Editor License Agreement](http://esotericsoftware.com/spine-editor-license#s2). + +## Spine version + +spine-cpp works with data exported from spine 4.2.xx. + +spine-cpp supports all spine features. + +## Setup + +1. Download the spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it as a zip via the download button above. +2. Copy the contents of the `spine-cpp/spine-cpp/src` and `spine-cpp/spine-cpp/include` directories into your project. Be sure your header search is configured to find the contents of the `spine-cpp/spine-cpp/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files. + +## Usage + +### [Please see the spine-cpp guide for full documentation](http://esotericsoftware.com/spine-cpp) + +## Extension + +Extending spine-cpp requires implementing both the `SpineExtension` class and the TextureLoader class: + +``` +#include +void spine::SpineExtension *spine::getDefaultExtension() { + return new spine::DefaultExtension(); +} + +class MyTextureLoader : public spine::TextureLoader +{ + virtual void load(spine::AtlasPage& page, const spine::String& path) { + void* texture = ... load the texture based on path ... + page->setRendererObject(texture); // use the texture later in your rendering code + } + + virtual void unload(void* texture) { // TODO } +}; +``` + +## Runtimes extending spine-cpp +- [spine-glfw](../spine-glfw) +- [spine-sdl](../spine-sdl) +- [spine-sfml](../spine-sfml/cpp) +- [spine-cocos2dx](../spine-cocos2dx) +- [spine-ue](../spine-ue) diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp-lite/module.modulemap b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp-lite/module.modulemap new file mode 100644 index 0000000..6ade2d5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp-lite/module.modulemap @@ -0,0 +1,4 @@ +module SpineCppLite { + header "spine-cpp-lite.h" + export * +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp-lite/spine-cpp-lite-codegen.py b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp-lite/spine-cpp-lite-codegen.py new file mode 100644 index 0000000..46d3e4e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp-lite/spine-cpp-lite-codegen.py @@ -0,0 +1,610 @@ +import re +import os + +script_directory = os.path.dirname(os.path.abspath(__file__)) +input_path = os.path.join(script_directory, 'spine-cpp-lite.h') + +with open(input_path, 'r') as file: + file_contents = file.read() + +supported_types_to_swift_types = { + 'void *': 'UnsafeMutableRawPointer', + 'const utf8 *': 'String?', + 'uint64_t': 'UInt64', + 'float *': 'Float?', + 'float': 'Float', + 'int32_t': 'Int32', + 'utf8 *': 'String?', + 'int32_t *': 'Int32?', + 'uint16_t *': 'UInt16', + 'spine_bool': 'Bool' +} + +def read_spine_types(data): + types_start = data.find('// @start: opaque_types') + len('// @start: opaque_types') + types_end = data.find('// @end: paque_types') + types_section = data[types_start:types_end] + return re.findall(r'SPINE_OPAQUE_TYPE\(([^)]+)\)', types_section) + +def read_spine_function_declarations(data): + declarations_start = data.find('// @start: function_declarations') + len('// @start: function_declarations') + declarations_end = data.find('// @end: function_declarations') + declarations_section = data[declarations_start:declarations_end] + lines = declarations_section.split('\n') + + filtered_lines = [] + ignore_next = False + next_returns_optional = False + for line in lines: + if ignore_next: + ignore_next = False + continue + + line = line.strip() + + if next_returns_optional: + next_returns_optional = False + line = line + "?" + + if not line.strip().startswith('//') and line.strip() != '': + filtered_lines.append(line) + + if line.startswith('//') and '@ignore' in line: + ignore_next = True + elif line.startswith('//') and '@optional' in line: + next_returns_optional = True + + function_declaration = [ + line.replace('SPINE_CPP_LITE_EXPORT', '').strip() + for line in filtered_lines + ] + + return function_declaration + +def read_spine_enums(data): + enums_start = data.find('// @start: enums') + len('// @start: enums') + enums_end = data.find('// @end: enums') + enums_section = data[enums_start:enums_end] + return re.findall(r"typedef enum (\w+) \{", enums_section) + +class SpineObject: + def __init__(self, name, functions): + self.name = name + self.functions = functions + self.function_names = {function.name for function in functions} + self.var_name = "wrappee" + + def __str__(self): + return f"SpineObject: name: {self.name}, functions: {self.functions}" + +class SpineFunction: + def __init__(self, return_type, name, parameters, returns_optional): + self.return_type = return_type + self.name = name + self.parameters = parameters + self.returns_optional = returns_optional + + def isReturningSpineClass(self): + return self.return_type.startswith("spine_") and self.return_type != "spine_bool" and self.return_type not in enums + + def __str__(self): + return f"SpineFunction(return_type: {self.return_type}, name: {self.name}, parameters: {self.parameters}, returns_optional: {self.returns_optional})" + + def __repr__(self): + return self.__str__() + +class SpineParam: + def __init__(self, type, name): + self.type = type + self.name = name + + def isSpineClass(self): + return self.type.startswith("spine_") and self.type != "spine_bool" and self.type not in enums + + def __str__(self): + return f"SpineParam(type: {self.type}, name: {self.name})" + + def __repr__(self): + return self.__str__() + +def parse_function_declaration(declaration): + returns_optional = declaration.endswith("?") + + # Strip semicolon and extra whitespace + declaration = declaration.strip('?').strip(';').strip() + + # Use regex to split the declaration into parts + # Regex explanation: + # ^([\w\s\*]+?)\s+ - Capture the return type, possibly including spaces and asterisks (non-greedy) + # ([\w]+) - Capture the function name (alphanumeric and underscores) + # \((.*)\) - Capture the argument list in entirety + match = re.match(r'^(\S.+?\s*\*?\s*)([\w]+)\s*\((.*)\)$', declaration) + + if not match: + return "Invalid function declaration" + + return_type, function_name, params = match.groups() + + params = params.strip() + parameters = [] + if params: + # Splitting each argument on comma + param_list = params.split(',') + for param in param_list: + + param_parts = [] + if '*' in param: # Split at the pointer and add it as a suffix to the type + param_parts = param.rsplit('*', 1) + param_parts[0] = param_parts[0] + '*' + else: # Assuming type and name are separated by space and taking the last space as the separator + param_parts = param.rsplit(' ', 1) + param_type, param_name = param_parts + spine_param = SpineParam(type = param_type.strip(), name = param_name.strip()) + parameters.append(spine_param) + + return SpineFunction( + return_type = return_type.strip(), + name = function_name.strip(), + parameters = parameters, + returns_optional = returns_optional + ) + +types = read_spine_types(file_contents) +function_declarations = read_spine_function_declarations(file_contents) +enums = read_spine_enums(file_contents) + +sorted_types = sorted(types, key=len, reverse=True) # Sorted by legth descending so we can match longest prefix. +spine_functions = [ + parse_function_declaration(function_declaration) + for function_declaration in function_declarations +] + +objects = [] + +for type in sorted_types: + object_functions = [] + + hits = set() ## Keep track of hits and remove them for next object + + for function_declaration in function_declarations: + spine_function = parse_function_declaration(function_declaration) + if spine_function.name.startswith(type): + hits.add(function_declaration); + object_functions.append(spine_function); + + object = SpineObject(name = type, functions = object_functions); + objects.append(object) + + function_declarations = [item for item in function_declarations if item not in hits] + +def snake_to_camel(snake_str): + # Split the string by underscore + parts = snake_str.split('_') + # Return the first part lowercased and concatenate capitalized subsequent parts + return parts[0] + ''.join(word.capitalize() for word in parts[1:]) + +def snake_to_title(snake_str): + # Split the string at underscores + words = snake_str.split('_') + # Capitalize the first letter of each word + words = [word.capitalize() for word in words] + # Join the words into a single string without any separator + title_str = ''.join(words) + return title_str + +inset = " " + +class SwiftTypeWriter: + def __init__(self, type): + self.type = type + + def write(self): + parameter_type = supported_types_to_swift_types.get(self.type) + if parameter_type is None: + parameter_type = snake_to_title(self.type.replace("spine_", "")) + + if parameter_type.endswith(" *"): + parameter_type = f"{parameter_type[:-2]}" + + return parameter_type + +class SwiftParamWriter: + def __init__(self, param): + self.param = param + + def write(self): + type = SwiftTypeWriter(type = self.param.type).write() + return f"{snake_to_camel(self.param.name)}: {type}" + +class SwiftFunctionBodyWriter: + def __init__(self, spine_object, spine_function, is_setter, is_getter_optional): + self.spine_object = spine_object + self.spine_function = spine_function + self.is_setter = is_setter + self.is_getter_optional = is_getter_optional + + def write(self): + body = "" + + num_function_name = self.spine_function.name.replace("get_", "get_num_") + swift_return_type_is_array = "get_" in self.spine_function.name and num_function_name in self.spine_object.function_names + + spine_params = self.spine_function.parameters; + + body = "" + if "dispose" in self.spine_function.name: + body += self.write_dispose_call() + + function_call = self.write_c_function_call(spine_params) + + if swift_return_type_is_array: + body += self.write_array_call(num_function_name, function_call) + else: + if not self.spine_function.return_type == "void": + body += "return " + + if self.spine_function.isReturningSpineClass(): + + function_prefix = f"{self.spine_object.name}_" + function_name = self.spine_function.name.replace(function_prefix, "", 1) + + if "find_" in function_name or self.spine_function.returns_optional: + body += function_call + body += ".flatMap { .init($0" + if self.spine_function.return_type in enums: + body += ".rawValue" + body += ") }" + else: + body += ".init(" + body += function_call + if self.spine_function.return_type in enums: + body += ".rawValue" + body += ")" + + else: + body += function_call + + if self.spine_function.return_type == "const utf8 *" or self.spine_function.return_type == "utf8 *": + body += ".flatMap { String(cString: $0) }" + if self.spine_function.return_type == "int32_t *" or self.spine_function.return_type == "float *": + body += ".flatMap { $0.pointee }" + + return body + + def write_c_function_call(self, spine_params): + function_call = "" + function_call += f"{self.spine_function.name}" + function_call += "(" + + # Replace name with ivar name + spine_params_with_ivar_name = spine_params + if spine_params_with_ivar_name and spine_params_with_ivar_name[0].type == self.spine_object.name: + spine_params_with_ivar_name[0].name = self.spine_object.var_name + + if self.is_setter and len(spine_params_with_ivar_name) == 2: + spine_params_with_ivar_name[1].name = "newValue" + if self.is_getter_optional: + spine_params_with_ivar_name[1].name += "?" + + swift_param_names = [] + for idx, spine_param in enumerate(spine_params_with_ivar_name): + if spine_param.isSpineClass() and idx > 0: + swift_param_names.append(f"{spine_param.name}.wrappee") + elif spine_param.type == "spine_bool": + swift_param_names.append(f"{spine_param.name} ? -1 : 0") + else: + swift_param_names.append(spine_param.name) + + + function_call += ", ".join(swift_param_names) + function_call += ")" + + if self.spine_function.return_type == "spine_bool": + function_call += " != 0" + + return function_call + + def write_array_spine_class(self, num_function_name, function_call): + array_call = f"let ptr = {function_call}" + array_call += "\n" + array_call += inset + inset + array_call += "guard let validPtr = ptr else { return [] }" + array_call += "\n" + array_call += inset + inset + array_call += f"let num = Int({num_function_name}({self.spine_object.var_name}))" + array_call += "\n" + array_call += inset + inset + array_call += "let buffer = UnsafeBufferPointer(start: validPtr, count: num)" + array_call += "\n" + array_call += inset + inset + array_call += "return buffer.compactMap {" + array_call += "\n" + array_call += inset + inset + inset + array_call += "$0.flatMap { .init($0) }" + array_call += "\n" + array_call += inset + inset + array_call += "}" + return array_call + + def write_array_call(self, num_function_name, function_call): + if self.spine_function.isReturningSpineClass(): + return self.write_array_spine_class(num_function_name, function_call) + array_call = f"let ptr = {function_call}" + array_call += "\n" + array_call += inset + inset + array_call += "guard let validPtr = ptr else { return [] }" + array_call += "\n" + array_call += inset + inset + array_call += f"let num = Int({num_function_name}({self.spine_object.var_name}))" + array_call += "\n" + array_call += inset + inset + + array_call += "let buffer = UnsafeBufferPointer(start: validPtr, count: num)" + array_call += "\n" + array_call += inset + inset + array_call += "return Array(buffer)" + return array_call + + def write_dispose_call(self): + dispose_body = "if disposed { return }" + dispose_body += "\n" + dispose_body += inset + inset + dispose_body += "disposed = true" + dispose_body += "\n" + dispose_body += inset + inset + return dispose_body + +class SwiftFunctionWriter: + def __init__(self, spine_object, spine_function, spine_setter_function): + self.spine_object = spine_object + self.spine_function = spine_function + self.spine_setter_function = spine_setter_function + + def write(self): + function_prefix = f"{self.spine_object.name}_" + function_name = self.spine_function.name.replace(function_prefix, "", 1) + is_getter = (function_name.startswith("get_") or function_name.startswith("is_")) and len(self.spine_function.parameters) < 2 + + num_function_name = self.spine_function.name.replace("get_", "get_num_") + swift_return_type_is_array = "get_" in self.spine_function.name and num_function_name in self.spine_object.function_names + + swift_return_type_writer = SwiftTypeWriter(type = self.spine_function.return_type) + swift_return_type = swift_return_type_writer.write() + if swift_return_type_is_array: + swift_return_type = f"[{swift_return_type}]" + + function_string = inset + + if is_getter: + + function_string += self.write_computed_property_signature(function_name, swift_return_type) + if self.spine_setter_function: + function_string += " {\n" + function_string += inset + inset + function_string += "get" + + else: + function_string += self.write_method_signature(function_name, swift_return_type) + + function_string += " {" + function_string += "\n" + + function_string += inset + inset + + if self.spine_setter_function: + function_string += inset + + function_string += SwiftFunctionBodyWriter(spine_object = self.spine_object, spine_function = self.spine_function, is_setter=False, is_getter_optional=False).write() + + if self.spine_setter_function: + function_string += "\n" + function_string += inset + inset + "}" + function_string += "\n" + function_string += inset + inset + "set {" + function_string += "\n" + function_string += inset + inset + inset + function_string += SwiftFunctionBodyWriter(spine_object = self.spine_object, spine_function = self.spine_setter_function, is_setter=True, is_getter_optional=self.spine_function.returns_optional).write() + function_string += "\n" + function_string += inset + inset + "}" + + function_string += "\n" + function_string += inset + "}" + function_string += "\n" + + return function_string + + def write_computed_property_signature(self, function_name, swift_return_type): + property_name = snake_to_camel(function_name.replace("get_", "")) + property_string = f"public var {property_name}: {swift_return_type}" + if self.spine_function.returns_optional: + property_string += "?" + return property_string + + def write_method_signature(self, function_name, swift_return_type): + + function_string = "" + + if not self.spine_function.return_type == "void": + function_string += "@discardableResult" + function_string += "\n" + function_string += inset + + function_string += f"public func {snake_to_camel(function_name)}" + + function_string += "(" + + spine_params = self.spine_function.parameters; + + # Filter out ivar + if spine_params and spine_params[0].type == self.spine_object.name: + spine_params_without_ivar = spine_params[1:] + else: + function_string = function_string.replace("public func ", "public static func ") + spine_params_without_ivar = spine_params + + swift_params = [ + SwiftParamWriter(param = spine_param).write() + for spine_param in spine_params_without_ivar + ] + + function_string += ", ".join(swift_params) + function_string += ")" + + if not self.spine_function.return_type == "void": + function_string += f" -> {swift_return_type}" + + if "find_" in function_name or self.spine_function.returns_optional: + function_string += "?" + + return function_string + +class SwiftObjectWriter: + def __init__(self, spine_object): + self.spine_object = spine_object + + def write(self): + ivar_type = self.spine_object.name + ivar_name = self.spine_object.var_name + + class_name = snake_to_title(self.spine_object.name.replace("spine_", "")) + + object_string = f"@objc(Spine{class_name})" + object_string += "\n" + object_string += "@objcMembers" + object_string += "\n" + object_string += f"public final class {class_name}: NSObject" + object_string += " {" + object_string += "\n" + object_string += "\n" + object_string += inset + object_string += f"internal let {ivar_name}: {ivar_type}" + object_string += "\n" + + if any("dispose" in function_name for function_name in self.spine_object.function_names): + object_string += inset + object_string += f"internal var disposed = false" + object_string += "\n" + + object_string += "\n" + + object_string += inset + object_string += f"internal init(_ {ivar_name}: {ivar_type})" + object_string += " {" + object_string += "\n" + object_string += inset + inset + object_string += f"self.{ivar_name} = {ivar_name}" + object_string += "\n" + object_string += inset + inset + object_string += "super.init()" + object_string += "\n" + object_string += inset + object_string += "}" + object_string += "\n" + object_string += "\n" + + object_string += inset + object_string += "public override func isEqual(_ object: Any?) -> Bool" + object_string += " {" + object_string += "\n" + object_string += inset + inset + object_string += f"guard let other = object as? {class_name} else {{ return false }}" + object_string += "\n" + object_string += inset + inset + object_string += f"return self.{ivar_name} == other.{ivar_name}" + object_string += "\n" + object_string += inset + object_string += "}" + object_string += "\n" + object_string += "\n" + + object_string += inset + object_string += "public override var hash: Int" + object_string += " {" + object_string += "\n" + object_string += inset + inset + object_string += "var hasher = Hasher()" + object_string += "\n" + object_string += inset + inset + object_string += f"hasher.combine(self.{ivar_name})" + object_string += "\n" + object_string += inset + inset + object_string += "return hasher.finalize()" + object_string += "\n" + object_string += inset + object_string += "}" + object_string += "\n" + object_string += "\n" + + filtered_spine_functions = [spine_function for spine_function in self.spine_object.functions if not "_get_num_" in spine_function.name] + + spine_functions_by_name = {} + getter_names = [] + setter_names = [] + method_names = [] + + for spine_function in filtered_spine_functions: + spine_functions_by_name[spine_function.name] = spine_function + + if ("_get_" in spine_function.name or "_is_" in spine_function.name) and len(spine_function.parameters) == 1: + getter_names.append(spine_function.name) + elif "_set_" in spine_function.name and len(spine_function.parameters) == 2: + setter_names.append(spine_function.name) + else: + method_names.append(spine_function.name) + + get_set_pairs = [] + + for setter_name in setter_names: + getter_name_get = setter_name.replace("_set_", "_get_") + getter_name_is = setter_name.replace("_set_", "_is_") + if getter_name_get in getter_names: + getter_names.remove(getter_name_get) + get_set_pairs.append((getter_name_get, setter_name)) + elif getter_name_is in getter_names: + getter_names.remove(getter_name_is) + get_set_pairs.append((getter_name_is, setter_name)) + else: + method_names.append(setter_name) # Coul not find getter by name. Move to methods + + # print(get_set_pairs) + + for getter_name in getter_names: + spine_function = spine_functions_by_name[getter_name] + object_string += SwiftFunctionWriter(spine_object = self.spine_object, spine_function = spine_function, spine_setter_function=None).write() + object_string += "\n" + + for get_set_pair in get_set_pairs: + getter_function = spine_functions_by_name[get_set_pair[0]] + setter_function = spine_functions_by_name[get_set_pair[1]] + object_string += SwiftFunctionWriter(spine_object = self.spine_object, spine_function = getter_function, spine_setter_function=setter_function).write() + object_string += "\n" + + for method_name in method_names: + spine_function = spine_functions_by_name[method_name] + object_string += SwiftFunctionWriter(spine_object = self.spine_object, spine_function = spine_function, spine_setter_function=None).write() + object_string += "\n" + + object_string += "}" + + return object_string + +class SwiftEnumWriter: + def __init__(self, spine_enum): + self.spine_enum = spine_enum + + def write(self): + # TODO: Consider leaving spine prefix (objc) or map whole c enum to swift/objc compatible enum + return f"public typealias {snake_to_title(self.spine_enum.replace("spine_", ""))} = {self.spine_enum}" + +print("import Foundation") +print("import SpineCppLite") +print("") + +for enum in enums: + print(SwiftEnumWriter(spine_enum=enum).write()) + +print("") + +for object in objects: + print(SwiftObjectWriter(spine_object = object).write()) + print("") diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp-lite/spine-cpp-lite.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp-lite/spine-cpp-lite.cpp new file mode 100644 index 0000000..6d60d52 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp-lite/spine-cpp-lite.cpp @@ -0,0 +1,4843 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include "spine-cpp-lite.h" +#include +#include +#include + +using namespace spine; + +struct AnimationStateEvent { + EventType type; + TrackEntry *entry; + Event *event; + AnimationStateEvent(EventType type, TrackEntry *entry, Event *event) : type(type), entry(entry), event(event){}; +}; + +struct EventListener : public AnimationStateListenerObject { + Vector events; + + void callback(AnimationState *state, EventType type, TrackEntry *entry, Event *event) { + events.add(AnimationStateEvent(type, entry, event)); + SP_UNUSED(state); + } +}; + +typedef struct _spine_atlas { + void *atlas; + utf8 **imagePaths; + int32_t numImagePaths; + utf8 *error; +} _spine_atlas; + +typedef struct _spine_skeleton_data_result { + spine_skeleton_data skeletonData; + utf8 *error; +} _spine_skeleton_data_result; + +typedef struct _spine_bounds { + float x, y, width, height; +} _spine_bounds; + +typedef struct _spine_vector { + float x, y; +} _spine_vector; + +typedef struct _spine_skeleton_drawable : public SpineObject { + spine_skeleton skeleton; + spine_animation_state animationState; + spine_animation_state_data animationStateData; + spine_animation_state_events animationStateEvents; + SkeletonRenderer *renderer; +} _spine_skeleton_drawable; + +typedef struct _spine_skin_entry { + int32_t slotIndex; + utf8 *name; + spine_attachment attachment; +} _spine_skin_entry; + +typedef struct _spine_skin_entries { + int32_t numEntries; + _spine_skin_entry *entries; +} _spine_skin_entries; + +static Color NULL_COLOR(0, 0, 0, 0); + +static SpineExtension *defaultExtension = nullptr; +static DebugExtension *debugExtension = nullptr; + +static void initExtensions() { + if (defaultExtension == nullptr) { + defaultExtension = new DefaultSpineExtension(); + debugExtension = new DebugExtension(defaultExtension); + } +} + +spine::SpineExtension *spine::getDefaultExtension() { + initExtensions(); + return defaultExtension; +} + +void spine_enable_debug_extension(spine_bool enable) { + initExtensions(); + SpineExtension::setInstance(enable ? debugExtension : defaultExtension); +} + +int32_t spine_major_version() { + return SPINE_MAJOR_VERSION; +} + +int32_t spine_minor_version() { + return SPINE_MINOR_VERSION; +} + +void spine_report_leaks() { + initExtensions(); + debugExtension->reportLeaks(); + fflush(stdout); +} + +// Color + +float spine_color_get_r(spine_color color) { + if (!color) return 0; + return ((Color *) color)->r; +} + +float spine_color_get_g(spine_color color) { + if (!color) return 0; + return ((Color *) color)->g; +} + +float spine_color_get_b(spine_color color) { + if (!color) return 0; + return ((Color *) color)->b; +} + +float spine_color_get_a(spine_color color) { + if (!color) return 0; + return ((Color *) color)->a; +} + +// Bounds + +float spine_bounds_get_x(spine_bounds bounds) { + if (!bounds) return 0; + return ((_spine_bounds *) bounds)->x; +} + +float spine_bounds_get_y(spine_bounds bounds) { + if (!bounds) return 0; + return ((_spine_bounds *) bounds)->y; +} + +float spine_bounds_get_width(spine_bounds bounds) { + if (!bounds) return 0; + return ((_spine_bounds *) bounds)->width; +} + +float spine_bounds_get_height(spine_bounds bounds) { + if (!bounds) return 0; + return ((_spine_bounds *) bounds)->height; +} + +// Vector +float spine_vector_get_x(spine_vector vector) { + if (!vector) return 0; + return ((_spine_vector *) vector)->x; +} + +float spine_vector_get_y(spine_vector vector) { + if (!vector) return 0; + return ((_spine_vector *) vector)->y; +} + +// Atlas + +class LiteTextureLoad : public TextureLoader { + void load(AtlasPage &page, const String &path) { + page.texture = (void *) (intptr_t) page.index; + } + + void unload(void *texture) { + } +}; +LiteTextureLoad liteLoader; + +spine_atlas spine_atlas_load(const utf8 *atlasData) { + if (!atlasData) return nullptr; + int32_t length = (int32_t) strlen(atlasData); + auto atlas = new (__FILE__, __LINE__) Atlas(atlasData, length, "", &liteLoader, true); + _spine_atlas *result = SpineExtension::calloc<_spine_atlas>(1, __FILE__, __LINE__); + result->atlas = atlas; + result->numImagePaths = (int32_t) atlas->getPages().size(); + result->imagePaths = SpineExtension::calloc(result->numImagePaths, __FILE__, __LINE__); + for (int i = 0; i < result->numImagePaths; i++) { + result->imagePaths[i] = (utf8 *) strdup(atlas->getPages()[i]->texturePath.buffer()); + } + return (spine_atlas) result; +} + +class CallbackTextureLoad : public TextureLoader { + spine_texture_loader_load_func loadCb; + spine_texture_loader_unload_func unloadCb; + +public: + CallbackTextureLoad() : loadCb(nullptr), unloadCb(nullptr) {} + + void setCallbacks(spine_texture_loader_load_func load, spine_texture_loader_unload_func unload) { + loadCb = load; + unloadCb = unload; + } + + void load(AtlasPage &page, const String &path) { + page.texture = this->loadCb(path.buffer()); + } + + void unload(void *texture) { + this->unloadCb(texture); + } +}; + +CallbackTextureLoad callbackLoader; + +spine_atlas spine_atlas_load_callback(const utf8 *atlasData, const utf8 *atlasDir, spine_texture_loader_load_func load, spine_texture_loader_unload_func unload) { + if (!atlasData) return nullptr; + int32_t length = (int32_t) strlen(atlasData); + callbackLoader.setCallbacks(load, unload); + auto atlas = new (__FILE__, __LINE__) Atlas(atlasData, length, (const char *) atlasDir, &callbackLoader, true); + _spine_atlas *result = SpineExtension::calloc<_spine_atlas>(1, __FILE__, __LINE__); + result->atlas = atlas; + result->numImagePaths = (int32_t) atlas->getPages().size(); + result->imagePaths = SpineExtension::calloc(result->numImagePaths, __FILE__, __LINE__); + for (int i = 0; i < result->numImagePaths; i++) { + result->imagePaths[i] = (utf8 *) strdup(atlas->getPages()[i]->texturePath.buffer()); + } + return (spine_atlas) result; +} + +int32_t spine_atlas_get_num_image_paths(spine_atlas atlas) { + if (!atlas) return 0; + return ((_spine_atlas *) atlas)->numImagePaths; +} + +spine_bool spine_atlas_is_pma(spine_atlas atlas) { + if (!atlas) return 0; + Atlas *_atlas = static_cast(((_spine_atlas *) atlas)->atlas); + if (_atlas->getPages().size() > 0) { + return _atlas->getPages()[0]->pma; + } else { + return 0; + } +} + +utf8 *spine_atlas_get_image_path(spine_atlas atlas, int32_t index) { + if (!atlas) return nullptr; + return ((_spine_atlas *) atlas)->imagePaths[index]; +} + +utf8 *spine_atlas_get_error(spine_atlas atlas) { + if (!atlas) return nullptr; + return ((_spine_atlas *) atlas)->error; +} + +void spine_atlas_dispose(spine_atlas atlas) { + if (!atlas) return; + _spine_atlas *_atlas = (_spine_atlas *) atlas; + if (_atlas->atlas) delete (Atlas *) _atlas->atlas; + if (_atlas->error) free(_atlas->error); + for (int i = 0; i < _atlas->numImagePaths; i++) { + free(_atlas->imagePaths[i]); + } + SpineExtension::free(_atlas->imagePaths, __FILE__, __LINE__); + SpineExtension::free(_atlas, __FILE__, __LINE__); +} + +// SkeletonData + +spine_skeleton_data_result spine_skeleton_data_load_json(spine_atlas atlas, const utf8 *skeletonData) { + _spine_skeleton_data_result *result = SpineExtension::calloc<_spine_skeleton_data_result>(1, __FILE__, __LINE__); + _spine_atlas *_atlas = (_spine_atlas *) atlas; + Bone::setYDown(true); + if (!_atlas) return (spine_skeleton_data_result) result; + if (!_atlas->atlas) return (spine_skeleton_data_result) result; + if (!skeletonData) return (spine_skeleton_data_result) result; + SkeletonJson json((Atlas *) _atlas->atlas); + SkeletonData *data = json.readSkeletonData(skeletonData); + result->skeletonData = (spine_skeleton_data) data; + if (!json.getError().isEmpty()) { + result->error = (utf8 *) strdup(json.getError().buffer()); + } + return (spine_skeleton_data_result) result; +} + +spine_skeleton_data_result spine_skeleton_data_load_binary(spine_atlas atlas, const uint8_t *skeletonData, int32_t length) { + _spine_skeleton_data_result *result = SpineExtension::calloc<_spine_skeleton_data_result>(1, __FILE__, __LINE__); + _spine_atlas *_atlas = (_spine_atlas *) atlas; + Bone::setYDown(true); + if (!_atlas) return (spine_skeleton_data_result) result; + if (!_atlas->atlas) return (spine_skeleton_data_result) result; + if (!skeletonData) return (spine_skeleton_data_result) result; + if (length <= 0) return (spine_skeleton_data_result) result; + SkeletonBinary binary((Atlas *) _atlas->atlas); + SkeletonData *data = binary.readSkeletonData(skeletonData, length); + result->skeletonData = (spine_skeleton_data) data; + if (!binary.getError().isEmpty()) { + result->error = (utf8 *) strdup(binary.getError().buffer()); + } + return (spine_skeleton_data_result) result; +} + +utf8 *spine_skeleton_data_result_get_error(spine_skeleton_data_result result) { + if (!result) return nullptr; + return ((_spine_skeleton_data_result *) result)->error; +} +spine_skeleton_data spine_skeleton_data_result_get_data(spine_skeleton_data_result result) { + if (!result) return nullptr; + return ((_spine_skeleton_data_result *) result)->skeletonData; +} + +void spine_skeleton_data_result_dispose(spine_skeleton_data_result result) { + if (!result) return; + _spine_skeleton_data_result *_result = (_spine_skeleton_data_result *) result; + if (_result->error) SpineExtension::free(_result->error, __FILE__, __LINE__); + SpineExtension::free(_result, __FILE__, __LINE__); +} + +spine_bone_data spine_skeleton_data_find_bone(spine_skeleton_data data, const utf8 *name) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_bone_data) _data->findBone(name); +} + +spine_slot_data spine_skeleton_data_find_slot(spine_skeleton_data data, const utf8 *name) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_slot_data) _data->findSlot(name); +} + +spine_skin spine_skeleton_data_find_skin(spine_skeleton_data data, const utf8 *name) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_skin) _data->findSkin(name); +} + +spine_event_data spine_skeleton_data_find_event(spine_skeleton_data data, const utf8 *name) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_event_data) _data->findEvent(name); +} + +spine_animation spine_skeleton_data_find_animation(spine_skeleton_data data, const utf8 *name) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_animation) _data->findAnimation(name); +} + +spine_ik_constraint_data spine_skeleton_data_find_ik_constraint(spine_skeleton_data data, const utf8 *name) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_ik_constraint_data) _data->findIkConstraint(name); +} + +spine_transform_constraint_data spine_skeleton_data_find_transform_constraint(spine_skeleton_data data, const utf8 *name) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_transform_constraint_data) _data->findTransformConstraint(name); +} + +spine_path_constraint_data spine_skeleton_data_find_path_constraint(spine_skeleton_data data, const utf8 *name) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_path_constraint_data) _data->findPathConstraint(name); +} + +spine_physics_constraint_data spine_skeleton_data_find_physics_constraint(spine_skeleton_data data, const utf8 *name) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_physics_constraint_data) _data->findPhysicsConstraint(name); +} + +const utf8 *spine_skeleton_data_get_name(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (utf8 *) _data->getName().buffer(); +} + +int32_t spine_skeleton_data_get_num_bones(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return (int32_t) _data->getBones().size(); +} + +spine_bone_data *spine_skeleton_data_get_bones(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_bone_data *) _data->getBones().buffer(); +} + +int32_t spine_skeleton_data_get_num_slots(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return (int32_t) _data->getSlots().size(); +} + +spine_slot_data *spine_skeleton_data_get_slots(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_slot_data *) _data->getSlots().buffer(); +} + +int32_t spine_skeleton_data_get_num_skins(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return (int32_t) _data->getSkins().size(); +} + +spine_skin *spine_skeleton_data_get_skins(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_skin *) _data->getSkins().buffer(); +} + +spine_skin spine_skeleton_data_get_default_skin(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_skin) _data->getDefaultSkin(); +} + +void spine_skeleton_data_set_default_skin(spine_skeleton_data data, spine_skin skin) { + if (data == nullptr) return; + SkeletonData *_data = (SkeletonData *) data; + _data->setDefaultSkin((Skin *) skin); +} + +int32_t spine_skeleton_data_get_num_events(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return (int32_t) _data->getEvents().size(); +} + +spine_event_data *spine_skeleton_data_get_events(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_event_data *) _data->getEvents().buffer(); +} + +int32_t spine_skeleton_data_get_num_animations(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return (int32_t) _data->getAnimations().size(); +} + +spine_animation *spine_skeleton_data_get_animations(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_animation *) _data->getAnimations().buffer(); +} + +int32_t spine_skeleton_data_get_num_ik_constraints(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return (int32_t) _data->getIkConstraints().size(); +} + +spine_ik_constraint_data *spine_skeleton_data_get_ik_constraints(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_ik_constraint_data *) _data->getIkConstraints().buffer(); +} + +int32_t spine_skeleton_data_get_num_transform_constraints(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return (int32_t) _data->getTransformConstraints().size(); +} + +spine_transform_constraint_data *spine_skeleton_data_get_transform_constraints(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_transform_constraint_data *) _data->getTransformConstraints().buffer(); +} + +int32_t spine_skeleton_data_get_num_path_constraints(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return (int32_t) _data->getPathConstraints().size(); +} + +spine_path_constraint_data *spine_skeleton_data_get_path_constraints(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_path_constraint_data *) _data->getPathConstraints().buffer(); +} + +int32_t spine_skeleton_data_get_num_physics_constraints(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return (int32_t) _data->getPhysicsConstraints().size(); +} + +spine_physics_constraint_data *spine_skeleton_data_get_physics_constraints(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (spine_physics_constraint_data *) _data->getPhysicsConstraints().buffer(); +} + +float spine_skeleton_data_get_x(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return _data->getX(); +} + +void spine_skeleton_data_set_x(spine_skeleton_data data, float x) { + if (data == nullptr) return; + SkeletonData *_data = (SkeletonData *) data; + _data->setX(x); +} + +float spine_skeleton_data_get_y(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return _data->getY(); +} + +void spine_skeleton_data_set_y(spine_skeleton_data data, float y) { + if (data == nullptr) return; + SkeletonData *_data = (SkeletonData *) data; + _data->setY(y); +} + +float spine_skeleton_data_get_width(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return _data->getWidth(); +} + +void spine_skeleton_data_set_width(spine_skeleton_data data, float width) { + if (data == nullptr) return; + SkeletonData *_data = (SkeletonData *) data; + _data->setWidth(width); +} + +float spine_skeleton_data_get_height(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return _data->getHeight(); +} + +void spine_skeleton_data_set_height(spine_skeleton_data data, float height) { + if (data == nullptr) return; + SkeletonData *_data = (SkeletonData *) data; + _data->setHeight(height); +} + +const utf8 *spine_skeleton_data_get_version(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (utf8 *) _data->getVersion().buffer(); +} + +const utf8 *spine_skeleton_data_get_hash(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (utf8 *) _data->getHash().buffer(); +} + +const utf8 *spine_skeleton_data_get_images_path(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (utf8 *) _data->getImagesPath().buffer(); +} + +const utf8 *spine_skeleton_data_get_audio_path(spine_skeleton_data data) { + if (data == nullptr) return nullptr; + SkeletonData *_data = (SkeletonData *) data; + return (utf8 *) _data->getAudioPath().buffer(); +} + +float spine_skeleton_data_get_fps(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return _data->getFps(); +} + +float spine_skeleton_data_get_reference_scale(spine_skeleton_data data) { + if (data == nullptr) return 0; + SkeletonData *_data = (SkeletonData *) data; + return _data->getReferenceScale(); +} + +void spine_skeleton_data_dispose(spine_skeleton_data data) { + if (!data) return; + delete (SkeletonData *) data; +} + +// SkeletonDrawable + +spine_skeleton_drawable spine_skeleton_drawable_create(spine_skeleton_data skeletonData) { + _spine_skeleton_drawable *drawable = new (__FILE__, __LINE__) _spine_skeleton_drawable(); + drawable->skeleton = (spine_skeleton) new (__FILE__, __LINE__) Skeleton((SkeletonData *) skeletonData); + AnimationStateData *stateData = new (__FILE__, __LINE__) AnimationStateData((SkeletonData *) skeletonData); + drawable->animationStateData = (spine_animation_state_data) stateData; + AnimationState *state = new (__FILE__, __LINE__) AnimationState(stateData); + drawable->animationState = (spine_animation_state) state; + state->setManualTrackEntryDisposal(true); + EventListener *listener = new EventListener(); + drawable->animationStateEvents = (spine_animation_state_events) listener; + state->setListener(listener); + drawable->renderer = new (__FILE__, __LINE__) SkeletonRenderer(); + return (spine_skeleton_drawable) drawable; +} + +void spine_skeleton_drawable_dispose(spine_skeleton_drawable drawable) { + _spine_skeleton_drawable *_drawable = (_spine_skeleton_drawable *) drawable; + if (!_drawable) return; + if (_drawable->skeleton) delete (Skeleton *) _drawable->skeleton; + if (_drawable->animationState) delete (AnimationState *) _drawable->animationState; + if (_drawable->animationStateData) delete (AnimationStateData *) _drawable->animationStateData; + if (_drawable->animationStateEvents) delete (EventListener *) (_drawable->animationStateEvents); + if (_drawable->renderer) delete (SkeletonRenderer *) _drawable->renderer; + SpineExtension::free(drawable, __FILE__, __LINE__); +} + +spine_render_command spine_skeleton_drawable_render(spine_skeleton_drawable drawable) { + _spine_skeleton_drawable *_drawable = (_spine_skeleton_drawable *) drawable; + if (!_drawable) return nullptr; + if (!_drawable->skeleton) return nullptr; + if (!_drawable->renderer) return nullptr; + return (spine_render_command) _drawable->renderer->render(*(Skeleton *) _drawable->skeleton); +} + +spine_skeleton spine_skeleton_drawable_get_skeleton(spine_skeleton_drawable drawable) { + if (!drawable) return nullptr; + return ((_spine_skeleton_drawable *) drawable)->skeleton; +} + +spine_animation_state spine_skeleton_drawable_get_animation_state(spine_skeleton_drawable drawable) { + if (!drawable) return nullptr; + return ((_spine_skeleton_drawable *) drawable)->animationState; +} + +spine_animation_state_data spine_skeleton_drawable_get_animation_state_data(spine_skeleton_drawable drawable) { + if (!drawable) return nullptr; + return ((_spine_skeleton_drawable *) drawable)->animationStateData; +} + +spine_animation_state_events spine_skeleton_drawable_get_animation_state_events(spine_skeleton_drawable drawable) { + if (!drawable) return nullptr; + return ((_spine_skeleton_drawable *) drawable)->animationStateEvents; +} + +// Render command +float *spine_render_command_get_positions(spine_render_command command) { + if (!command) return nullptr; + return ((RenderCommand *) command)->positions; +} + +float *spine_render_command_get_uvs(spine_render_command command) { + if (!command) return nullptr; + return ((RenderCommand *) command)->uvs; +} + +int32_t *spine_render_command_get_colors(spine_render_command command) { + if (!command) return nullptr; + return (int32_t *) ((RenderCommand *) command)->colors; +} + +int32_t *spine_render_command_get_dark_colors(spine_render_command command) { + if (!command) return nullptr; + return (int32_t *) ((RenderCommand *) command)->darkColors; +} + +int32_t spine_render_command_get_num_vertices(spine_render_command command) { + if (!command) return 0; + return ((RenderCommand *) command)->numVertices; +} + +uint16_t *spine_render_command_get_indices(spine_render_command command) { + if (!command) return nullptr; + return ((RenderCommand *) command)->indices; +} + +int32_t spine_render_command_get_num_indices(spine_render_command command) { + if (!command) return 0; + return ((RenderCommand *) command)->numIndices; +} + +int32_t spine_render_command_get_atlas_page(spine_render_command command) { + if (!command) return 0; + return (int32_t) (intptr_t) ((RenderCommand *) command)->texture; +} + +spine_blend_mode spine_render_command_get_blend_mode(spine_render_command command) { + if (!command) return SPINE_BLEND_MODE_NORMAL; + return (spine_blend_mode) ((RenderCommand *) command)->blendMode; +} + +spine_render_command spine_render_command_get_next(spine_render_command command) { + if (!command) return nullptr; + return (spine_render_command) ((RenderCommand *) command)->next; +} + +// Animation + +const utf8 *spine_animation_get_name(spine_animation animation) { + if (animation == nullptr) return nullptr; + Animation *_animation = (Animation *) animation; + return (utf8 *) _animation->getName().buffer(); +} + +float spine_animation_get_duration(spine_animation animation) { + if (animation == nullptr) return 0; + Animation *_animation = (Animation *) animation; + return _animation->getDuration(); +} + +// AnimationStateData +spine_skeleton_data spine_animation_state_data_get_skeleton_data(spine_animation_state_data stateData) { + if (stateData == nullptr) return nullptr; + AnimationStateData *_stateData = (AnimationStateData *) stateData; + return (spine_skeleton_data) _stateData->getSkeletonData(); +} + +float spine_animation_state_data_get_default_mix(spine_animation_state_data stateData) { + if (stateData == nullptr) return 0; + AnimationStateData *_stateData = (AnimationStateData *) stateData; + return _stateData->getDefaultMix(); +} + +void spine_animation_state_data_set_default_mix(spine_animation_state_data stateData, float defaultMix) { + if (stateData == nullptr) return; + AnimationStateData *_stateData = (AnimationStateData *) stateData; + _stateData->setDefaultMix(defaultMix); +} + +void spine_animation_state_data_set_mix(spine_animation_state_data stateData, spine_animation from, spine_animation to, float duration) { + if (stateData == nullptr) return; + if (from == nullptr || to == nullptr) return; + AnimationStateData *_stateData = (AnimationStateData *) stateData; + _stateData->setMix((Animation *) from, (Animation *) to, duration); +} + +float spine_animation_state_data_get_mix(spine_animation_state_data stateData, spine_animation from, spine_animation to) { + if (stateData == nullptr) return 0; + if (from == nullptr || to == nullptr) return 0; + AnimationStateData *_stateData = (AnimationStateData *) stateData; + return _stateData->getMix((Animation *) from, (Animation *) to); +} + +void spine_animation_state_data_set_mix_by_name(spine_animation_state_data stateData, const utf8 *fromName, const utf8 *toName, float duration) { + if (stateData == nullptr) return; + if (fromName == nullptr || toName == nullptr) return; + AnimationStateData *_stateData = (AnimationStateData *) stateData; + _stateData->setMix(fromName, toName, duration); +} + +float spine_animation_state_data_get_mix_by_name(spine_animation_state_data stateData, const utf8 *fromName, const utf8 *toName) { + if (stateData == nullptr) return 0; + AnimationStateData *_stateData = (AnimationStateData *) stateData; + Animation *from = _stateData->getSkeletonData()->findAnimation(fromName); + Animation *to = _stateData->getSkeletonData()->findAnimation(toName); + if (from == nullptr || to == nullptr) return 0; + return _stateData->getMix(from, to); +} + +void spine_animation_state_data_clear(spine_animation_state_data stateData) { + if (stateData == nullptr) return; + AnimationStateData *_stateData = (AnimationStateData *) stateData; + _stateData->clear(); +} + +// AnimationState +void spine_animation_state_update(spine_animation_state state, float delta) { + if (state == nullptr) return; + AnimationState *_state = (AnimationState *) state; + _state->update(delta); +} + +void spine_animation_state_dispose_track_entry(spine_animation_state state, spine_track_entry entry) { + if (state == nullptr) return; + if (entry == nullptr) return; + AnimationState *_state = (AnimationState *) state; + _state->disposeTrackEntry((TrackEntry *) entry); +} + +void spine_animation_state_apply(spine_animation_state state, spine_skeleton skeleton) { + if (state == nullptr) return; + AnimationState *_state = (AnimationState *) state; + _state->apply(*(Skeleton *) skeleton); +} + +void spine_animation_state_clear_tracks(spine_animation_state state) { + if (state == nullptr) return; + AnimationState *_state = (AnimationState *) state; + _state->clearTracks(); +} + +int32_t spine_animation_state_get_num_tracks(spine_animation_state state) { + if (state == nullptr) return 0; + AnimationState *_state = (AnimationState *) state; + return (int32_t) _state->getTracks().size(); +} + +void spine_animation_state_clear_track(spine_animation_state state, int32_t trackIndex) { + if (state == nullptr) return; + AnimationState *_state = (AnimationState *) state; + _state->clearTrack(trackIndex); +} + +spine_track_entry spine_animation_state_set_animation_by_name(spine_animation_state state, int32_t trackIndex, const utf8 *animationName, spine_bool loop) { + if (state == nullptr) return nullptr; + AnimationState *_state = (AnimationState *) state; + return (spine_track_entry) _state->setAnimation(trackIndex, animationName, loop); +} + +spine_track_entry spine_animation_state_set_animation(spine_animation_state state, int32_t trackIndex, spine_animation animation, spine_bool loop) { + if (state == nullptr) return nullptr; + AnimationState *_state = (AnimationState *) state; + return (spine_track_entry) _state->setAnimation(trackIndex, (Animation *) animation, loop); +} + +spine_track_entry spine_animation_state_add_animation_by_name(spine_animation_state state, int32_t trackIndex, const utf8 *animationName, spine_bool loop, float delay) { + if (state == nullptr) return nullptr; + AnimationState *_state = (AnimationState *) state; + return (spine_track_entry) _state->addAnimation(trackIndex, animationName, loop, delay); +} + +spine_track_entry spine_animation_state_add_animation(spine_animation_state state, int32_t trackIndex, spine_animation animation, spine_bool loop, float delay) { + if (state == nullptr) return nullptr; + AnimationState *_state = (AnimationState *) state; + return (spine_track_entry) _state->addAnimation(trackIndex, (Animation *) animation, loop, delay); +} + +spine_track_entry spine_animation_state_set_empty_animation(spine_animation_state state, int32_t trackIndex, float mixDuration) { + if (state == nullptr) return nullptr; + AnimationState *_state = (AnimationState *) state; + return (spine_track_entry) _state->setEmptyAnimation(trackIndex, mixDuration); +} + +spine_track_entry spine_animation_state_add_empty_animation(spine_animation_state state, int32_t trackIndex, float mixDuration, float delay) { + if (state == nullptr) return nullptr; + AnimationState *_state = (AnimationState *) state; + return (spine_track_entry) _state->addEmptyAnimation(trackIndex, mixDuration, delay); +} + +void spine_animation_state_set_empty_animations(spine_animation_state state, float mixDuration) { + if (state == nullptr) return; + AnimationState *_state = (AnimationState *) state; + _state->setEmptyAnimations(mixDuration); +} + +spine_track_entry spine_animation_state_get_current(spine_animation_state state, int32_t trackIndex) { + if (state == nullptr) return nullptr; + AnimationState *_state = (AnimationState *) state; + return (spine_track_entry) _state->getCurrent(trackIndex); +} + +spine_animation_state_data spine_animation_state_get_data(spine_animation_state state) { + if (state == nullptr) return nullptr; + AnimationState *_state = (AnimationState *) state; + return (spine_animation_state_data) _state->getData(); +} + +float spine_animation_state_get_time_scale(spine_animation_state state) { + if (state == nullptr) return 0; + AnimationState *_state = (AnimationState *) state; + return _state->getTimeScale(); +} + +void spine_animation_state_set_time_scale(spine_animation_state state, float timeScale) { + if (state == nullptr) return; + AnimationState *_state = (AnimationState *) state; + _state->setTimeScale(timeScale); +} + +int32_t spine_animation_state_events_get_num_events(spine_animation_state_events events) { + if (events == nullptr) return 0; + EventListener *_events = (EventListener *) events; + return (int32_t) _events->events.size(); +} + +spine_event_type spine_animation_state_events_get_event_type(spine_animation_state_events events, int32_t index) { + if (events == nullptr) return SPINE_EVENT_TYPE_DISPOSE; + if (index < 0) return SPINE_EVENT_TYPE_DISPOSE; + EventListener *_events = (EventListener *) events; + if (index >= (int) _events->events.size()) return SPINE_EVENT_TYPE_DISPOSE; + return (spine_event_type) _events->events[index].type; +} + +spine_track_entry spine_animation_state_events_get_track_entry(spine_animation_state_events events, int32_t index) { + if (events == nullptr) return nullptr; + EventListener *_events = (EventListener *) events; + if (index >= (int) _events->events.size()) return nullptr; + return (spine_track_entry) _events->events[index].entry; +} + +spine_event spine_animation_state_events_get_event(spine_animation_state_events events, int32_t index) { + if (events == nullptr) return nullptr; + EventListener *_events = (EventListener *) events; + if (index >= (int) _events->events.size()) return nullptr; + return (spine_event) _events->events[index].event; +} + +void spine_animation_state_events_reset(spine_animation_state_events events) { + if (events == nullptr) return; + EventListener *_events = (EventListener *) events; + _events->events.clear(); +} + +// TrackEntry + +int32_t spine_track_entry_get_track_index(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getTrackIndex(); +} + +spine_animation spine_track_entry_get_animation(spine_track_entry entry) { + if (entry == nullptr) return nullptr; + TrackEntry *_entry = (TrackEntry *) entry; + return (spine_animation) _entry->getAnimation(); +} + +spine_track_entry spine_track_entry_get_previous(spine_track_entry entry) { + if (entry == nullptr) return nullptr; + TrackEntry *_entry = (TrackEntry *) entry; + return (spine_track_entry) _entry->getPrevious(); +} + +spine_bool spine_track_entry_get_loop(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getLoop() ? -1 : 0; +} + +void spine_track_entry_set_loop(spine_track_entry entry, spine_bool loop) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setLoop(loop); +} + +spine_bool spine_track_entry_get_hold_previous(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getHoldPrevious() ? -1 : 0; +} + +void spine_track_entry_set_hold_previous(spine_track_entry entry, spine_bool holdPrevious) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setHoldPrevious(holdPrevious); +} + +spine_bool spine_track_entry_get_reverse(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getReverse() ? -1 : 0; +} + +void spine_track_entry_set_reverse(spine_track_entry entry, spine_bool reverse) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setReverse(reverse); +} + +spine_bool spine_track_entry_get_shortest_rotation(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getShortestRotation() ? -1 : 0; +} + +void spine_track_entry_set_shortest_rotation(spine_track_entry entry, spine_bool shortestRotation) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setShortestRotation(shortestRotation); +} + +float spine_track_entry_get_delay(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getDelay(); +} + +void spine_track_entry_set_delay(spine_track_entry entry, float delay) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setDelay(delay); +} + +float spine_track_entry_get_track_time(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getTrackTime(); +} + +void spine_track_entry_set_track_time(spine_track_entry entry, float trackTime) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setTrackTime(trackTime); +} + +float spine_track_entry_get_track_end(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getTrackEnd(); +} + +void spine_track_entry_set_track_end(spine_track_entry entry, float trackEnd) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setTrackEnd(trackEnd); +} + +float spine_track_entry_get_animation_start(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getAnimationStart(); +} + +void spine_track_entry_set_animation_start(spine_track_entry entry, float animationStart) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setAnimationStart(animationStart); +} + +float spine_track_entry_get_animation_end(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getAnimationEnd(); +} + +void spine_track_entry_set_animation_end(spine_track_entry entry, float animationEnd) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setAnimationEnd(animationEnd); +} + +float spine_track_entry_get_animation_last(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getAnimationLast(); +} + +void spine_track_entry_set_animation_last(spine_track_entry entry, float animationLast) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setAnimationLast(animationLast); +} + +float spine_track_entry_get_animation_time(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getAnimationTime(); +} + +float spine_track_entry_get_time_scale(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getTimeScale(); +} + +void spine_track_entry_set_time_scale(spine_track_entry entry, float timeScale) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setTimeScale(timeScale); +} + +float spine_track_entry_get_alpha(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getAlpha(); +} + +void spine_track_entry_set_alpha(spine_track_entry entry, float alpha) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setAlpha(alpha); +} + +float spine_track_entry_get_event_threshold(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getEventThreshold(); +} + +void spine_track_entry_set_event_threshold(spine_track_entry entry, float eventThreshold) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setEventThreshold(eventThreshold); +} + +float spine_track_entry_get_alpha_attachment_threshold(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getAlphaAttachmentThreshold(); +} + +void spine_track_entry_set_alpha_attachment_threshold(spine_track_entry entry, float attachmentThreshold) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setAlphaAttachmentThreshold(attachmentThreshold); +} + +float spine_track_entry_get_mix_attachment_threshold(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getMixAttachmentThreshold(); +} + +void spine_track_entry_set_mix_attachment_threshold(spine_track_entry entry, float attachmentThreshold) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setMixAttachmentThreshold(attachmentThreshold); +} + +float spine_track_entry_get_mix_draw_order_threshold(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getMixDrawOrderThreshold(); +} + +void spine_track_entry_set_mix_draw_order_threshold(spine_track_entry entry, float drawOrderThreshold) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setMixDrawOrderThreshold(drawOrderThreshold); +} + +spine_track_entry spine_track_entry_get_next(spine_track_entry entry) { + if (entry == nullptr) return nullptr; + TrackEntry *_entry = (TrackEntry *) entry; + return (spine_track_entry) _entry->getNext(); +} + +spine_bool spine_track_entry_is_complete(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->isComplete() ? -1 : 0; +} + +float spine_track_entry_get_mix_time(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getMixTime(); +} + +void spine_track_entry_set_mix_time(spine_track_entry entry, float mixTime) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setMixTime(mixTime); +} + +float spine_track_entry_get_mix_duration(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getMixDuration(); +} + +void spine_track_entry_set_mix_duration(spine_track_entry entry, float mixDuration) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setMixDuration(mixDuration); +} + +spine_mix_blend spine_track_entry_get_mix_blend(spine_track_entry entry) { + if (entry == nullptr) return SPINE_MIX_BLEND_SETUP; + TrackEntry *_entry = (TrackEntry *) entry; + return (spine_mix_blend) _entry->getMixBlend(); +} + +void spine_track_entry_set_mix_blend(spine_track_entry entry, spine_mix_blend mixBlend) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->setMixBlend((MixBlend) mixBlend); +} + +spine_track_entry spine_track_entry_get_mixing_from(spine_track_entry entry) { + if (entry == nullptr) return nullptr; + TrackEntry *_entry = (TrackEntry *) entry; + return (spine_track_entry) _entry->getMixingFrom(); +} + +spine_track_entry spine_track_entry_get_mixing_to(spine_track_entry entry) { + if (entry == nullptr) return nullptr; + TrackEntry *_entry = (TrackEntry *) entry; + return (spine_track_entry) _entry->getMixingTo(); +} + +void spine_track_entry_reset_rotation_directions(spine_track_entry entry) { + if (entry == nullptr) return; + TrackEntry *_entry = (TrackEntry *) entry; + _entry->resetRotationDirections(); +} + +float spine_track_entry_get_track_complete(spine_track_entry entry) { + if (entry == nullptr) return 0; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->getTrackComplete(); +} + +spine_bool spine_track_entry_was_applied(spine_track_entry entry) { + if (entry == nullptr) return false; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->wasApplied(); +} + +spine_bool spine_track_entry_is_next_ready(spine_track_entry entry) { + if (entry == nullptr) return false; + TrackEntry *_entry = (TrackEntry *) entry; + return _entry->isNextReady(); +} + +// Skeleton + +void spine_skeleton_update_cache(spine_skeleton skeleton) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->updateCache(); +} + +void spine_skeleton_update_world_transform(spine_skeleton skeleton, spine_physics physics) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->updateWorldTransform((spine::Physics) physics); +} + +void spine_skeleton_update_world_transform_bone(spine_skeleton skeleton, spine_physics physics, spine_bone parent) { + if (skeleton == nullptr) return; + if (parent == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + Bone *_bone = (Bone *) parent; + _skeleton->updateWorldTransform((spine::Physics) physics, _bone); +} + +void spine_skeleton_set_to_setup_pose(spine_skeleton skeleton) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->setToSetupPose(); +} + +void spine_skeleton_set_bones_to_setup_pose(spine_skeleton skeleton) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->setBonesToSetupPose(); +} + +void spine_skeleton_set_slots_to_setup_pose(spine_skeleton skeleton) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->setSlotsToSetupPose(); +} + +spine_bone spine_skeleton_find_bone(spine_skeleton skeleton, const utf8 *boneName) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_bone) _skeleton->findBone(boneName); +} + +spine_slot spine_skeleton_find_slot(spine_skeleton skeleton, const utf8 *slotName) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_slot) _skeleton->findSlot(slotName); +} + +void spine_skeleton_set_skin_by_name(spine_skeleton skeleton, const utf8 *skinName) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->setSkin(skinName); +} + +void spine_skeleton_set_skin(spine_skeleton skeleton, spine_skin skin) { + if (skeleton == nullptr) return; + if (skin == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->setSkin((Skin *) skin); +} + +spine_attachment spine_skeleton_get_attachment_by_name(spine_skeleton skeleton, const utf8 *slotName, const utf8 *attachmentName) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_attachment) _skeleton->getAttachment(slotName, attachmentName); +} + +spine_attachment spine_skeleton_get_attachment(spine_skeleton skeleton, int32_t slotIndex, const utf8 *attachmentName) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_attachment) _skeleton->getAttachment(slotIndex, attachmentName); +} + +void spine_skeleton_set_attachment(spine_skeleton skeleton, const utf8 *slotName, const utf8 *attachmentName) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + return _skeleton->setAttachment(slotName, attachmentName); +} + +spine_ik_constraint spine_skeleton_find_ik_constraint(spine_skeleton skeleton, const utf8 *constraintName) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_ik_constraint) _skeleton->findIkConstraint(constraintName); +} + +spine_transform_constraint spine_skeleton_find_transform_constraint(spine_skeleton skeleton, const utf8 *constraintName) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_transform_constraint) _skeleton->findTransformConstraint(constraintName); +} + +spine_path_constraint spine_skeleton_find_path_constraint(spine_skeleton skeleton, const utf8 *constraintName) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_path_constraint) _skeleton->findPathConstraint(constraintName); +} + +spine_physics_constraint spine_skeleton_find_physics_constraint(spine_skeleton skeleton, const utf8 *constraintName) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_physics_constraint) _skeleton->findPhysicsConstraint(constraintName); +} + +_spine_bounds tmp_bounds; +spine_bounds spine_skeleton_get_bounds(spine_skeleton skeleton) { + _spine_bounds *bounds = &tmp_bounds; + if (skeleton == nullptr) return (spine_bounds) bounds; + Skeleton *_skeleton = (Skeleton *) skeleton; + Vector vertices; + SkeletonClipping clipper; + + _skeleton->getBounds(bounds->x, bounds->y, bounds->width, bounds->height, vertices, &clipper); + return (spine_bounds) bounds; +} + +spine_bone spine_skeleton_get_root_bone(spine_skeleton skeleton) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_bone) _skeleton->getRootBone(); +} + +spine_skeleton_data spine_skeleton_get_data(spine_skeleton skeleton) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_skeleton_data) _skeleton->getData(); +} + +int32_t spine_skeleton_get_num_bones(spine_skeleton skeleton) { + if (skeleton == nullptr) return 0; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (int32_t) _skeleton->getBones().size(); +} + +spine_bone *spine_skeleton_get_bones(spine_skeleton skeleton) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_bone *) _skeleton->getBones().buffer(); +} + +int32_t spine_skeleton_get_num_slots(spine_skeleton skeleton) { + if (skeleton == nullptr) return 0; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (int32_t) _skeleton->getSlots().size(); +} + +spine_slot *spine_skeleton_get_slots(spine_skeleton skeleton) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_slot *) _skeleton->getSlots().buffer(); +} + +int32_t spine_skeleton_get_num_draw_order(spine_skeleton skeleton) { + if (skeleton == nullptr) return 0; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (int32_t) _skeleton->getDrawOrder().size(); +} + +spine_slot *spine_skeleton_get_draw_order(spine_skeleton skeleton) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_slot *) _skeleton->getDrawOrder().buffer(); +} + +int32_t spine_skeleton_get_num_ik_constraints(spine_skeleton skeleton) { + if (skeleton == nullptr) return 0; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (int32_t) _skeleton->getIkConstraints().size(); +} + +spine_ik_constraint *spine_skeleton_get_ik_constraints(spine_skeleton skeleton) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_ik_constraint *) _skeleton->getIkConstraints().buffer(); +} + +int32_t spine_skeleton_get_num_transform_constraints(spine_skeleton skeleton) { + if (skeleton == nullptr) return 0; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (int32_t) _skeleton->getTransformConstraints().size(); +} + +spine_transform_constraint *spine_skeleton_get_transform_constraints(spine_skeleton skeleton) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_transform_constraint *) _skeleton->getTransformConstraints().buffer(); +} + +int32_t spine_skeleton_get_num_path_constraints(spine_skeleton skeleton) { + if (skeleton == nullptr) return 0; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (int32_t) _skeleton->getPathConstraints().size(); +} + +spine_path_constraint *spine_skeleton_get_path_constraints(spine_skeleton skeleton) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_path_constraint *) _skeleton->getPathConstraints().buffer(); +} + +int32_t spine_skeleton_get_num_physics_constraints(spine_skeleton skeleton) { + if (skeleton == nullptr) return 0; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (int32_t) _skeleton->getPhysicsConstraints().size(); +} + +spine_physics_constraint *spine_skeleton_get_physics_constraints(spine_skeleton skeleton) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_physics_constraint *) _skeleton->getPhysicsConstraints().buffer(); +} + +spine_skin spine_skeleton_get_skin(spine_skeleton skeleton) { + if (skeleton == nullptr) return nullptr; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_skin) _skeleton->getSkin(); +} + +spine_color spine_skeleton_get_color(spine_skeleton skeleton) { + if (skeleton == nullptr) return (spine_color) &NULL_COLOR; + Skeleton *_skeleton = (Skeleton *) skeleton; + return (spine_color) &_skeleton->getColor(); +} + +void spine_skeleton_set_color(spine_skeleton skeleton, float r, float g, float b, float a) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->getColor().set(r, g, b, a); +} + +void spine_skeleton_set_position(spine_skeleton skeleton, float x, float y) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->setPosition(x, y); +} + +float spine_skeleton_get_x(spine_skeleton skeleton) { + if (skeleton == nullptr) return 0; + Skeleton *_skeleton = (Skeleton *) skeleton; + return _skeleton->getX(); +} + +void spine_skeleton_set_x(spine_skeleton skeleton, float x) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->setX(x); +} + +float spine_skeleton_get_y(spine_skeleton skeleton) { + if (skeleton == nullptr) return 0; + Skeleton *_skeleton = (Skeleton *) skeleton; + return _skeleton->getY(); +} + +void spine_skeleton_set_y(spine_skeleton skeleton, float y) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->setY(y); +} + +void spine_skeleton_set_scale(spine_skeleton skeleton, float scaleX, float scaleY) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->setScaleX(scaleX); + _skeleton->setScaleY(scaleY); +} + +float spine_skeleton_get_scale_x(spine_skeleton skeleton) { + if (skeleton == nullptr) return 0; + Skeleton *_skeleton = (Skeleton *) skeleton; + return _skeleton->getScaleX(); +} + +void spine_skeleton_set_scale_x(spine_skeleton skeleton, float scaleX) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->setScaleX(scaleX); +} + +float spine_skeleton_get_scale_y(spine_skeleton skeleton) { + if (skeleton == nullptr) return 0; + Skeleton *_skeleton = (Skeleton *) skeleton; + return _skeleton->getScaleY(); +} + +void spine_skeleton_set_scale_y(spine_skeleton skeleton, float scaleY) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->setScaleY(scaleY); +} + +float spine_skeleton_get_time(spine_skeleton skeleton) { + if (skeleton == nullptr) return 0; + Skeleton *_skeleton = (Skeleton *) skeleton; + return _skeleton->getTime(); +} + +void spine_skeleton_set_time(spine_skeleton skeleton, float time) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->setTime(time); +} + +void spine_skeleton_update(spine_skeleton skeleton, float delta) { + if (skeleton == nullptr) return; + Skeleton *_skeleton = (Skeleton *) skeleton; + _skeleton->update(delta); +} + +// EventData +const utf8 *spine_event_data_get_name(spine_event_data event) { + if (event == nullptr) return nullptr; + EventData *_event = (EventData *) event; + return (utf8 *) _event->getName().buffer(); +} + +int32_t spine_event_data_get_int_value(spine_event_data event) { + if (event == nullptr) return 0; + EventData *_event = (EventData *) event; + return _event->getIntValue(); +} + +void spine_event_data_set_int_value(spine_event_data event, int32_t value) { + if (event == nullptr) return; + EventData *_event = (EventData *) event; + _event->setIntValue(value); +} + +float spine_event_data_get_float_value(spine_event_data event) { + if (event == nullptr) return 0; + EventData *_event = (EventData *) event; + return _event->getFloatValue(); +} + +void spine_event_data_set_float_value(spine_event_data event, float value) { + if (event == nullptr) return; + EventData *_event = (EventData *) event; + _event->setFloatValue(value); +} + +const utf8 *spine_event_data_get_string_value(spine_event_data event) { + if (event == nullptr) return nullptr; + EventData *_event = (EventData *) event; + return (utf8 *) _event->getStringValue().buffer(); +} + +void spine_event_data_set_string_value(spine_event_data event, const utf8 *value) { + if (event == nullptr) return; + EventData *_event = (EventData *) event; + _event->setStringValue(value); +} + +const utf8 *spine_event_data_get_audio_path(spine_event_data event) { + if (event == nullptr) return nullptr; + EventData *_event = (EventData *) event; + return (utf8 *) _event->getAudioPath().buffer(); +} + +float spine_event_data_get_volume(spine_event_data event) { + if (event == nullptr) return 0; + EventData *_event = (EventData *) event; + return _event->getVolume(); +} + +void spine_event_data_set_volume(spine_event_data event, float volume) { + if (event == nullptr) return; + EventData *_event = (EventData *) event; + _event->setVolume(volume); +} + +float spine_event_data_get_balance(spine_event_data event) { + if (event == nullptr) return 0; + EventData *_event = (EventData *) event; + return _event->getBalance(); +} + +void spine_event_data_set_balance(spine_event_data event, float balance) { + if (event == nullptr) return; + EventData *_event = (EventData *) event; + _event->setBalance(balance); +} + +// Event + +spine_event_data spine_event_get_data(spine_event event) { + if (event == nullptr) return nullptr; + Event *_event = (Event *) event; + return (spine_event_data) &_event->getData(); +} + +float spine_event_get_time(spine_event event) { + if (event == nullptr) return 0; + Event *_event = (Event *) event; + return _event->getTime(); +} + +int32_t spine_event_get_int_value(spine_event event) { + if (event == nullptr) return 0; + Event *_event = (Event *) event; + return _event->getIntValue(); +} + +void spine_event_set_int_value(spine_event event, int32_t value) { + if (event == nullptr) return; + Event *_event = (Event *) event; + _event->setIntValue(value); +} + +float spine_event_get_float_value(spine_event event) { + if (event == nullptr) return 0; + Event *_event = (Event *) event; + return _event->getFloatValue(); +} + +void spine_event_set_float_value(spine_event event, float value) { + if (event == nullptr) return; + Event *_event = (Event *) event; + _event->setFloatValue(value); +} + +const utf8 *spine_event_get_string_value(spine_event event) { + if (event == nullptr) return nullptr; + Event *_event = (Event *) event; + return (utf8 *) _event->getStringValue().buffer(); +} + +void spine_event_set_string_value(spine_event event, const utf8 *value) { + if (event == nullptr) return; + Event *_event = (Event *) event; + _event->setStringValue(value); +} + +float spine_event_get_volume(spine_event event) { + if (event == nullptr) return 0; + Event *_event = (Event *) event; + return _event->getVolume(); +} + +void spine_event_set_volume(spine_event event, float volume) { + if (event == nullptr) return; + Event *_event = (Event *) event; + _event->setVolume(volume); +} + +float spine_event_get_balance(spine_event event) { + if (event == nullptr) return 0; + Event *_event = (Event *) event; + return _event->getBalance(); +} + +void spine_event_set_balance(spine_event event, float balance) { + if (event == nullptr) return; + Event *_event = (Event *) event; + _event->setBalance(balance); +} + +// SlotData +int32_t spine_slot_data_get_index(spine_slot_data slot) { + if (slot == nullptr) return 0; + SlotData *_slot = (SlotData *) slot; + return _slot->getIndex(); +} + +const utf8 *spine_slot_data_get_name(spine_slot_data slot) { + if (slot == nullptr) return nullptr; + SlotData *_slot = (SlotData *) slot; + return (utf8 *) _slot->getName().buffer(); +} + +spine_bone_data spine_slot_data_get_bone_data(spine_slot_data slot) { + if (slot == nullptr) return nullptr; + SlotData *_slot = (SlotData *) slot; + return (spine_bone_data) &_slot->getBoneData(); +} + +spine_color spine_slot_data_get_color(spine_slot_data slot) { + if (slot == nullptr) return (spine_color) &NULL_COLOR; + SlotData *_slot = (SlotData *) slot; + return (spine_color) &_slot->getColor(); +} + +void spine_slot_data_set_color(spine_slot_data slot, float r, float g, float b, float a) { + if (slot == nullptr) return; + SlotData *_slot = (SlotData *) slot; + _slot->getColor().set(r, g, b, a); +} + +spine_color spine_slot_data_get_dark_color(spine_slot_data slot) { + if (slot == nullptr) return (spine_color) &NULL_COLOR; + SlotData *_slot = (SlotData *) slot; + return (spine_color) &_slot->getDarkColor(); +} + +void spine_slot_data_set_dark_color(spine_slot_data slot, float r, float g, float b, float a) { + if (slot == nullptr) return; + SlotData *_slot = (SlotData *) slot; + _slot->getDarkColor().set(r, g, b, a); +} + +spine_bool spine_slot_data_get_has_dark_color(spine_slot_data slot) { + if (slot == nullptr) return 0; + SlotData *_slot = (SlotData *) slot; + return _slot->hasDarkColor() ? -1 : 0; +} + +void spine_slot_data_set_has_dark_color(spine_slot_data slot, spine_bool hasDarkColor) { + if (slot == nullptr) return; + SlotData *_slot = (SlotData *) slot; + _slot->setHasDarkColor(hasDarkColor); +} + +const utf8 *spine_slot_data_get_attachment_name(spine_slot_data slot) { + if (slot == nullptr) return nullptr; + SlotData *_slot = (SlotData *) slot; + return (utf8 *) _slot->getAttachmentName().buffer(); +} + +void spine_slot_data_set_attachment_name(spine_slot_data slot, const utf8 *attachmentName) { + if (slot == nullptr) return; + SlotData *_slot = (SlotData *) slot; + _slot->setAttachmentName(attachmentName); +} + +spine_blend_mode spine_slot_data_get_blend_mode(spine_slot_data slot) { + if (slot == nullptr) return SPINE_BLEND_MODE_NORMAL; + SlotData *_slot = (SlotData *) slot; + return (spine_blend_mode) _slot->getBlendMode(); +} + +void spine_slot_data_set_blend_mode(spine_slot_data slot, spine_blend_mode blendMode) { + if (slot == nullptr) return; + SlotData *_slot = (SlotData *) slot; + _slot->setBlendMode((BlendMode) blendMode); +} + +spine_bool spine_slot_data_is_visible(spine_slot_data slot) { + if (slot == nullptr) return false; + SlotData *_slot = (SlotData *) slot; + return _slot->isVisible(); +} + +void spine_slot_data_set_visible(spine_slot_data slot, spine_bool visible) { + if (slot == nullptr) return; + SlotData *_slot = (SlotData *) slot; + _slot->setVisible(visible); +} + +// Slot +void spine_slot_set_to_setup_pose(spine_slot slot) { + if (slot == nullptr) return; + Slot *_slot = (Slot *) slot; + _slot->setToSetupPose(); +} + +spine_slot_data spine_slot_get_data(spine_slot slot) { + if (slot == nullptr) return nullptr; + Slot *_slot = (Slot *) slot; + return (spine_slot_data) &_slot->getData(); +} + +spine_bone spine_slot_get_bone(spine_slot slot) { + if (slot == nullptr) return nullptr; + Slot *_slot = (Slot *) slot; + return (spine_bone) &_slot->getBone(); +} + +spine_skeleton spine_slot_get_skeleton(spine_slot slot) { + if (slot == nullptr) return nullptr; + Slot *_slot = (Slot *) slot; + return (spine_skeleton) &_slot->getSkeleton(); +} + +spine_color spine_slot_get_color(spine_slot slot) { + if (slot == nullptr) return (spine_color) &NULL_COLOR; + Slot *_slot = (Slot *) slot; + return (spine_color) &_slot->getColor(); +} + +void spine_slot_set_color(spine_slot slot, float r, float g, float b, float a) { + if (slot == nullptr) return; + Slot *_slot = (Slot *) slot; + _slot->getColor().set(r, g, b, a); +} + +spine_color spine_slot_get_dark_color(spine_slot slot) { + if (slot == nullptr) return (spine_color) &NULL_COLOR; + Slot *_slot = (Slot *) slot; + return (spine_color) &_slot->getDarkColor(); +} + +void spine_slot_set_dark_color(spine_slot slot, float r, float g, float b, float a) { + if (slot == nullptr) return; + Slot *_slot = (Slot *) slot; + _slot->getDarkColor().set(r, g, b, a); +} + +spine_bool spine_slot_has_dark_color(spine_slot slot) { + if (slot == nullptr) return 0; + Slot *_slot = (Slot *) slot; + return _slot->hasDarkColor() ? -1 : 0; +} + +spine_attachment spine_slot_get_attachment(spine_slot slot) { + if (slot == nullptr) return nullptr; + Slot *_slot = (Slot *) slot; + return (spine_attachment) _slot->getAttachment(); +} + +void spine_slot_set_attachment(spine_slot slot, spine_attachment attachment) { + if (slot == nullptr) return; + Slot *_slot = (Slot *) slot; + _slot->setAttachment((Attachment *) attachment); +} + +int32_t spine_slot_get_sequence_index(spine_slot slot) { + if (slot == nullptr) return 0; + Slot *_slot = (Slot *) slot; + return _slot->getSequenceIndex(); +} + +void spine_slot_set_sequence_index(spine_slot slot, int32_t sequenceIndex) { + if (slot == nullptr) return; + Slot *_slot = (Slot *) slot; + _slot->setSequenceIndex(sequenceIndex); +} + +// BoneData +int32_t spine_bone_data_get_index(spine_bone_data data) { + if (data == nullptr) return 0; + BoneData *_data = (BoneData *) data; + return _data->getIndex(); +} + +const utf8 *spine_bone_data_get_name(spine_bone_data data) { + if (data == nullptr) return nullptr; + BoneData *_data = (BoneData *) data; + return (utf8 *) _data->getName().buffer(); +} + +spine_bone_data spine_bone_data_get_parent(spine_bone_data data) { + if (data == nullptr) return nullptr; + BoneData *_data = (BoneData *) data; + return (spine_bone_data) _data->getParent(); +} + +float spine_bone_data_get_length(spine_bone_data data) { + if (data == nullptr) return 0; + BoneData *_data = (BoneData *) data; + return _data->getLength(); +} + +void spine_bone_data_set_length(spine_bone_data data, float length) { + if (data == nullptr) return; + BoneData *_data = (BoneData *) data; + _data->setLength(length); +} + +float spine_bone_data_get_x(spine_bone_data data) { + if (data == nullptr) return 0; + BoneData *_data = (BoneData *) data; + return _data->getX(); +} + +void spine_bone_data_set_x(spine_bone_data data, float x) { + if (data == nullptr) return; + BoneData *_data = (BoneData *) data; + _data->setX(x); +} + +float spine_bone_data_get_y(spine_bone_data data) { + if (data == nullptr) return 0; + BoneData *_data = (BoneData *) data; + return _data->getY(); +} + +void spine_bone_data_set_y(spine_bone_data data, float y) { + if (data == nullptr) return; + BoneData *_data = (BoneData *) data; + _data->setY(y); +} + +float spine_bone_data_get_rotation(spine_bone_data data) { + if (data == nullptr) return 0; + BoneData *_data = (BoneData *) data; + return _data->getRotation(); +} + +void spine_bone_data_set_rotation(spine_bone_data data, float rotation) { + if (data == nullptr) return; + BoneData *_data = (BoneData *) data; + _data->setRotation(rotation); +} + +float spine_bone_data_get_scale_x(spine_bone_data data) { + if (data == nullptr) return 0; + BoneData *_data = (BoneData *) data; + return _data->getScaleX(); +} + +void spine_bone_data_set_scale_x(spine_bone_data data, float scaleX) { + if (data == nullptr) return; + BoneData *_data = (BoneData *) data; + _data->setScaleX(scaleX); +} + +float spine_bone_data_get_scale_y(spine_bone_data data) { + if (data == nullptr) return 0; + BoneData *_data = (BoneData *) data; + return _data->getScaleY(); +} + +void spine_bone_data_set_scale_y(spine_bone_data data, float scaleY) { + if (data == nullptr) return; + BoneData *_data = (BoneData *) data; + _data->setScaleY(scaleY); +} + +float spine_bone_data_get_shear_x(spine_bone_data data) { + if (data == nullptr) return 0; + BoneData *_data = (BoneData *) data; + return _data->getShearX(); +} + +void spine_bone_data_set_shear_x(spine_bone_data data, float shearX) { + if (data == nullptr) return; + BoneData *_data = (BoneData *) data; + _data->setShearX(shearX); +} + +float spine_bone_data_get_shear_y(spine_bone_data data) { + if (data == nullptr) return 0; + BoneData *_data = (BoneData *) data; + return _data->getShearY(); +} + +void spine_bone_data_set_shear_y(spine_bone_data data, float y) { + if (data == nullptr) return; + BoneData *_data = (BoneData *) data; + _data->setShearY(y); +} + +spine_inherit spine_bone_data_get_inherit(spine_bone_data data) { + if (data == nullptr) return SPINE_INHERIT_NORMAL; + BoneData *_data = (BoneData *) data; + return (spine_inherit) _data->getInherit(); +} + +void spine_bone_data_set_inherit(spine_bone_data data, spine_inherit inherit) { + if (data == nullptr) return; + BoneData *_data = (BoneData *) data; + _data->setInherit((Inherit) inherit); +} + +spine_bool spine_bone_data_get_is_skin_required(spine_bone_data data) { + if (data == nullptr) return 0; + BoneData *_data = (BoneData *) data; + return _data->isSkinRequired() ? -1 : 0; +} + +void spine_bone_data_set_is_skin_required(spine_bone_data data, spine_bool isSkinRequired) { + if (data == nullptr) return; + BoneData *_data = (BoneData *) data; + _data->setSkinRequired(isSkinRequired); +} + +spine_color spine_bone_data_get_color(spine_bone_data data) { + if (data == nullptr) return (spine_color) &NULL_COLOR; + BoneData *_data = (BoneData *) data; + return (spine_color) &_data->getColor(); +} + +void spine_bone_data_set_color(spine_bone_data data, float r, float g, float b, float a) { + if (data == nullptr) return; + BoneData *_data = (BoneData *) data; + _data->getColor().set(r, g, b, a); +} + +spine_bool spine_bone_data_is_visible(spine_bone_data data) { + if (data == nullptr) return false; + BoneData *_data = (BoneData *) data; + return _data->isVisible(); +} + +void spine_bone_data_set_visible(spine_bone_data data, spine_bool isVisible) { + if (data == nullptr) return; + BoneData *_data = (BoneData *) data; + _data->setVisible(isVisible); +} + +// Bone +void spine_bone_set_is_y_down(spine_bool yDown) { + Bone::setYDown(yDown); +} + +spine_bool spine_bone_get_is_y_down() { + return Bone::isYDown() ? -1 : 0; +} + +void spine_bone_update(spine_bone bone) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->update(spine::Physics_Update); +} + +void spine_bone_update_world_transform(spine_bone bone) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->updateWorldTransform(); +} + +void spine_bone_update_world_transform_with(spine_bone bone, float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->updateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY); +} + +void spine_bone_update_applied_transform(spine_bone bone) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->updateAppliedTransform(); +} + +void spine_bone_set_to_setup_pose(spine_bone bone) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setToSetupPose(); +} + +_spine_vector tmp_vector; +spine_vector spine_bone_world_to_local(spine_bone bone, float worldX, float worldY) { + _spine_vector *coords = &tmp_vector; + if (bone == nullptr) return (spine_vector) coords; + Bone *_bone = (Bone *) bone; + _bone->worldToLocal(worldX, worldY, coords->x, coords->y); + return (spine_vector) coords; +} + +spine_vector spine_bone_world_to_parent(spine_bone bone, float worldX, float worldY) { + _spine_vector *coords = &tmp_vector; + if (bone == nullptr) return (spine_vector) coords; + Bone *_bone = (Bone *) bone; + _bone->worldToParent(worldX, worldY, coords->x, coords->y); + return (spine_vector) coords; +} + +spine_vector spine_bone_local_to_world(spine_bone bone, float localX, float localY) { + _spine_vector *coords = &tmp_vector; + if (bone == nullptr) return (spine_vector) coords; + Bone *_bone = (Bone *) bone; + _bone->localToWorld(localX, localY, coords->x, coords->y); + return (spine_vector) coords; +} + +spine_vector spine_bone_parent_to_world(spine_bone bone, float localX, float localY) { + _spine_vector *coords = &tmp_vector; + if (bone == nullptr) return (spine_vector) coords; + Bone *_bone = (Bone *) bone; + _bone->parentToWorld(localX, localY, coords->x, coords->y); + return (spine_vector) coords; +} + +float spine_bone_world_to_local_rotation(spine_bone bone, float worldRotation) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->worldToLocalRotation(worldRotation); +} + +float spine_bone_local_to_world_rotation(spine_bone bone, float localRotation) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->localToWorldRotation(localRotation); +} + +void spine_bone_rotate_world(spine_bone bone, float degrees) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->rotateWorld(degrees); +} + +float spine_bone_get_world_to_local_rotation_x(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getWorldToLocalRotationX(); +} + +float spine_bone_get_world_to_local_rotation_y(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getWorldToLocalRotationY(); +} + +spine_bone_data spine_bone_get_data(spine_bone bone) { + if (bone == nullptr) return nullptr; + Bone *_bone = (Bone *) bone; + return (spine_bone_data) &_bone->getData(); +} + +spine_skeleton spine_bone_get_skeleton(spine_bone bone) { + if (bone == nullptr) return nullptr; + Bone *_bone = (Bone *) bone; + return (spine_skeleton) &_bone->getSkeleton(); +} + +spine_bone spine_bone_get_parent(spine_bone bone) { + if (bone == nullptr) return nullptr; + Bone *_bone = (Bone *) bone; + return (spine_bone) _bone->getParent(); +} + +int32_t spine_bone_get_num_children(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return (int32_t) _bone->getChildren().size(); +} + +spine_bone *spine_bone_get_children(spine_bone bone) { + if (bone == nullptr) return nullptr; + Bone *_bone = (Bone *) bone; + return (spine_bone *) _bone->getChildren().buffer(); +} + +float spine_bone_get_x(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getX(); +} + +void spine_bone_set_x(spine_bone bone, float x) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setX(x); +} + +float spine_bone_get_y(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getY(); +} + +void spine_bone_set_y(spine_bone bone, float y) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setY(y); +} + +float spine_bone_get_rotation(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getRotation(); +} + +void spine_bone_set_rotation(spine_bone bone, float rotation) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setRotation(rotation); +} + +float spine_bone_get_scale_x(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getScaleX(); +} + +void spine_bone_set_scale_x(spine_bone bone, float scaleX) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setScaleX(scaleX); +} + +float spine_bone_get_scale_y(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getScaleY(); +} + +void spine_bone_set_scale_y(spine_bone bone, float scaleY) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setScaleY(scaleY); +} + +float spine_bone_get_shear_x(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getShearX(); +} + +void spine_bone_set_shear_x(spine_bone bone, float shearX) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setShearX(shearX); +} + +float spine_bone_get_shear_y(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getShearY(); +} + +void spine_bone_set_shear_y(spine_bone bone, float shearY) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setShearY(shearY); +} + +float spine_bone_get_applied_rotation(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getAppliedRotation(); +} + +void spine_bone_set_applied_rotation(spine_bone bone, float rotation) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setAppliedRotation(rotation); +} + +float spine_bone_get_a_x(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getAX(); +} + +void spine_bone_set_a_x(spine_bone bone, float x) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setAX(x); +} + +float spine_bone_get_a_y(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getAY(); +} + +void spine_bone_set_a_y(spine_bone bone, float y) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setAY(y); +} + +float spine_bone_get_a_scale_x(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getAScaleX(); +} + +void spine_bone_set_a_scale_x(spine_bone bone, float scaleX) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setAScaleX(scaleX); +} + +float spine_bone_get_a_scale_y(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getAScaleY(); +} + +void spine_bone_set_a_scale_y(spine_bone bone, float scaleY) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setAScaleY(scaleY); +} + +float spine_bone_get_a_shear_x(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getAShearX(); +} + +void spine_bone_set_a_shear_x(spine_bone bone, float shearX) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setAShearX(shearX); +} + +float spine_bone_get_a_shear_y(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getAShearY(); +} + +void spine_bone_set_a_shear_y(spine_bone bone, float shearY) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setAShearY(shearY); +} + +float spine_bone_get_a(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getA(); +} + +void spine_bone_set_a(spine_bone bone, float a) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setA(a); +} + +float spine_bone_get_b(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getB(); +} + +void spine_bone_set_b(spine_bone bone, float b) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setB(b); +} + +float spine_bone_get_c(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getC(); +} + +void spine_bone_set_c(spine_bone bone, float c) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setC(c); +} + +float spine_bone_get_d(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getD(); +} + +void spine_bone_set_d(spine_bone bone, float d) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setD(d); +} + +float spine_bone_get_world_x(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getWorldX(); +} + +void spine_bone_set_world_x(spine_bone bone, float worldX) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setWorldX(worldX); +} + +float spine_bone_get_world_y(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getWorldY(); +} + +void spine_bone_set_world_y(spine_bone bone, float worldY) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setWorldY(worldY); +} + +float spine_bone_get_world_rotation_x(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getWorldRotationX(); +} + +float spine_bone_get_world_rotation_y(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getWorldToLocalRotationY(); +} + +float spine_bone_get_world_scale_x(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getWorldScaleX(); +} + +float spine_bone_get_world_scale_y(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->getWorldScaleY(); +} + +spine_bool spine_bone_get_is_active(spine_bone bone) { + if (bone == nullptr) return 0; + Bone *_bone = (Bone *) bone; + return _bone->isActive() ? -1 : 0; +} + +void spine_bone_set_is_active(spine_bone bone, spine_bool isActive) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setActive(isActive); +} + +spine_inherit spine_bone_get_inherit(spine_bone bone) { + if (bone == nullptr) return SPINE_INHERIT_NORMAL; + Bone *_bone = (Bone *) bone; + return (spine_inherit) _bone->getInherit(); +} + +void spine_bone_set_inherit(spine_bone bone, spine_inherit inherit) { + if (bone == nullptr) return; + Bone *_bone = (Bone *) bone; + _bone->setInherit((spine::Inherit) inherit); +} + +// Attachment +const utf8 *spine_attachment_get_name(spine_attachment attachment) { + if (attachment == nullptr) return nullptr; + Attachment *_attachment = (Attachment *) attachment; + return (utf8 *) _attachment->getName().buffer(); +} + +spine_attachment_type spine_attachment_get_type(spine_attachment attachment) { + if (attachment == nullptr) return SPINE_ATTACHMENT_REGION; + Attachment *_attachment = (Attachment *) attachment; + if (_attachment->getRTTI().isExactly(RegionAttachment::rtti)) { + return SPINE_ATTACHMENT_REGION; + } else if (_attachment->getRTTI().isExactly(MeshAttachment::rtti)) { + return SPINE_ATTACHMENT_MESH; + } else if (_attachment->getRTTI().isExactly(ClippingAttachment::rtti)) { + return SPINE_ATTACHMENT_CLIPPING; + } else if (_attachment->getRTTI().isExactly(BoundingBoxAttachment::rtti)) { + return SPINE_ATTACHMENT_BOUNDING_BOX; + } else if (_attachment->getRTTI().isExactly(PathAttachment::rtti)) { + return SPINE_ATTACHMENT_PATH; + } else if (_attachment->getRTTI().isExactly(PointAttachment::rtti)) { + return SPINE_ATTACHMENT_POINT; + } else { + return SPINE_ATTACHMENT_REGION; + } +} + +spine_attachment spine_attachment_copy(spine_attachment attachment) { + if (attachment == nullptr) return nullptr; + Attachment *_attachment = (Attachment *) attachment; + return (spine_attachment) _attachment->copy(); +} + +spine_bounding_box_attachment spine_attachment_cast_to_bounding_box_attachment(spine_attachment attachment) { + if (attachment == nullptr) return nullptr; + Attachment *_attachment = (Attachment *) attachment; + if (_attachment->getRTTI().isExactly(BoundingBoxAttachment::rtti)) { + BoundingBoxAttachment *boundingBox = static_cast(_attachment); + return (spine_bounding_box_attachment) boundingBox; + } + return nullptr; +} + +void spine_attachment_dispose(spine_attachment attachment) { + if (attachment == nullptr) return; + Attachment *_attachment = (Attachment *) attachment; + delete _attachment; +} + +// PointAttachment +spine_vector spine_point_attachment_compute_world_position(spine_point_attachment attachment, spine_bone bone) { + _spine_vector *result = &tmp_vector; + if (attachment == nullptr) return (spine_vector) result; + PointAttachment *_attachment = (PointAttachment *) attachment; + _attachment->computeWorldPosition(*(Bone *) bone, result->x, result->y); + return (spine_vector) result; +} + +float spine_point_attachment_compute_world_rotation(spine_point_attachment attachment, spine_bone bone) { + if (attachment == nullptr) return 0; + PointAttachment *_attachment = (PointAttachment *) attachment; + return _attachment->computeWorldRotation(*(Bone *) bone); +} + +float spine_point_attachment_get_x(spine_point_attachment attachment) { + if (attachment == nullptr) return 0; + PointAttachment *_attachment = (PointAttachment *) attachment; + return _attachment->getX(); +} + +void spine_point_attachment_set_x(spine_point_attachment attachment, float x) { + if (attachment == nullptr) return; + PointAttachment *_attachment = (PointAttachment *) attachment; + _attachment->setX(x); +} + +float spine_point_attachment_get_y(spine_point_attachment attachment) { + if (attachment == nullptr) return 0; + PointAttachment *_attachment = (PointAttachment *) attachment; + return _attachment->getY(); +} + +void spine_point_attachment_set_y(spine_point_attachment attachment, float y) { + if (attachment == nullptr) return; + PointAttachment *_attachment = (PointAttachment *) attachment; + _attachment->setY(y); +} + +float spine_point_attachment_get_rotation(spine_point_attachment attachment) { + if (attachment == nullptr) return 0; + PointAttachment *_attachment = (PointAttachment *) attachment; + return _attachment->getRotation(); +} + +void spine_point_attachment_set_rotation(spine_point_attachment attachment, float rotation) { + if (attachment == nullptr) return; + PointAttachment *_attachment = (PointAttachment *) attachment; + _attachment->setRotation(rotation); +} + +spine_color spine_point_attachment_get_color(spine_point_attachment attachment) { + if (attachment == nullptr) return (spine_color) &NULL_COLOR; + PointAttachment *_attachment = (PointAttachment *) attachment; + return (spine_color) &_attachment->getColor(); +} + +void spine_point_attachment_set_color(spine_point_attachment attachment, float r, float g, float b, float a) { + if (attachment == nullptr) return; + PointAttachment *_attachment = (PointAttachment *) attachment; + _attachment->getColor().set(r, g, b, a); +} + +// RegionAttachment +void spine_region_attachment_update_region(spine_region_attachment attachment) { + if (attachment == nullptr) return; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + _attachment->updateRegion(); +} + +void spine_region_attachment_compute_world_vertices(spine_region_attachment attachment, spine_slot slot, float *worldVertices) { + if (attachment == nullptr) return; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + _attachment->computeWorldVertices(*(Slot *) slot, worldVertices, 0); +} + +float spine_region_attachment_get_x(spine_region_attachment attachment) { + if (attachment == nullptr) return 0; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return _attachment->getX(); +} + +void spine_region_attachment_set_x(spine_region_attachment attachment, float x) { + if (attachment == nullptr) return; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + _attachment->setX(x); +} + +float spine_region_attachment_get_y(spine_region_attachment attachment) { + if (attachment == nullptr) return 0; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return _attachment->getY(); +} + +void spine_region_attachment_set_y(spine_region_attachment attachment, float y) { + if (attachment == nullptr) return; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + _attachment->setY(y); +} + +float spine_region_attachment_get_rotation(spine_region_attachment attachment) { + if (attachment == nullptr) return 0; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return _attachment->getRotation(); +} + +void spine_region_attachment_set_rotation(spine_region_attachment attachment, float rotation) { + if (attachment == nullptr) return; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + _attachment->setRotation(rotation); +} + +float spine_region_attachment_get_scale_x(spine_region_attachment attachment) { + if (attachment == nullptr) return 0; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return _attachment->getScaleX(); +} + +void spine_region_attachment_set_scale_x(spine_region_attachment attachment, float scaleX) { + if (attachment == nullptr) return; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + _attachment->setScaleX(scaleX); +} + +float spine_region_attachment_get_scale_y(spine_region_attachment attachment) { + if (attachment == nullptr) return 0; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return _attachment->getScaleY(); +} + +void spine_region_attachment_set_scale_y(spine_region_attachment attachment, float scaleY) { + if (attachment == nullptr) return; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + _attachment->setScaleY(scaleY); +} + +float spine_region_attachment_get_width(spine_region_attachment attachment) { + if (attachment == nullptr) return 0; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return _attachment->getWidth(); +} + +void spine_region_attachment_set_width(spine_region_attachment attachment, float width) { + if (attachment == nullptr) return; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + _attachment->setWidth(width); +} + +float spine_region_attachment_get_height(spine_region_attachment attachment) { + if (attachment == nullptr) return 0; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return _attachment->getHeight(); +} + +void spine_region_attachment_set_height(spine_region_attachment attachment, float height) { + if (attachment == nullptr) return; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + _attachment->setHeight(height); +} + +spine_color spine_region_attachment_get_color(spine_region_attachment attachment) { + if (attachment == nullptr) return (spine_color) &NULL_COLOR; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return (spine_color) &_attachment->getColor(); +} + +void spine_region_attachment_set_color(spine_region_attachment attachment, float r, float g, float b, float a) { + if (attachment == nullptr) return; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + _attachment->getColor().set(r, g, b, a); +} + +const utf8 *spine_region_attachment_get_path(spine_region_attachment attachment) { + if (attachment == nullptr) return nullptr; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return (utf8 *) _attachment->getPath().buffer(); +} + +spine_texture_region spine_region_attachment_get_region(spine_region_attachment attachment) { + if (attachment == nullptr) return nullptr; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return (spine_texture_region) _attachment->getRegion(); +} + +spine_sequence spine_region_attachment_get_sequence(spine_region_attachment attachment) { + if (attachment == nullptr) return nullptr; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return (spine_sequence) _attachment->getSequence(); +} + +int32_t spine_region_attachment_get_num_offset(spine_region_attachment attachment) { + if (attachment == nullptr) return 0; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return (int32_t) _attachment->getOffset().size(); +} + +float *spine_region_attachment_get_offset(spine_region_attachment attachment) { + if (attachment == nullptr) return nullptr; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return _attachment->getOffset().buffer(); +} + +int32_t spine_region_attachment_get_num_uvs(spine_region_attachment attachment) { + if (attachment == nullptr) return 0; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return (int32_t) _attachment->getUVs().size(); +} + +float *spine_region_attachment_get_uvs(spine_region_attachment attachment) { + if (attachment == nullptr) return nullptr; + RegionAttachment *_attachment = (RegionAttachment *) attachment; + return _attachment->getUVs().buffer(); +} + +// VertexAttachment +int32_t spine_vertex_attachment_get_world_vertices_length(spine_vertex_attachment attachment) { + if (attachment == nullptr) return 0; + VertexAttachment *_attachment = (VertexAttachment *) attachment; + return (int32_t) _attachment->getWorldVerticesLength(); +} + +void spine_vertex_attachment_compute_world_vertices(spine_vertex_attachment attachment, spine_slot slot, float *worldVertices) { + if (attachment == nullptr) return; + VertexAttachment *_attachment = (VertexAttachment *) attachment; + _attachment->computeWorldVertices(*(Slot *) slot, worldVertices); +} + +int32_t spine_vertex_attachment_get_num_bones(spine_vertex_attachment attachment) { + if (attachment == nullptr) return 0; + VertexAttachment *_attachment = (VertexAttachment *) attachment; + return (int32_t) _attachment->getBones().size(); +} + +int32_t *spine_vertex_attachment_get_bones(spine_vertex_attachment attachment) { + if (attachment == nullptr) return nullptr; + VertexAttachment *_attachment = (VertexAttachment *) attachment; + return _attachment->getBones().buffer(); +} + +// VertexAttachment +int32_t spine_vertex_attachment_get_num_vertices(spine_vertex_attachment attachment) { + if (attachment == nullptr) return 0; + VertexAttachment *_attachment = (VertexAttachment *) attachment; + return (int32_t) _attachment->getVertices().size(); +} + +float *spine_vertex_attachment_get_vertices(spine_vertex_attachment attachment) { + if (attachment == nullptr) return nullptr; + VertexAttachment *_attachment = (VertexAttachment *) attachment; + return _attachment->getVertices().buffer(); +} + +spine_attachment spine_vertex_attachment_get_timeline_attachment(spine_vertex_attachment attachment) { + if (attachment == nullptr) return nullptr; + VertexAttachment *_attachment = (VertexAttachment *) attachment; + return (spine_attachment) _attachment->getTimelineAttachment(); +} + +void spine_vertex_attachment_set_timeline_attachment(spine_vertex_attachment attachment, spine_attachment timelineAttachment) { + if (attachment == nullptr) return; + VertexAttachment *_attachment = (VertexAttachment *) attachment; + _attachment->setTimelineAttachment((Attachment *) timelineAttachment); +} + +// MeshAttachment +void spine_mesh_attachment_update_region(spine_mesh_attachment attachment) { + if (attachment == nullptr) return; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + _attachment->updateRegion(); +} + +int32_t spine_mesh_attachment_get_hull_length(spine_mesh_attachment attachment) { + if (attachment == nullptr) return 0; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return _attachment->getHullLength(); +} + +void spine_mesh_attachment_set_hull_length(spine_mesh_attachment attachment, int32_t hullLength) { + if (attachment == nullptr) return; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + _attachment->setHullLength(hullLength); +} + +int32_t spine_mesh_attachment_get_num_region_uvs(spine_mesh_attachment attachment) { + if (attachment == nullptr) return 0; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return (int32_t) _attachment->getRegionUVs().size(); +} + +float *spine_mesh_attachment_get_region_uvs(spine_mesh_attachment attachment) { + if (attachment == nullptr) return nullptr; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return _attachment->getRegionUVs().buffer(); +} + +int32_t spine_mesh_attachment_get_num_uvs(spine_mesh_attachment attachment) { + if (attachment == nullptr) return 0; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return (int32_t) _attachment->getUVs().size(); +} + +float *spine_mesh_attachment_get_uvs(spine_mesh_attachment attachment) { + if (attachment == nullptr) return 0; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return _attachment->getUVs().buffer(); +} + +int32_t spine_mesh_attachment_get_num_triangles(spine_mesh_attachment attachment) { + if (attachment == nullptr) return 0; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return (int32_t) _attachment->getTriangles().size(); +} + +uint16_t *spine_mesh_attachment_get_triangles(spine_mesh_attachment attachment) { + if (attachment == nullptr) return nullptr; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return _attachment->getTriangles().buffer(); +} + +spine_color spine_mesh_attachment_get_color(spine_mesh_attachment attachment) { + if (attachment == nullptr) return (spine_color) &NULL_COLOR; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return (spine_color) &_attachment->getColor(); +} + +void spine_mesh_attachment_set_color(spine_mesh_attachment attachment, float r, float g, float b, float a) { + if (attachment == nullptr) return; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + _attachment->getColor().set(r, g, b, a); +} + +const utf8 *spine_mesh_attachment_get_path(spine_mesh_attachment attachment) { + if (attachment == nullptr) return nullptr; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return (utf8 *) _attachment->getPath().buffer(); +} + +spine_texture_region spine_mesh_attachment_get_region(spine_mesh_attachment attachment) { + if (attachment == nullptr) return nullptr; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return (spine_texture_region) _attachment->getRegion(); +} + +spine_sequence spine_mesh_attachment_get_sequence(spine_mesh_attachment attachment) { + if (attachment == nullptr) return nullptr; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return (spine_sequence) _attachment->getSequence(); +} + +spine_mesh_attachment spine_mesh_attachment_get_parent_mesh(spine_mesh_attachment attachment) { + if (attachment == nullptr) return nullptr; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return (spine_mesh_attachment) _attachment->getParentMesh(); +} + +void spine_mesh_attachment_set_parent_mesh(spine_mesh_attachment attachment, spine_mesh_attachment parentMesh) { + if (attachment == nullptr) return; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + _attachment->setParentMesh((MeshAttachment *) parentMesh); +} + +int32_t spine_mesh_attachment_get_num_edges(spine_mesh_attachment attachment) { + if (attachment == nullptr) return 0; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return (int32_t) _attachment->getEdges().size(); +} + +unsigned short *spine_mesh_attachment_get_edges(spine_mesh_attachment attachment) { + if (attachment == nullptr) return nullptr; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return _attachment->getEdges().buffer(); +} + +float spine_mesh_attachment_get_width(spine_mesh_attachment attachment) { + if (attachment == nullptr) return 0; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return _attachment->getWidth(); +} + +void spine_mesh_attachment_set_width(spine_mesh_attachment attachment, float width) { + if (attachment == nullptr) return; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + _attachment->setWidth(width); +} + +float spine_mesh_attachment_get_height(spine_mesh_attachment attachment) { + if (attachment == nullptr) return 0; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + return _attachment->getHeight(); +} + +void spine_mesh_attachment_set_height(spine_mesh_attachment attachment, float height) { + if (attachment == nullptr) return; + MeshAttachment *_attachment = (MeshAttachment *) attachment; + _attachment->setHeight(height); +} + +// ClippingAttachment +spine_slot_data spine_clipping_attachment_get_end_slot(spine_clipping_attachment attachment) { + if (attachment == nullptr) return nullptr; + ClippingAttachment *_attachment = (ClippingAttachment *) attachment; + return (spine_slot_data) _attachment->getEndSlot(); +} + +void spine_clipping_attachment_set_end_slot(spine_clipping_attachment attachment, spine_slot_data endSlot) { + if (attachment == nullptr) return; + ClippingAttachment *_attachment = (ClippingAttachment *) attachment; + _attachment->setEndSlot((SlotData *) endSlot); +} + +spine_color spine_clipping_attachment_get_color(spine_clipping_attachment attachment) { + if (attachment == nullptr) return (spine_color) &NULL_COLOR; + ClippingAttachment *_attachment = (ClippingAttachment *) attachment; + return (spine_color) &_attachment->getColor(); +} + +void spine_clipping_attachment_set_color(spine_clipping_attachment attachment, float r, float g, float b, float a) { + if (attachment == nullptr) return; + ClippingAttachment *_attachment = (ClippingAttachment *) attachment; + _attachment->getColor().set(r, g, b, a); +} + +// BoundingBoxAttachment +spine_color spine_bounding_box_attachment_get_color(spine_bounding_box_attachment attachment) { + if (attachment == nullptr) return (spine_color) &NULL_COLOR; + BoundingBoxAttachment *_attachment = (BoundingBoxAttachment *) attachment; + return (spine_color) &_attachment->getColor(); +} + +void spine_bounding_box_attachment_set_color(spine_bounding_box_attachment attachment, float r, float g, float b, float a) { + if (attachment == nullptr) return; + BoundingBoxAttachment *_attachment = (BoundingBoxAttachment *) attachment; + _attachment->getColor().set(r, g, b, a); +} + +// PathAttachment +int32_t spine_path_attachment_get_num_lengths(spine_path_attachment attachment) { + if (attachment == nullptr) return 0; + PathAttachment *_attachment = (PathAttachment *) attachment; + return (int32_t) _attachment->getLengths().size(); +} + +float *spine_path_attachment_get_lengths(spine_path_attachment attachment) { + if (attachment == nullptr) return nullptr; + PathAttachment *_attachment = (PathAttachment *) attachment; + return _attachment->getLengths().buffer(); +} + +spine_bool spine_path_attachment_get_is_closed(spine_path_attachment attachment) { + if (attachment == nullptr) return 0; + PathAttachment *_attachment = (PathAttachment *) attachment; + return _attachment->isClosed() ? -1 : 0; +} + +void spine_path_attachment_set_is_closed(spine_path_attachment attachment, spine_bool isClosed) { + if (attachment == nullptr) return; + PathAttachment *_attachment = (PathAttachment *) attachment; + _attachment->setClosed(isClosed); +} + +spine_bool spine_path_attachment_get_is_constant_speed(spine_path_attachment attachment) { + if (attachment == nullptr) return 0; + PathAttachment *_attachment = (PathAttachment *) attachment; + return _attachment->isConstantSpeed() ? -1 : 0; +} + +void spine_path_attachment_set_is_constant_speed(spine_path_attachment attachment, spine_bool isConstantSpeed) { + if (attachment == nullptr) return; + PathAttachment *_attachment = (PathAttachment *) attachment; + _attachment->setConstantSpeed(isConstantSpeed); +} + +spine_color spine_path_attachment_get_color(spine_path_attachment attachment) { + if (attachment == nullptr) return (spine_color) &NULL_COLOR; + PathAttachment *_attachment = (PathAttachment *) attachment; + return (spine_color) &_attachment->getColor(); +} + +void spine_path_attachment_set_color(spine_path_attachment attachment, float r, float g, float b, float a) { + if (attachment == nullptr) return; + PathAttachment *_attachment = (PathAttachment *) attachment; + _attachment->getColor().set(r, g, b, a); +} + +// Skin +void spine_skin_set_attachment(spine_skin skin, int32_t slotIndex, const utf8 *name, spine_attachment attachment) { + if (skin == nullptr) return; + Skin *_skin = (Skin *) skin; + _skin->setAttachment(slotIndex, name, (Attachment *) attachment); +} + +spine_attachment spine_skin_get_attachment(spine_skin skin, int32_t slotIndex, const utf8 *name) { + if (skin == nullptr) return nullptr; + Skin *_skin = (Skin *) skin; + return (spine_attachment) _skin->getAttachment(slotIndex, name); +} + +void spine_skin_remove_attachment(spine_skin skin, int32_t slotIndex, const utf8 *name) { + if (skin == nullptr) return; + Skin *_skin = (Skin *) skin; + _skin->removeAttachment(slotIndex, name); +} + +const utf8 *spine_skin_get_name(spine_skin skin) { + if (skin == nullptr) return nullptr; + Skin *_skin = (Skin *) skin; + return (utf8 *) _skin->getName().buffer(); +} + +void spine_skin_add_skin(spine_skin skin, spine_skin other) { + if (skin == nullptr) return; + if (other == nullptr) return; + Skin *_skin = (Skin *) skin; + _skin->addSkin((Skin *) other); +} + +void spine_skin_copy_skin(spine_skin skin, spine_skin other) { + if (skin == nullptr) return; + if (other == nullptr) return; + Skin *_skin = (Skin *) skin; + _skin->copySkin((Skin *) other); +} + +spine_skin_entries spine_skin_get_entries(spine_skin skin) { + if (skin == nullptr) return nullptr; + Skin *_skin = (Skin *) skin; + _spine_skin_entries *entries = SpineExtension::getInstance()->calloc<_spine_skin_entries>(1, __FILE__, __LINE__); + { + Skin::AttachmentMap::Entries mapEntries = _skin->getAttachments(); + while (mapEntries.hasNext()) { + entries->numEntries++; + mapEntries.next(); + } + } + { + entries->entries = SpineExtension::getInstance()->calloc<_spine_skin_entry>(entries->numEntries, __FILE__, __LINE__); + Skin::AttachmentMap::Entries mapEntries = _skin->getAttachments(); + int32_t i = 0; + while (mapEntries.hasNext()) { + Skin::AttachmentMap::Entry entry = mapEntries.next(); + entries->entries[i++] = {(int32_t) entry._slotIndex, (utf8 *) entry._name.buffer(), (spine_attachment) entry._attachment}; + } + } + return (spine_skin_entries) entries; +} + +int32_t spine_skin_entries_get_num_entries(spine_skin_entries entries) { + if (!entries) return 0; + return ((_spine_skin_entries *) entries)->numEntries; +} + +spine_skin_entry spine_skin_entries_get_entry(spine_skin_entries entries, int32_t index) { + if (!entries) return 0; + return (spine_skin_entry) & ((_spine_skin_entries *) entries)->entries[index]; +} + +void spine_skin_entries_dispose(spine_skin_entries entries) { + if (entries == nullptr) return; + SpineExtension::getInstance()->free(((_spine_skin_entries *) entries)->entries, __FILE__, __LINE__); + SpineExtension::getInstance()->free(entries, __FILE__, __LINE__); +} + +int32_t spine_skin_entry_get_slot_index(spine_skin_entry entry) { + if (!entry) return 0; + return ((_spine_skin_entry *) entry)->slotIndex; +} + +utf8 *spine_skin_entry_get_name(spine_skin_entry entry) { + if (!entry) return nullptr; + return ((_spine_skin_entry *) entry)->name; +} + +spine_attachment spine_skin_entry_get_attachment(spine_skin_entry entry) { + if (!entry) return nullptr; + return ((_spine_skin_entry *) entry)->attachment; +} + +int32_t spine_skin_get_num_bones(spine_skin skin) { + if (skin == nullptr) return 0; + Skin *_skin = (Skin *) skin; + return (int32_t) _skin->getBones().size(); +} + +spine_bone_data *spine_skin_get_bones(spine_skin skin) { + if (skin == nullptr) return nullptr; + Skin *_skin = (Skin *) skin; + return (spine_bone_data *) _skin->getBones().buffer(); +} + +int32_t spine_skin_get_num_constraints(spine_skin skin) { + if (skin == nullptr) return 0; + Skin *_skin = (Skin *) skin; + return (int32_t) _skin->getConstraints().size(); +} + +spine_constraint_data *spine_skin_get_constraints(spine_skin skin) { + if (skin == nullptr) return nullptr; + Skin *_skin = (Skin *) skin; + return (spine_constraint_data *) _skin->getConstraints().buffer(); +} + +spine_skin spine_skin_create(const utf8 *name) { + if (name == nullptr) return nullptr; + return (spine_skin) new (__FILE__, __LINE__) Skin(name); +} + +void spine_skin_dispose(spine_skin skin) { + if (skin == nullptr) return; + Skin *_skin = (Skin *) skin; + delete _skin; +} + +// ConstraintData +spine_constraint_type spine_constraint_data_get_type(spine_constraint_data data) { + if (data == nullptr) return SPINE_CONSTRAINT_IK; + ConstraintData *_data = (ConstraintData *) data; + if (_data->getRTTI().isExactly(IkConstraintData::rtti)) { + return SPINE_CONSTRAINT_IK; + } else if (_data->getRTTI().isExactly(TransformConstraintData::rtti)) { + return SPINE_CONSTRAINT_TRANSFORM; + } else if (_data->getRTTI().isExactly(PathConstraintData::rtti)) { + return SPINE_CONSTRAINT_PATH; + } else { + return SPINE_CONSTRAINT_IK; + } +} + +const utf8 *spine_constraint_data_get_name(spine_constraint_data data) { + if (data == nullptr) return nullptr; + ConstraintData *_data = (ConstraintData *) data; + return (utf8 *) _data->getName().buffer(); +} + +uint64_t spine_constraint_data_get_order(spine_constraint_data data) { + if (data == nullptr) return 0; + ConstraintData *_data = (ConstraintData *) data; + return (uint64_t) _data->getOrder(); +} + +void spine_constraint_data_set_order(spine_constraint_data data, uint64_t order) { + if (data == nullptr) return; + ConstraintData *_data = (ConstraintData *) data; + _data->setOrder((size_t) order); +} + +spine_bool spine_constraint_data_get_is_skin_required(spine_constraint_data data) { + if (data == nullptr) return 0; + ConstraintData *_data = (ConstraintData *) data; + return _data->isSkinRequired() ? -1 : 0; +} + +void spine_constraint_data_set_is_skin_required(spine_constraint_data data, spine_bool isSkinRequired) { + if (data == nullptr) return; + ConstraintData *_data = (ConstraintData *) data; + _data->setSkinRequired(isSkinRequired); +} + +// IkConstraintData +int32_t spine_ik_constraint_data_get_num_bones(spine_ik_constraint_data data) { + if (data == nullptr) return 0; + IkConstraintData *_data = (IkConstraintData *) data; + return (int32_t) _data->getBones().size(); +} + +spine_bone_data *spine_ik_constraint_data_get_bones(spine_ik_constraint_data data) { + if (data == nullptr) return nullptr; + IkConstraintData *_data = (IkConstraintData *) data; + return (spine_bone_data *) _data->getBones().buffer(); +} + +spine_bone_data spine_ik_constraint_data_get_target(spine_ik_constraint_data data) { + if (data == nullptr) return nullptr; + IkConstraintData *_data = (IkConstraintData *) data; + return (spine_bone_data) _data->getTarget(); +} + +void spine_ik_constraint_data_set_target(spine_ik_constraint_data data, spine_bone_data target) { + if (data == nullptr) return; + IkConstraintData *_data = (IkConstraintData *) data; + _data->setTarget((BoneData *) target); +} + +int32_t spine_ik_constraint_data_get_bend_direction(spine_ik_constraint_data data) { + if (data == nullptr) return 1; + IkConstraintData *_data = (IkConstraintData *) data; + return _data->getBendDirection(); +} + +void spine_ik_constraint_data_set_bend_direction(spine_ik_constraint_data data, int32_t bendDirection) { + if (data == nullptr) return; + IkConstraintData *_data = (IkConstraintData *) data; + _data->setBendDirection(bendDirection); +} + +spine_bool spine_ik_constraint_data_get_compress(spine_ik_constraint_data data) { + if (data == nullptr) return 0; + IkConstraintData *_data = (IkConstraintData *) data; + return _data->getCompress() ? -1 : 0; +} + +void spine_ik_constraint_data_set_compress(spine_ik_constraint_data data, spine_bool compress) { + if (data == nullptr) return; + IkConstraintData *_data = (IkConstraintData *) data; + _data->setCompress(compress); +} + +spine_bool spine_ik_constraint_data_get_stretch(spine_ik_constraint_data data) { + if (data == nullptr) return 0; + IkConstraintData *_data = (IkConstraintData *) data; + return _data->getStretch() ? -1 : 0; +} + +void spine_ik_constraint_data_set_stretch(spine_ik_constraint_data data, spine_bool stretch) { + if (data == nullptr) return; + IkConstraintData *_data = (IkConstraintData *) data; + _data->setStretch(stretch); +} + +spine_bool spine_ik_constraint_data_get_uniform(spine_ik_constraint_data data) { + if (data == nullptr) return 0; + IkConstraintData *_data = (IkConstraintData *) data; + return _data->getUniform() ? -1 : 0; +} + +void spine_ik_constraint_data_set_uniform(spine_ik_constraint_data data, spine_bool uniform) { + if (data == nullptr) return; + IkConstraintData *_data = (IkConstraintData *) data; + _data->setUniform(uniform); +} + +float spine_ik_constraint_data_get_mix(spine_ik_constraint_data data) { + if (data == nullptr) return 0; + IkConstraintData *_data = (IkConstraintData *) data; + return _data->getMix(); +} + +void spine_ik_constraint_data_set_mix(spine_ik_constraint_data data, float mix) { + if (data == nullptr) return; + IkConstraintData *_data = (IkConstraintData *) data; + _data->setMix(mix); +} + +float spine_ik_constraint_data_get_softness(spine_ik_constraint_data data) { + if (data == nullptr) return 0; + IkConstraintData *_data = (IkConstraintData *) data; + return _data->getSoftness(); +} + +void spine_ik_constraint_data_set_softness(spine_ik_constraint_data data, float softness) { + if (data == nullptr) return; + IkConstraintData *_data = (IkConstraintData *) data; + _data->setSoftness(softness); +} + +// IKConstraint +void spine_ik_constraint_update(spine_ik_constraint constraint) { + if (constraint == nullptr) return; + IkConstraint *_constraint = (IkConstraint *) constraint; + _constraint->update(spine::Physics_Update); +} + +int32_t spine_ik_constraint_get_order(spine_ik_constraint constraint) { + if (constraint == nullptr) return 0; + IkConstraint *_constraint = (IkConstraint *) constraint; + return _constraint->getOrder(); +} + +spine_ik_constraint_data spine_ik_constraint_get_data(spine_ik_constraint constraint) { + if (constraint == nullptr) return nullptr; + IkConstraint *_constraint = (IkConstraint *) constraint; + return (spine_ik_constraint_data) &_constraint->getData(); +} + +int32_t spine_ik_constraint_get_num_bones(spine_ik_constraint constraint) { + if (constraint == nullptr) return 0; + IkConstraint *_constraint = (IkConstraint *) constraint; + return (int32_t) _constraint->getBones().size(); +} + +spine_bone *spine_ik_constraint_get_bones(spine_ik_constraint constraint) { + if (constraint == nullptr) return nullptr; + IkConstraint *_constraint = (IkConstraint *) constraint; + return (spine_bone *) _constraint->getBones().buffer(); +} + +spine_bone spine_ik_constraint_get_target(spine_ik_constraint constraint) { + if (constraint == nullptr) return nullptr; + IkConstraint *_constraint = (IkConstraint *) constraint; + return (spine_bone) _constraint->getTarget(); +} + +void spine_ik_constraint_set_target(spine_ik_constraint constraint, spine_bone target) { + if (constraint == nullptr) return; + IkConstraint *_constraint = (IkConstraint *) constraint; + _constraint->setTarget((Bone *) target); +} + +int32_t spine_ik_constraint_get_bend_direction(spine_ik_constraint constraint) { + if (constraint == nullptr) return 1; + IkConstraint *_constraint = (IkConstraint *) constraint; + return _constraint->getBendDirection(); +} + +void spine_ik_constraint_set_bend_direction(spine_ik_constraint constraint, int32_t bendDirection) { + if (constraint == nullptr) return; + IkConstraint *_constraint = (IkConstraint *) constraint; + _constraint->setBendDirection(bendDirection); +} + +spine_bool spine_ik_constraint_get_compress(spine_ik_constraint constraint) { + if (constraint == nullptr) return 0; + IkConstraint *_constraint = (IkConstraint *) constraint; + return _constraint->getCompress() ? -1 : 0; +} + +void spine_ik_constraint_set_compress(spine_ik_constraint constraint, spine_bool compress) { + if (constraint == nullptr) return; + IkConstraint *_constraint = (IkConstraint *) constraint; + _constraint->setCompress(compress); +} + +spine_bool spine_ik_constraint_get_stretch(spine_ik_constraint constraint) { + if (constraint == nullptr) return 0; + IkConstraint *_constraint = (IkConstraint *) constraint; + return _constraint->getStretch() ? -1 : 0; +} + +void spine_ik_constraint_set_stretch(spine_ik_constraint constraint, spine_bool stretch) { + if (constraint == nullptr) return; + IkConstraint *_constraint = (IkConstraint *) constraint; + _constraint->setStretch(stretch); +} + +float spine_ik_constraint_get_mix(spine_ik_constraint constraint) { + if (constraint == nullptr) return 0; + IkConstraint *_constraint = (IkConstraint *) constraint; + return _constraint->getMix(); +} + +void spine_ik_constraint_set_mix(spine_ik_constraint constraint, float mix) { + if (constraint == nullptr) return; + IkConstraint *_constraint = (IkConstraint *) constraint; + _constraint->setMix(mix); +} + +float spine_ik_constraint_get_softness(spine_ik_constraint constraint) { + if (constraint == nullptr) return 0; + IkConstraint *_constraint = (IkConstraint *) constraint; + return _constraint->getSoftness(); +} + +void spine_ik_constraint_set_softness(spine_ik_constraint constraint, float softness) { + if (constraint == nullptr) return; + IkConstraint *_constraint = (IkConstraint *) constraint; + _constraint->setSoftness(softness); +} + +spine_bool spine_ik_constraint_get_is_active(spine_ik_constraint constraint) { + if (constraint == nullptr) return 0; + IkConstraint *_constraint = (IkConstraint *) constraint; + return _constraint->isActive() ? -1 : 0; +} + +void spine_ik_constraint_set_is_active(spine_ik_constraint constraint, spine_bool isActive) { + if (constraint == nullptr) return; + IkConstraint *_constraint = (IkConstraint *) constraint; + _constraint->setActive(isActive); +} + +// TransformConstraintData +int32_t spine_transform_constraint_data_get_num_bones(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return (int32_t) _data->getBones().size(); +} + +spine_bone_data *spine_transform_constraint_data_get_bones(spine_transform_constraint_data data) { + if (data == nullptr) return nullptr; + TransformConstraintData *_data = (TransformConstraintData *) data; + return (spine_bone_data *) _data->getBones().buffer(); +} + +spine_bone_data spine_transform_constraint_data_get_target(spine_transform_constraint_data data) { + if (data == nullptr) return nullptr; + TransformConstraintData *_data = (TransformConstraintData *) data; + return (spine_bone_data) _data->getTarget(); +} + +void spine_transform_constraint_data_set_target(spine_transform_constraint_data data, spine_bone_data target) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setTarget((BoneData *) target); +} + +float spine_transform_constraint_data_get_mix_rotate(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->getMixRotate(); +} + +void spine_transform_constraint_data_set_mix_rotate(spine_transform_constraint_data data, float mixRotate) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setMixRotate(mixRotate); +} + +float spine_transform_constraint_data_get_mix_x(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->getMixX(); +} + +void spine_transform_constraint_data_set_mix_x(spine_transform_constraint_data data, float mixX) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setMixX(mixX); +} + +float spine_transform_constraint_data_get_mix_y(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->getMixY(); +} + +void spine_transform_constraint_data_set_mix_y(spine_transform_constraint_data data, float mixY) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setMixY(mixY); +} + +float spine_transform_constraint_data_get_mix_scale_x(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->getMixScaleX(); +} + +void spine_transform_constraint_data_set_mix_scale_x(spine_transform_constraint_data data, float mixScaleX) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setMixScaleX(mixScaleX); +} + +float spine_transform_constraint_data_get_mix_scale_y(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->getMixScaleY(); +} + +void spine_transform_constraint_data_set_mix_scale_y(spine_transform_constraint_data data, float mixScaleY) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setMixScaleY(mixScaleY); +} + +float spine_transform_constraint_data_get_mix_shear_y(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->getMixShearY(); +} + +void spine_transform_constraint_data_set_mix_shear_y(spine_transform_constraint_data data, float mixShearY) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setMixShearY(mixShearY); +} + +float spine_transform_constraint_data_get_offset_rotation(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->getOffsetRotation(); +} + +void spine_transform_constraint_data_set_offset_rotation(spine_transform_constraint_data data, float offsetRotation) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setOffsetRotation(offsetRotation); +} + +float spine_transform_constraint_data_get_offset_x(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->getOffsetX(); +} + +void spine_transform_constraint_data_set_offset_x(spine_transform_constraint_data data, float offsetX) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setOffsetX(offsetX); +} + +float spine_transform_constraint_data_get_offset_y(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->getOffsetY(); +} + +void spine_transform_constraint_data_set_offset_y(spine_transform_constraint_data data, float offsetY) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setOffsetY(offsetY); +} + +float spine_transform_constraint_data_get_offset_scale_x(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->getOffsetScaleX(); +} + +void spine_transform_constraint_data_set_offset_scale_x(spine_transform_constraint_data data, float offsetScaleX) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setOffsetScaleX(offsetScaleX); +} + +float spine_transform_constraint_data_get_offset_scale_y(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->getOffsetScaleY(); +} + +void spine_transform_constraint_data_set_offset_scale_y(spine_transform_constraint_data data, float offsetScaleY) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setOffsetScaleY(offsetScaleY); +} + +float spine_transform_constraint_data_get_offset_shear_y(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->getOffsetShearY(); +} + +void spine_transform_constraint_data_set_offset_shear_y(spine_transform_constraint_data data, float offsetShearY) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setOffsetShearY(offsetShearY); +} + +spine_bool spine_transform_constraint_data_get_is_relative(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->isRelative() ? -1 : 0; +} + +void spine_transform_constraint_data_set_is_relative(spine_transform_constraint_data data, spine_bool isRelative) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setRelative(isRelative); +} + +spine_bool spine_transform_constraint_data_get_is_local(spine_transform_constraint_data data) { + if (data == nullptr) return 0; + TransformConstraintData *_data = (TransformConstraintData *) data; + return _data->isLocal() ? -1 : 0; +} + +void spine_transform_constraint_data_set_is_local(spine_transform_constraint_data data, spine_bool isLocal) { + if (data == nullptr) return; + TransformConstraintData *_data = (TransformConstraintData *) data; + _data->setLocal(isLocal); +} + +// TransformConstraint +void spine_transform_constraint_update(spine_transform_constraint constraint) { + if (constraint == nullptr) return; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + _constraint->update(spine::Physics_Update); +} + +int32_t spine_transform_constraint_get_order(spine_transform_constraint constraint) { + if (constraint == nullptr) return 0; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + return _constraint->getOrder(); +} + +spine_transform_constraint_data spine_transform_constraint_get_data(spine_transform_constraint constraint) { + if (constraint == nullptr) return nullptr; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + return (spine_transform_constraint_data) &_constraint->getData(); +} + +int32_t spine_transform_constraint_get_num_bones(spine_transform_constraint constraint) { + if (constraint == nullptr) return 0; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + return (int32_t) _constraint->getBones().size(); +} + +spine_bone *spine_transform_constraint_get_bones(spine_transform_constraint constraint) { + if (constraint == nullptr) return nullptr; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + return (spine_bone *) _constraint->getBones().buffer(); +} + +spine_bone spine_transform_constraint_get_target(spine_transform_constraint constraint) { + if (constraint == nullptr) return nullptr; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + return (spine_bone) _constraint->getTarget(); +} + +void spine_transform_constraint_set_target(spine_transform_constraint constraint, spine_bone target) { + if (constraint == nullptr) return; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + _constraint->setTarget((Bone *) target); +} + +float spine_transform_constraint_get_mix_rotate(spine_transform_constraint constraint) { + if (constraint == nullptr) return 0; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + return _constraint->getMixRotate(); +} + +void spine_transform_constraint_set_mix_rotate(spine_transform_constraint constraint, float mixRotate) { + if (constraint == nullptr) return; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + _constraint->setMixRotate(mixRotate); +} + +float spine_transform_constraint_get_mix_x(spine_transform_constraint constraint) { + if (constraint == nullptr) return 0; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + return _constraint->getMixX(); +} + +void spine_transform_constraint_set_mix_x(spine_transform_constraint constraint, float mixX) { + if (constraint == nullptr) return; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + _constraint->setMixX(mixX); +} + +float spine_transform_constraint_get_mix_y(spine_transform_constraint constraint) { + if (constraint == nullptr) return 0; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + return _constraint->getMixY(); +} + +void spine_transform_constraint_set_mix_y(spine_transform_constraint constraint, float mixY) { + if (constraint == nullptr) return; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + _constraint->setMixY(mixY); +} + +float spine_transform_constraint_get_mix_scale_x(spine_transform_constraint constraint) { + if (constraint == nullptr) return 0; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + return _constraint->getMixScaleX(); +} + +void spine_transform_constraint_set_mix_scale_x(spine_transform_constraint constraint, float mixScaleX) { + if (constraint == nullptr) return; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + _constraint->setMixScaleX(mixScaleX); +} + +float spine_transform_constraint_get_mix_scale_y(spine_transform_constraint constraint) { + if (constraint == nullptr) return 0; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + return _constraint->getMixScaleY(); +} + +void spine_transform_constraint_set_mix_scale_y(spine_transform_constraint constraint, float mixScaleY) { + if (constraint == nullptr) return; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + _constraint->setMixScaleY(mixScaleY); +} + +float spine_transform_constraint_get_mix_shear_y(spine_transform_constraint constraint) { + if (constraint == nullptr) return 0; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + return _constraint->getMixShearY(); +} + +void spine_transform_constraint_set_mix_shear_y(spine_transform_constraint constraint, float mixShearY) { + if (constraint == nullptr) return; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + _constraint->setMixShearY(mixShearY); +} + +spine_bool spine_transform_constraint_get_is_active(spine_transform_constraint constraint) { + if (constraint == nullptr) return 0; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + return _constraint->isActive() ? -1 : 0; +} + +void spine_transform_constraint_set_is_active(spine_transform_constraint constraint, spine_bool isActive) { + if (constraint == nullptr) return; + TransformConstraint *_constraint = (TransformConstraint *) constraint; + _constraint->setActive(isActive); +} + +// PathConstraintData +int32_t spine_path_constraint_data_get_num_bones(spine_path_constraint_data data) { + if (data == nullptr) return 0; + PathConstraintData *_data = (PathConstraintData *) data; + return (int32_t) _data->getBones().size(); +} + +spine_bone_data *spine_path_constraint_data_get_bones(spine_path_constraint_data data) { + if (data == nullptr) return nullptr; + PathConstraintData *_data = (PathConstraintData *) data; + return (spine_bone_data *) _data->getBones().buffer(); +} + +spine_slot_data spine_path_constraint_data_get_target(spine_path_constraint_data data) { + if (data == nullptr) return nullptr; + PathConstraintData *_data = (PathConstraintData *) data; + return (spine_slot_data) _data->getTarget(); +} + +void spine_path_constraint_data_set_target(spine_path_constraint_data data, spine_slot_data target) { + if (data == nullptr) return; + PathConstraintData *_data = (PathConstraintData *) data; + _data->setTarget((SlotData *) target); +} + +spine_position_mode spine_path_constraint_data_get_position_mode(spine_path_constraint_data data) { + if (data == nullptr) return SPINE_POSITION_MODE_FIXED; + PathConstraintData *_data = (PathConstraintData *) data; + return (spine_position_mode) _data->getPositionMode(); +} + +void spine_path_constraint_data_set_position_mode(spine_path_constraint_data data, spine_position_mode positionMode) { + if (data == nullptr) return; + PathConstraintData *_data = (PathConstraintData *) data; + _data->setPositionMode((PositionMode) positionMode); +} + +spine_spacing_mode spine_path_constraint_data_get_spacing_mode(spine_path_constraint_data data) { + if (data == nullptr) return SPINE_SPACING_MODE_LENGTH; + PathConstraintData *_data = (PathConstraintData *) data; + return (spine_spacing_mode) _data->getSpacingMode(); +} + +void spine_path_constraint_data_set_spacing_mode(spine_path_constraint_data data, spine_spacing_mode spacingMode) { + if (data == nullptr) return; + PathConstraintData *_data = (PathConstraintData *) data; + _data->setSpacingMode((SpacingMode) spacingMode); +} + +spine_rotate_mode spine_path_constraint_data_get_rotate_mode(spine_path_constraint_data data) { + if (data == nullptr) return SPINE_ROTATE_MODE_TANGENT; + PathConstraintData *_data = (PathConstraintData *) data; + return (spine_rotate_mode) _data->getRotateMode(); +} + +void spine_path_constraint_data_set_rotate_mode(spine_path_constraint_data data, spine_rotate_mode rotateMode) { + if (data == nullptr) return; + PathConstraintData *_data = (PathConstraintData *) data; + _data->setRotateMode((RotateMode) rotateMode); +} + +float spine_path_constraint_data_get_offset_rotation(spine_path_constraint_data data) { + if (data == nullptr) return 0; + PathConstraintData *_data = (PathConstraintData *) data; + return _data->getOffsetRotation(); +} + +void spine_path_constraint_data_set_offset_rotation(spine_path_constraint_data data, float offsetRotation) { + if (data == nullptr) return; + PathConstraintData *_data = (PathConstraintData *) data; + _data->setOffsetRotation(offsetRotation); +} + +float spine_path_constraint_data_get_position(spine_path_constraint_data data) { + if (data == nullptr) return 0; + PathConstraintData *_data = (PathConstraintData *) data; + return _data->getPosition(); +} + +void spine_path_constraint_data_set_position(spine_path_constraint_data data, float position) { + if (data == nullptr) return; + PathConstraintData *_data = (PathConstraintData *) data; + _data->setPosition(position); +} + +float spine_path_constraint_data_get_spacing(spine_path_constraint_data data) { + if (data == nullptr) return 0; + PathConstraintData *_data = (PathConstraintData *) data; + return _data->getSpacing(); +} + +void spine_path_constraint_data_set_spacing(spine_path_constraint_data data, float spacing) { + if (data == nullptr) return; + PathConstraintData *_data = (PathConstraintData *) data; + _data->setSpacing(spacing); +} + +float spine_path_constraint_data_get_mix_rotate(spine_path_constraint_data data) { + if (data == nullptr) return 0; + PathConstraintData *_data = (PathConstraintData *) data; + return _data->getMixRotate(); +} + +void spine_path_constraint_data_set_mix_rotate(spine_path_constraint_data data, float mixRotate) { + if (data == nullptr) return; + PathConstraintData *_data = (PathConstraintData *) data; + _data->setMixRotate(mixRotate); +} + +float spine_path_constraint_data_get_mix_x(spine_path_constraint_data data) { + if (data == nullptr) return 0; + PathConstraintData *_data = (PathConstraintData *) data; + return _data->getMixX(); +} + +void spine_path_constraint_data_set_mix_x(spine_path_constraint_data data, float mixX) { + if (data == nullptr) return; + PathConstraintData *_data = (PathConstraintData *) data; + _data->setMixX(mixX); +} + +float spine_path_constraint_data_get_mix_y(spine_path_constraint_data data) { + if (data == nullptr) return 0; + PathConstraintData *_data = (PathConstraintData *) data; + return _data->getMixY(); +} + +void spine_path_constraint_data_set_mix_y(spine_path_constraint_data data, float mixY) { + if (data == nullptr) return; + PathConstraintData *_data = (PathConstraintData *) data; + _data->setMixY(mixY); +} + +// PathConstraint +void spine_path_constraint_update(spine_path_constraint constraint) { + if (constraint == nullptr) return; + PathConstraint *_constraint = (PathConstraint *) constraint; + _constraint->update(spine::Physics_Update); +} + +int32_t spine_path_constraint_get_order(spine_path_constraint constraint) { + if (constraint == nullptr) return 0; + PathConstraint *_constraint = (PathConstraint *) constraint; + return _constraint->getOrder(); +} + +spine_path_constraint_data spine_path_constraint_get_data(spine_path_constraint constraint) { + if (constraint == nullptr) return nullptr; + PathConstraint *_constraint = (PathConstraint *) constraint; + return (spine_path_constraint_data) &_constraint->getData(); +} + +int32_t spine_path_constraint_get_num_bones(spine_path_constraint constraint) { + if (constraint == nullptr) return 0; + PathConstraint *_constraint = (PathConstraint *) constraint; + return (int32_t) _constraint->getBones().size(); +} + +spine_bone *spine_path_constraint_get_bones(spine_path_constraint constraint) { + if (constraint == nullptr) return nullptr; + PathConstraint *_constraint = (PathConstraint *) constraint; + return (spine_bone *) _constraint->getBones().buffer(); +} + +spine_slot spine_path_constraint_get_target(spine_path_constraint constraint) { + if (constraint == nullptr) return nullptr; + PathConstraint *_constraint = (PathConstraint *) constraint; + return (spine_slot) _constraint->getTarget(); +} + +void spine_path_constraint_set_target(spine_path_constraint constraint, spine_slot target) { + if (constraint == nullptr) return; + PathConstraint *_constraint = (PathConstraint *) constraint; + _constraint->setTarget((Slot *) target); +} + +float spine_path_constraint_get_position(spine_path_constraint constraint) { + if (constraint == nullptr) return 0; + PathConstraint *_constraint = (PathConstraint *) constraint; + return _constraint->getPosition(); +} + +void spine_path_constraint_set_position(spine_path_constraint constraint, float position) { + if (constraint == nullptr) return; + PathConstraint *_constraint = (PathConstraint *) constraint; + _constraint->setPosition(position); +} + +float spine_path_constraint_get_spacing(spine_path_constraint constraint) { + if (constraint == nullptr) return 0; + PathConstraint *_constraint = (PathConstraint *) constraint; + return _constraint->getSpacing(); +} + +void spine_path_constraint_set_spacing(spine_path_constraint constraint, float spacing) { + if (constraint == nullptr) return; + PathConstraint *_constraint = (PathConstraint *) constraint; + _constraint->setSpacing(spacing); +} + +float spine_path_constraint_get_mix_rotate(spine_path_constraint constraint) { + if (constraint == nullptr) return 0; + PathConstraint *_constraint = (PathConstraint *) constraint; + return _constraint->getMixRotate(); +} + +void spine_path_constraint_set_mix_rotate(spine_path_constraint constraint, float mixRotate) { + if (constraint == nullptr) return; + PathConstraint *_constraint = (PathConstraint *) constraint; + _constraint->setMixRotate(mixRotate); +} + +float spine_path_constraint_get_mix_x(spine_path_constraint constraint) { + if (constraint == nullptr) return 0; + PathConstraint *_constraint = (PathConstraint *) constraint; + return _constraint->getMixX(); +} + +void spine_path_constraint_set_mix_x(spine_path_constraint constraint, float mixX) { + if (constraint == nullptr) return; + PathConstraint *_constraint = (PathConstraint *) constraint; + _constraint->setMixX(mixX); +} + +float spine_path_constraint_get_mix_y(spine_path_constraint constraint) { + if (constraint == nullptr) return 0; + PathConstraint *_constraint = (PathConstraint *) constraint; + return _constraint->getMixY(); +} + +void spine_path_constraint_set_mix_y(spine_path_constraint constraint, float mixY) { + if (constraint == nullptr) return; + PathConstraint *_constraint = (PathConstraint *) constraint; + _constraint->setMixY(mixY); +} + +spine_bool spine_path_constraint_get_is_active(spine_path_constraint constraint) { + if (constraint == nullptr) return 0; + PathConstraint *_constraint = (PathConstraint *) constraint; + return _constraint->isActive() ? -1 : 0; +} + +void spine_path_constraint_set_is_active(spine_path_constraint constraint, spine_bool isActive) { + if (constraint == nullptr) return; + PathConstraint *_constraint = (PathConstraint *) constraint; + _constraint->setActive(isActive); +} + +// PhysicsConstraintData +void spine_physics_constraint_data_set_bone(spine_physics_constraint_data data, spine_bone_data bone) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setBone((BoneData *) bone); +} + +spine_bone_data spine_physics_constraint_data_get_bone(spine_physics_constraint_data data) { + if (data == nullptr) return nullptr; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return (spine_bone_data) _data->getBone(); +} + +void spine_physics_constraint_data_set_x(spine_physics_constraint_data data, float x) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setX(x); +} + +float spine_physics_constraint_data_get_x(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getX(); +} + +void spine_physics_constraint_data_set_y(spine_physics_constraint_data data, float y) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setY(y); +} + +float spine_physics_constraint_data_get_y(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getY(); +} + +void spine_physics_constraint_data_set_rotate(spine_physics_constraint_data data, float rotate) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setRotate(rotate); +} + +float spine_physics_constraint_data_get_rotate(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getRotate(); +} + +void spine_physics_constraint_data_set_scale_x(spine_physics_constraint_data data, float scaleX) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setScaleX(scaleX); +} + +float spine_physics_constraint_data_get_scale_x(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getScaleX(); +} + +void spine_physics_constraint_data_set_shear_x(spine_physics_constraint_data data, float shearX) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setShearX(shearX); +} + +float spine_physics_constraint_data_get_shear_x(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getShearX(); +} + +void spine_physics_constraint_data_set_limit(spine_physics_constraint_data data, float limit) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setLimit(limit); +} + +float spine_physics_constraint_data_get_limit(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getLimit(); +} + +void spine_physics_constraint_data_set_step(spine_physics_constraint_data data, float step) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setStep(step); +} + +float spine_physics_constraint_data_get_step(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getStep(); +} + +void spine_physics_constraint_data_set_inertia(spine_physics_constraint_data data, float inertia) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setInertia(inertia); +} + +float spine_physics_constraint_data_get_inertia(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getInertia(); +} + +void spine_physics_constraint_data_set_strength(spine_physics_constraint_data data, float strength) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setStrength(strength); +} + +float spine_physics_constraint_data_get_strength(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getStrength(); +} + +void spine_physics_constraint_data_set_damping(spine_physics_constraint_data data, float damping) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setDamping(damping); +} + +float spine_physics_constraint_data_get_damping(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getDamping(); +} + +void spine_physics_constraint_data_set_mass_inverse(spine_physics_constraint_data data, float massInverse) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setMassInverse(massInverse); +} + +float spine_physics_constraint_data_get_mass_inverse(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getMassInverse(); +} + +void spine_physics_constraint_data_set_wind(spine_physics_constraint_data data, float wind) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setWind(wind); +} + +float spine_physics_constraint_data_get_wind(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getWind(); +} + +void spine_physics_constraint_data_set_gravity(spine_physics_constraint_data data, float gravity) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setGravity(gravity); +} + +float spine_physics_constraint_data_get_gravity(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getGravity(); +} + +void spine_physics_constraint_data_set_mix(spine_physics_constraint_data data, float mix) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setMix(mix); +} + +float spine_physics_constraint_data_get_mix(spine_physics_constraint_data data) { + if (data == nullptr) return 0.0f; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->getMix(); +} + +void spine_physics_constraint_data_set_inertia_global(spine_physics_constraint_data data, int32_t inertiaGlobal) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setInertiaGlobal(inertiaGlobal); +} + +spine_bool spine_physics_constraint_data_is_inertia_global(spine_physics_constraint_data data) { + if (data == nullptr) return false; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->isInertiaGlobal(); +} + +void spine_physics_constraint_data_set_strength_global(spine_physics_constraint_data data, spine_bool strengthGlobal) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setStrengthGlobal(strengthGlobal); +} + +spine_bool spine_physics_constraint_data_is_strength_global(spine_physics_constraint_data data) { + if (data == nullptr) return false; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->isStrengthGlobal(); +} + +void spine_physics_constraint_data_set_damping_global(spine_physics_constraint_data data, spine_bool dampingGlobal) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setDampingGlobal(dampingGlobal); +} + +spine_bool spine_physics_constraint_data_is_damping_global(spine_physics_constraint_data data) { + if (data == nullptr) return false; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->isDampingGlobal(); +} + +void spine_physics_constraint_data_set_mass_global(spine_physics_constraint_data data, spine_bool massGlobal) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setMassGlobal(massGlobal); +} + +spine_bool spine_physics_constraint_data_is_mass_global(spine_physics_constraint_data data) { + if (data == nullptr) return false; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->isMassGlobal(); +} + +void spine_physics_constraint_data_set_wind_global(spine_physics_constraint_data data, spine_bool windGlobal) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setWindGlobal(windGlobal); +} + +spine_bool spine_physics_constraint_data_is_wind_global(spine_physics_constraint_data data) { + if (data == nullptr) return false; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->isWindGlobal(); +} + +void spine_physics_constraint_data_set_gravity_global(spine_physics_constraint_data data, spine_bool gravityGlobal) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setGravityGlobal(gravityGlobal); +} + +spine_bool spine_physics_constraint_data_is_gravity_global(spine_physics_constraint_data data) { + if (data == nullptr) return false; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->isGravityGlobal(); +} + +void spine_physics_constraint_data_set_mix_global(spine_physics_constraint_data data, spine_bool mixGlobal) { + if (data == nullptr) return; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + _data->setMixGlobal(mixGlobal); +} + +spine_bool spine_physics_constraint_data_is_mix_global(spine_physics_constraint_data data) { + if (data == nullptr) return false; + PhysicsConstraintData *_data = (PhysicsConstraintData *) data; + return _data->isMixGlobal(); +} + +// PhysicsConstraint +void spine_physics_constraint_set_bone(spine_physics_constraint constraint, spine_bone bone) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setBone((Bone *) bone); +} + +spine_bone spine_physics_constraint_get_bone(spine_physics_constraint constraint) { + if (constraint == nullptr) return nullptr; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return (spine_bone) _constraint->getBone(); +} + +void spine_physics_constraint_set_inertia(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setInertia(value); +} + +float spine_physics_constraint_get_inertia(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getInertia(); +} + +void spine_physics_constraint_set_strength(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setStrength(value); +} + +float spine_physics_constraint_get_strength(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getStrength(); +} + +void spine_physics_constraint_set_damping(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setDamping(value); +} + +float spine_physics_constraint_get_damping(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getDamping(); +} + +void spine_physics_constraint_set_mass_inverse(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setMassInverse(value); +} + +float spine_physics_constraint_get_mass_inverse(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getMassInverse(); +} + +void spine_physics_constraint_set_wind(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setWind(value); +} + +float spine_physics_constraint_get_wind(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getWind(); +} + +void spine_physics_constraint_set_gravity(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setGravity(value); +} + +float spine_physics_constraint_get_gravity(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getGravity(); +} + +void spine_physics_constraint_set_mix(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setMix(value); +} + +float spine_physics_constraint_get_mix(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getMix(); +} + +void spine_physics_constraint_set_reset(spine_physics_constraint constraint, spine_bool value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setReset(value); +} + +spine_bool spine_physics_constraint_get_reset(spine_physics_constraint constraint) { + if (constraint == nullptr) return false; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getReset(); +} + +void spine_physics_constraint_set_ux(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setUx(value); +} + +float spine_physics_constraint_get_ux(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getUx(); +} + +void spine_physics_constraint_set_uy(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setUy(value); +} + +float spine_physics_constraint_get_uy(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getUy(); +} + +void spine_physics_constraint_set_cx(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setCx(value); +} + +float spine_physics_constraint_get_cx(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getCx(); +} + +void spine_physics_constraint_set_cy(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setCy(value); +} + +float spine_physics_constraint_get_cy(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getCy(); +} + +void spine_physics_constraint_set_tx(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setTx(value); +} + +float spine_physics_constraint_get_tx(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getTx(); +} + +void spine_physics_constraint_set_ty(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setTy(value); +} + +float spine_physics_constraint_get_ty(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getTy(); +} + +void spine_physics_constraint_set_x_offset(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setXOffset(value); +} + +float spine_physics_constraint_get_x_offset(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getXOffset(); +} + +void spine_physics_constraint_set_x_velocity(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setXVelocity(value); +} + +float spine_physics_constraint_get_x_velocity(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getXVelocity(); +} + +void spine_physics_constraint_set_y_offset(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setYOffset(value); +} + +float spine_physics_constraint_get_y_offset(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getYOffset(); +} + +void spine_physics_constraint_set_y_velocity(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setYVelocity(value); +} + +float spine_physics_constraint_get_y_velocity(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getYVelocity(); +} + +void spine_physics_constraint_set_rotate_offset(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setRotateOffset(value); +} + +float spine_physics_constraint_get_rotate_offset(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getRotateOffset(); +} + +void spine_physics_constraint_set_rotate_velocity(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setRotateVelocity(value); +} + +float spine_physics_constraint_get_rotate_velocity(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getRotateVelocity(); +} + +void spine_physics_constraint_set_scale_offset(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setScaleOffset(value); +} + +float spine_physics_constraint_get_scale_offset(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getScaleOffset(); +} + +void spine_physics_constraint_set_scale_velocity(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setScaleVelocity(value); +} + +float spine_physics_constraint_get_scale_velocity(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getScaleVelocity(); +} + +void spine_physics_constraint_set_active(spine_physics_constraint constraint, spine_bool value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setActive(value); +} + +spine_bool spine_physics_constraint_is_active(spine_physics_constraint constraint) { + if (constraint == nullptr) return false; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->isActive(); +} + +void spine_physics_constraint_set_remaining(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setRemaining(value); +} + +float spine_physics_constraint_get_remaining(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getRemaining(); +} + +void spine_physics_constraint_set_last_time(spine_physics_constraint constraint, float value) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->setLastTime(value); +} + +float spine_physics_constraint_get_last_time(spine_physics_constraint constraint) { + if (constraint == nullptr) return 0.0f; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + return _constraint->getLastTime(); +} + +void spine_physics_constraint_reset_fully(spine_physics_constraint constraint) { + if (constraint == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) constraint; + _constraint->reset(); +} + +void spine_physics_constraint_update(spine_physics_constraint data, spine_physics physics) { + if (data == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) data; + _constraint->update((spine::Physics) physics); +} + +void spine_physics_constraint_translate(spine_physics_constraint data, float x, float y) { + if (data == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) data; + _constraint->translate(x, y); +} + +void spine_physics_constraint_rotate(spine_physics_constraint data, float x, float y, float degrees) { + if (data == nullptr) return; + PhysicsConstraint *_constraint = (PhysicsConstraint *) data; + _constraint->rotate(x, y, degrees); +} + +// Sequence +void spine_sequence_apply(spine_sequence sequence, spine_slot slot, spine_attachment attachment) { + if (sequence == nullptr) return; + Sequence *_sequence = (Sequence *) sequence; + _sequence->apply((Slot *) slot, (Attachment *) attachment); +} + +const utf8 *spine_sequence_get_path(spine_sequence sequence, const utf8 *basePath, int32_t index) { + if (sequence == nullptr) return nullptr; + Sequence *_sequence = (Sequence *) sequence; + return (utf8 *) strdup(_sequence->getPath(basePath, index).buffer()); +} + +int32_t spine_sequence_get_id(spine_sequence sequence) { + if (sequence == nullptr) return 0; + Sequence *_sequence = (Sequence *) sequence; + return _sequence->getId(); +} + +void spine_sequence_set_id(spine_sequence sequence, int32_t id) { + if (sequence == nullptr) return; + Sequence *_sequence = (Sequence *) sequence; + _sequence->setId(id); +} + +int32_t spine_sequence_get_start(spine_sequence sequence) { + if (sequence == nullptr) return 0; + Sequence *_sequence = (Sequence *) sequence; + return _sequence->getStart(); +} + +void spine_sequence_set_start(spine_sequence sequence, int32_t start) { + if (sequence == nullptr) return; + Sequence *_sequence = (Sequence *) sequence; + _sequence->setStart(start); +} + +int32_t spine_sequence_get_digits(spine_sequence sequence) { + if (sequence == nullptr) return 0; + Sequence *_sequence = (Sequence *) sequence; + return _sequence->getDigits(); +} + +void spine_sequence_set_digits(spine_sequence sequence, int32_t digits) { + if (sequence == nullptr) return; + Sequence *_sequence = (Sequence *) sequence; + _sequence->setDigits(digits); +} + +int32_t spine_sequence_get_setup_index(spine_sequence sequence) { + if (sequence == nullptr) return 0; + Sequence *_sequence = (Sequence *) sequence; + return _sequence->getSetupIndex(); +} + +void spine_sequence_set_setup_index(spine_sequence sequence, int32_t setupIndex) { + if (sequence == nullptr) return; + Sequence *_sequence = (Sequence *) sequence; + _sequence->setSetupIndex(setupIndex); +} + +int32_t spine_sequence_get_num_regions(spine_sequence sequence) { + if (sequence == nullptr) return 0; + Sequence *_sequence = (Sequence *) sequence; + return (int32_t) _sequence->getRegions().size(); +} + +spine_texture_region *spine_sequence_get_regions(spine_sequence sequence) { + if (sequence == nullptr) return nullptr; + Sequence *_sequence = (Sequence *) sequence; + return (spine_texture_region *) _sequence->getRegions().buffer(); +} + +// TextureRegion +void *spine_texture_region_get_texture(spine_texture_region textureRegion) { + if (textureRegion == nullptr) return nullptr; + TextureRegion *_region = (TextureRegion *) textureRegion; + return _region->rendererObject; +} + +void spine_texture_region_set_texture(spine_texture_region textureRegion, void *texture) { + if (textureRegion == nullptr) return; + TextureRegion *_region = (TextureRegion *) textureRegion; + _region->rendererObject = texture; +} + +float spine_texture_region_get_u(spine_texture_region textureRegion) { + if (textureRegion == nullptr) return 0; + TextureRegion *_region = (TextureRegion *) textureRegion; + return _region->u; +} + +void spine_texture_region_set_u(spine_texture_region textureRegion, float u) { + if (textureRegion == nullptr) return; + TextureRegion *_region = (TextureRegion *) textureRegion; + _region->u = u; +} + +float spine_texture_region_get_v(spine_texture_region textureRegion) { + if (textureRegion == nullptr) return 0; + TextureRegion *_region = (TextureRegion *) textureRegion; + return _region->v; +} +void spine_texture_region_set_v(spine_texture_region textureRegion, float v) { + if (textureRegion == nullptr) return; + TextureRegion *_region = (TextureRegion *) textureRegion; + _region->v = v; +} +float spine_texture_region_get_u2(spine_texture_region textureRegion) { + if (textureRegion == nullptr) return 0; + TextureRegion *_region = (TextureRegion *) textureRegion; + return _region->u2; +} + +void spine_texture_region_set_u2(spine_texture_region textureRegion, float u2) { + if (textureRegion == nullptr) return; + TextureRegion *_region = (TextureRegion *) textureRegion; + _region->u2 = u2; +} + +float spine_texture_region_get_v2(spine_texture_region textureRegion) { + if (textureRegion == nullptr) return 0; + TextureRegion *_region = (TextureRegion *) textureRegion; + return _region->v2; +} + +void spine_texture_region_set_v2(spine_texture_region textureRegion, float v2) { + if (textureRegion == nullptr) return; + TextureRegion *_region = (TextureRegion *) textureRegion; + _region->v2 = v2; +} + +int32_t spine_texture_region_get_degrees(spine_texture_region textureRegion) { + if (textureRegion == nullptr) return 0; + TextureRegion *_region = (TextureRegion *) textureRegion; + return _region->degrees; +} + +void spine_texture_region_set_degrees(spine_texture_region textureRegion, int32_t degrees) { + if (textureRegion == nullptr) return; + TextureRegion *_region = (TextureRegion *) textureRegion; + _region->degrees = degrees; +} + +float spine_texture_region_get_offset_x(spine_texture_region textureRegion) { + if (textureRegion == nullptr) return 0; + TextureRegion *_region = (TextureRegion *) textureRegion; + return _region->offsetX; +} + +void spine_texture_region_set_offset_x(spine_texture_region textureRegion, float offsetX) { + if (textureRegion == nullptr) return; + TextureRegion *_region = (TextureRegion *) textureRegion; + _region->offsetX = offsetX; +} + +float spine_texture_region_get_offset_y(spine_texture_region textureRegion) { + if (textureRegion == nullptr) return 0; + TextureRegion *_region = (TextureRegion *) textureRegion; + return _region->offsetY; +} + +void spine_texture_region_set_offset_y(spine_texture_region textureRegion, float offsetY) { + if (textureRegion == nullptr) return; + TextureRegion *_region = (TextureRegion *) textureRegion; + _region->offsetY = offsetY; +} + +int32_t spine_texture_region_get_width(spine_texture_region textureRegion) { + if (textureRegion == nullptr) return 0; + TextureRegion *_region = (TextureRegion *) textureRegion; + return _region->width; +} + +void spine_texture_region_set_width(spine_texture_region textureRegion, int32_t width) { + if (textureRegion == nullptr) return; + TextureRegion *_region = (TextureRegion *) textureRegion; + _region->width = width; +} + +int32_t spine_texture_region_get_height(spine_texture_region textureRegion) { + if (textureRegion == nullptr) return 0; + TextureRegion *_region = (TextureRegion *) textureRegion; + return _region->height; +} + +void spine_texture_region_set_height(spine_texture_region textureRegion, int32_t height) { + if (textureRegion == nullptr) return; + TextureRegion *_region = (TextureRegion *) textureRegion; + _region->height = height; +} + +int32_t spine_texture_region_get_original_width(spine_texture_region textureRegion) { + if (textureRegion == nullptr) return 0; + TextureRegion *_region = (TextureRegion *) textureRegion; + return _region->originalWidth; +} + +void spine_texture_region_set_original_width(spine_texture_region textureRegion, int32_t originalWidth) { + if (textureRegion == nullptr) return; + TextureRegion *_region = (TextureRegion *) textureRegion; + _region->originalWidth = originalWidth; +} + +int32_t spine_texture_region_get_original_height(spine_texture_region textureRegion) { + if (textureRegion == nullptr) return 0; + TextureRegion *_region = (TextureRegion *) textureRegion; + return _region->originalHeight; +} + +void spine_texture_region_set_original_height(spine_texture_region textureRegion, int32_t originalHeight) { + if (textureRegion == nullptr) return; + TextureRegion *_region = (TextureRegion *) textureRegion; + _region->originalHeight = originalHeight; +} + +spine_skeleton_bounds spine_skeleton_bounds_create() { + return (spine_skeleton_bounds) new (__FILE__, __LINE__) SkeletonBounds(); +} + +void spine_skeleton_bounds_dispose(spine_skeleton_bounds bounds) { + if (bounds == nullptr) return; + SkeletonBounds *_bounds = (SkeletonBounds *) bounds; + delete _bounds; +} + +void spine_skeleton_bounds_update(spine_skeleton_bounds bounds, spine_skeleton skeleton, spine_bool updateAabb) { + if (bounds == nullptr) return; + if (skeleton == nullptr) return; + + SkeletonBounds *_bounds = (SkeletonBounds *) bounds; + Skeleton *_skeleton = (Skeleton *) skeleton; + _bounds->update(*_skeleton, updateAabb != 0); +} + +spine_bool spine_skeleton_bounds_aabb_contains_point(spine_skeleton_bounds bounds, float x, float y) { + if (bounds == nullptr) return false; + return ((SkeletonBounds *) bounds)->aabbcontainsPoint(x, y); +} + +spine_bool spine_skeleton_bounds_aabb_intersects_segment(spine_skeleton_bounds bounds, float x1, float y1, float x2, float y2) { + if (bounds == nullptr) return false; + return ((SkeletonBounds *) bounds)->aabbintersectsSegment(x1, y1, x2, y2); +} + +spine_bool spine_skeleton_bounds_aabb_intersects_skeleton(spine_skeleton_bounds bounds, spine_skeleton_bounds otherBounds) { + if (bounds == nullptr) return false; + if (otherBounds == nullptr) return false; + return ((SkeletonBounds *) bounds)->aabbIntersectsSkeleton(*((SkeletonBounds *) bounds)); +} + +spine_bool spine_skeleton_bounds_contains_point(spine_skeleton_bounds bounds, spine_polygon polygon, float x, float y) { + if (bounds == nullptr) return false; + if (polygon == nullptr) return false; + return ((SkeletonBounds *) bounds)->containsPoint((Polygon *) polygon, x, y); +} + +spine_bounding_box_attachment spine_skeleton_bounds_contains_point_attachment(spine_skeleton_bounds bounds, float x, float y) { + if (bounds == nullptr) return nullptr; + return (spine_bounding_box_attachment) ((SkeletonBounds *) bounds)->containsPoint(x, y); +} + +spine_bounding_box_attachment spine_skeleton_bounds_intersects_segment_attachment(spine_skeleton_bounds bounds, float x1, float y1, float x2, float y2) { + if (bounds == nullptr) return nullptr; + return (spine_bounding_box_attachment) ((SkeletonBounds *) bounds)->intersectsSegment(x1, y1, x2, y2); +} + +spine_bool spine_skeleton_bounds_intersects_segment(spine_skeleton_bounds bounds, spine_polygon polygon, float x1, float y1, float x2, float y2) { + if (bounds == nullptr) return false; + if (polygon == nullptr) return false; + return ((SkeletonBounds *) bounds)->intersectsSegment((Polygon *) polygon, x1, y1, x2, y2); +} + +spine_polygon spine_skeleton_bounds_get_polygon(spine_skeleton_bounds bounds, spine_bounding_box_attachment attachment) { + if (bounds == nullptr) return nullptr; + if (attachment == nullptr) return nullptr; + return (spine_polygon) ((SkeletonBounds *) bounds)->getPolygon((BoundingBoxAttachment *) attachment); +} + +spine_bounding_box_attachment spine_skeleton_bounds_get_bounding_box(spine_skeleton_bounds bounds, spine_polygon polygon) { + if (bounds == nullptr) return nullptr; + if (polygon == nullptr) return nullptr; + return (spine_bounding_box_attachment) ((SkeletonBounds *) bounds)->getBoundingBox((Polygon *) polygon); +} + +int32_t spine_skeleton_bounds_get_num_polygons(spine_skeleton_bounds bounds) { + if (bounds == nullptr) return 0; + return (int32_t) ((SkeletonBounds *) bounds)->getPolygons().size(); +} + +spine_polygon *spine_skeleton_bounds_get_polygons(spine_skeleton_bounds bounds) { + if (bounds == nullptr) return nullptr; + return (spine_polygon *) ((SkeletonBounds *) bounds)->getPolygons().buffer(); +} + +int32_t spine_skeleton_bounds_get_num_bounding_boxes(spine_skeleton_bounds bounds) { + if (bounds == nullptr) return 0; + return (int32_t) ((SkeletonBounds *) bounds)->getBoundingBoxes().size(); +} + +spine_bounding_box_attachment *spine_skeleton_bounds_get_bounding_boxes(spine_skeleton_bounds bounds) { + if (bounds == nullptr) return nullptr; + return (spine_bounding_box_attachment *) ((SkeletonBounds *) bounds)->getBoundingBoxes().buffer(); +} + +float spine_skeleton_bounds_get_width(spine_skeleton_bounds bounds) { + if (bounds == nullptr) return 0; + return ((SkeletonBounds *) bounds)->getWidth(); +} + +float spine_skeleton_bounds_get_height(spine_skeleton_bounds bounds) { + if (bounds == nullptr) return 0; + return ((SkeletonBounds *) bounds)->getHeight(); +} + +int32_t spine_polygon_get_num_vertices(spine_polygon polygon) { + if (polygon == nullptr) return 0; + return ((Polygon *) polygon)->_vertices.size(); +} + +float *spine_polygon_get_vertices(spine_polygon polygon) { + if (polygon == nullptr) return 0; + return ((Polygon *) polygon)->_vertices.buffer(); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp-lite/spine-cpp-lite.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp-lite/spine-cpp-lite.h new file mode 100644 index 0000000..530afa4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp-lite/spine-cpp-lite.h @@ -0,0 +1,1085 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_CPP_LITE +#define SPINE_CPP_LITE + +#include + +#ifdef __cplusplus +#if _WIN32 +#define SPINE_CPP_LITE_EXPORT extern "C" __declspec(dllexport) +#else +#ifdef __EMSCRIPTEN__ +#define SPINE_CPP_LITE_EXPORT extern "C" __attribute__((used)) +#else +#define SPINE_CPP_LITE_EXPORT extern "C" +#endif +#endif +#else +#if _WIN32 +#define SPINE_CPP_LITE_EXPORT __declspec(dllexport) +#else +#ifdef __EMSCRIPTEN__ +#define SPINE_CPP_LITE_EXPORT __attribute__((used)) +#else +#define SPINE_CPP_LITE_EXPORT +#endif +#endif +#endif + +#define SPINE_OPAQUE_TYPE(name) \ + typedef struct name##_wrapper { \ + } name##_wrapper; \ + typedef name##_wrapper *name; + +// @start: opaque_types + +SPINE_OPAQUE_TYPE(spine_skeleton) +SPINE_OPAQUE_TYPE(spine_skeleton_data) +SPINE_OPAQUE_TYPE(spine_bone) +SPINE_OPAQUE_TYPE(spine_bone_data) +SPINE_OPAQUE_TYPE(spine_slot) +SPINE_OPAQUE_TYPE(spine_slot_data) +SPINE_OPAQUE_TYPE(spine_skin) +SPINE_OPAQUE_TYPE(spine_attachment) +SPINE_OPAQUE_TYPE(spine_region_attachment) +SPINE_OPAQUE_TYPE(spine_vertex_attachment) +SPINE_OPAQUE_TYPE(spine_mesh_attachment) +SPINE_OPAQUE_TYPE(spine_clipping_attachment) +SPINE_OPAQUE_TYPE(spine_bounding_box_attachment) +SPINE_OPAQUE_TYPE(spine_path_attachment) +SPINE_OPAQUE_TYPE(spine_point_attachment) +SPINE_OPAQUE_TYPE(spine_texture_region) +SPINE_OPAQUE_TYPE(spine_sequence) +SPINE_OPAQUE_TYPE(spine_constraint) +SPINE_OPAQUE_TYPE(spine_constraint_data) +SPINE_OPAQUE_TYPE(spine_ik_constraint) +SPINE_OPAQUE_TYPE(spine_ik_constraint_data) +SPINE_OPAQUE_TYPE(spine_transform_constraint) +SPINE_OPAQUE_TYPE(spine_transform_constraint_data) +SPINE_OPAQUE_TYPE(spine_path_constraint) +SPINE_OPAQUE_TYPE(spine_path_constraint_data) +SPINE_OPAQUE_TYPE(spine_physics_constraint) +SPINE_OPAQUE_TYPE(spine_physics_constraint_data) +SPINE_OPAQUE_TYPE(spine_animation_state) +SPINE_OPAQUE_TYPE(spine_animation_state_data) +SPINE_OPAQUE_TYPE(spine_animation_state_events) +SPINE_OPAQUE_TYPE(spine_event) +SPINE_OPAQUE_TYPE(spine_event_data) +SPINE_OPAQUE_TYPE(spine_track_entry) +SPINE_OPAQUE_TYPE(spine_animation) +SPINE_OPAQUE_TYPE(spine_atlas) +SPINE_OPAQUE_TYPE(spine_skeleton_data_result) +SPINE_OPAQUE_TYPE(spine_render_command) +SPINE_OPAQUE_TYPE(spine_bounds) +SPINE_OPAQUE_TYPE(spine_color) +SPINE_OPAQUE_TYPE(spine_vector) +SPINE_OPAQUE_TYPE(spine_skeleton_drawable) +SPINE_OPAQUE_TYPE(spine_skin_entry) +SPINE_OPAQUE_TYPE(spine_skin_entries) +SPINE_OPAQUE_TYPE(spine_skeleton_bounds) +SPINE_OPAQUE_TYPE(spine_polygon) + +// @end: opaque_types + +typedef char utf8; + +// @start: enums + +typedef enum spine_blend_mode { + SPINE_BLEND_MODE_NORMAL = 0, + SPINE_BLEND_MODE_ADDITIVE, + SPINE_BLEND_MODE_MULTIPLY, + SPINE_BLEND_MODE_SCREEN +} spine_blend_mode; + +typedef enum spine_mix_blend { + SPINE_MIX_BLEND_SETUP = 0, + SPINE_MIX_BLEND_FIRST, + SPINE_MIX_BLEND_REPLACE, + SPINE_MIX_BLEND_ADD +} spine_mix_blend; + +typedef enum spine_event_type { + SPINE_EVENT_TYPE_START = 0, + SPINE_EVENT_TYPE_INTERRUPT, + SPINE_EVENT_TYPE_END, + SPINE_EVENT_TYPE_COMPLETE, + SPINE_EVENT_TYPE_DISPOSE, + SPINE_EVENT_TYPE_EVENT +} spine_event_type; + +typedef enum spine_attachment_type { + SPINE_ATTACHMENT_REGION = 0, + SPINE_ATTACHMENT_MESH, + SPINE_ATTACHMENT_CLIPPING, + SPINE_ATTACHMENT_BOUNDING_BOX, + SPINE_ATTACHMENT_PATH, + SPINE_ATTACHMENT_POINT, +} spine_attachment_type; + +typedef enum spine_constraint_type { + SPINE_CONSTRAINT_IK, + SPINE_CONSTRAINT_TRANSFORM, + SPINE_CONSTRAINT_PATH +} spine_constraint_type; + +typedef enum spine_inherit { + SPINE_INHERIT_NORMAL = 0, + SPINE_INHERIT_ONLY_TRANSLATION, + SPINE_INHERIT_NO_ROTATION_OR_REFLECTION, + SPINE_INHERIT_NO_SCALE, + SPINE_INHERIT_NO_SCALE_OR_REFLECTION +} spine_inherit; + +typedef enum spine_position_mode { + SPINE_POSITION_MODE_FIXED = 0, + SPINE_POSITION_MODE_PERCENT +} spine_position_mode; + +typedef enum spine_spacing_mode { + SPINE_SPACING_MODE_LENGTH = 0, + SPINE_SPACING_MODE_FIXED, + SPINE_SPACING_MODE_PERCENT, + SPINE_SPACING_MODE_PROPORTIONAL +} spine_spacing_mode; + +typedef enum spine_rotate_mode { + SPINE_ROTATE_MODE_TANGENT = 0, + SPINE_ROTATE_MODE_CHAIN, + SPINE_ROTATE_MODE_CHAIN_SCALE +} spine_rotate_mode; + +typedef enum spine_physics { + SPINE_PHYSICS_NONE = 0, + SPINE_PHYSICS_RESET, + SPINE_PHYSICS_UPDATE, + SPINE_PHYSICS_POSE + +} spine_physics; + +// @end: enums + +typedef int32_t spine_bool; + +typedef void* (*spine_texture_loader_load_func)(const char *path); + +typedef void (*spine_texture_loader_unload_func)(void *texture); + +// @start: function_declarations + +SPINE_CPP_LITE_EXPORT int32_t spine_major_version(); +SPINE_CPP_LITE_EXPORT int32_t spine_minor_version(); +SPINE_CPP_LITE_EXPORT void spine_enable_debug_extension(spine_bool enable); +SPINE_CPP_LITE_EXPORT void spine_report_leaks(); + +SPINE_CPP_LITE_EXPORT float spine_color_get_r(spine_color color); +SPINE_CPP_LITE_EXPORT float spine_color_get_g(spine_color color); +SPINE_CPP_LITE_EXPORT float spine_color_get_b(spine_color color); +SPINE_CPP_LITE_EXPORT float spine_color_get_a(spine_color color); + +SPINE_CPP_LITE_EXPORT float spine_bounds_get_x(spine_bounds bounds); +SPINE_CPP_LITE_EXPORT float spine_bounds_get_y(spine_bounds bounds); +SPINE_CPP_LITE_EXPORT float spine_bounds_get_width(spine_bounds bounds); +SPINE_CPP_LITE_EXPORT float spine_bounds_get_height(spine_bounds bounds); + +SPINE_CPP_LITE_EXPORT float spine_vector_get_x(spine_vector vector); +SPINE_CPP_LITE_EXPORT float spine_vector_get_y(spine_vector vector); + +SPINE_CPP_LITE_EXPORT spine_atlas spine_atlas_load(const utf8 *atlasData); +// @ignore +SPINE_CPP_LITE_EXPORT spine_atlas spine_atlas_load_callback(const utf8 *atlasData, const utf8 *atlasDir, spine_texture_loader_load_func load, spine_texture_loader_unload_func unload); +SPINE_CPP_LITE_EXPORT int32_t spine_atlas_get_num_image_paths(spine_atlas atlas); +SPINE_CPP_LITE_EXPORT utf8 *spine_atlas_get_image_path(spine_atlas atlas, int32_t index); +SPINE_CPP_LITE_EXPORT spine_bool spine_atlas_is_pma(spine_atlas atlas); +SPINE_CPP_LITE_EXPORT utf8 *spine_atlas_get_error(spine_atlas atlas); +SPINE_CPP_LITE_EXPORT void spine_atlas_dispose(spine_atlas atlas); + +// @ignore +SPINE_CPP_LITE_EXPORT spine_skeleton_data_result spine_skeleton_data_load_json(spine_atlas atlas, const utf8 *skeletonData); +// @ignore +SPINE_CPP_LITE_EXPORT spine_skeleton_data_result spine_skeleton_data_load_binary(spine_atlas atlas, const uint8_t *skeletonData, int32_t length); +SPINE_CPP_LITE_EXPORT utf8 *spine_skeleton_data_result_get_error(spine_skeleton_data_result result); +SPINE_CPP_LITE_EXPORT spine_skeleton_data spine_skeleton_data_result_get_data(spine_skeleton_data_result result); +SPINE_CPP_LITE_EXPORT void spine_skeleton_data_result_dispose(spine_skeleton_data_result result); +SPINE_CPP_LITE_EXPORT spine_bone_data spine_skeleton_data_find_bone(spine_skeleton_data data, const utf8 *name); +SPINE_CPP_LITE_EXPORT spine_slot_data spine_skeleton_data_find_slot(spine_skeleton_data data, const utf8 *name); +SPINE_CPP_LITE_EXPORT spine_skin spine_skeleton_data_find_skin(spine_skeleton_data data, const utf8 *name); +SPINE_CPP_LITE_EXPORT spine_event_data spine_skeleton_data_find_event(spine_skeleton_data data, const utf8 *name); +SPINE_CPP_LITE_EXPORT spine_animation spine_skeleton_data_find_animation(spine_skeleton_data data, const utf8 *name); +SPINE_CPP_LITE_EXPORT spine_ik_constraint_data spine_skeleton_data_find_ik_constraint(spine_skeleton_data data, const utf8 *name); +SPINE_CPP_LITE_EXPORT spine_transform_constraint_data spine_skeleton_data_find_transform_constraint(spine_skeleton_data data, const utf8 *name); +SPINE_CPP_LITE_EXPORT spine_path_constraint_data spine_skeleton_data_find_path_constraint(spine_skeleton_data data, const utf8 *name); +SPINE_CPP_LITE_EXPORT spine_physics_constraint_data spine_skeleton_data_find_physics_constraint(spine_skeleton_data data, const utf8 *name); +// @optiona; +SPINE_CPP_LITE_EXPORT const utf8 *spine_skeleton_data_get_name(spine_skeleton_data data); +// OMITTED setName() +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_data_get_num_bones(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT spine_bone_data *spine_skeleton_data_get_bones(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_data_get_num_slots(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT spine_slot_data *spine_skeleton_data_get_slots(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_data_get_num_skins(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT spine_skin *spine_skeleton_data_get_skins(spine_skeleton_data data); +// @optional +SPINE_CPP_LITE_EXPORT spine_skin spine_skeleton_data_get_default_skin(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT void spine_skeleton_data_set_default_skin(spine_skeleton_data data, spine_skin skin); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_data_get_num_events(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT spine_event_data *spine_skeleton_data_get_events(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_data_get_num_animations(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT spine_animation *spine_skeleton_data_get_animations(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_data_get_num_ik_constraints(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT spine_ik_constraint_data *spine_skeleton_data_get_ik_constraints(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_data_get_num_transform_constraints(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT spine_transform_constraint_data *spine_skeleton_data_get_transform_constraints(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_data_get_num_path_constraints(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT spine_path_constraint_data *spine_skeleton_data_get_path_constraints(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_data_get_num_physics_constraints(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT spine_physics_constraint_data *spine_skeleton_data_get_physics_constraints(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT float spine_skeleton_data_get_x(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT void spine_skeleton_data_set_x(spine_skeleton_data data, float x); +SPINE_CPP_LITE_EXPORT float spine_skeleton_data_get_y(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT void spine_skeleton_data_set_y(spine_skeleton_data data, float y); +SPINE_CPP_LITE_EXPORT float spine_skeleton_data_get_width(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT void spine_skeleton_data_set_width(spine_skeleton_data data, float width); +SPINE_CPP_LITE_EXPORT float spine_skeleton_data_get_height(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT void spine_skeleton_data_set_height(spine_skeleton_data data, float height); +SPINE_CPP_LITE_EXPORT const utf8 *spine_skeleton_data_get_version(spine_skeleton_data data); +// OMITTED setVersion() +// @ignore +SPINE_CPP_LITE_EXPORT const utf8 *spine_skeleton_data_get_hash(spine_skeleton_data data); +// OMITTED setHash() +SPINE_CPP_LITE_EXPORT const utf8 *spine_skeleton_data_get_images_path(spine_skeleton_data data); +// OMITTED setImagesPath() +SPINE_CPP_LITE_EXPORT const utf8 *spine_skeleton_data_get_audio_path(spine_skeleton_data data); +// OMITTED setAudioPath() +SPINE_CPP_LITE_EXPORT float spine_skeleton_data_get_fps(spine_skeleton_data data); +// OMITTED setFps() +SPINE_CPP_LITE_EXPORT float spine_skeleton_data_get_reference_scale(spine_skeleton_data data); +SPINE_CPP_LITE_EXPORT void spine_skeleton_data_dispose(spine_skeleton_data data); + +// @ignore +SPINE_CPP_LITE_EXPORT spine_skeleton_drawable spine_skeleton_drawable_create(spine_skeleton_data skeletonData); +// @ignore +SPINE_CPP_LITE_EXPORT spine_render_command spine_skeleton_drawable_render(spine_skeleton_drawable drawable); +SPINE_CPP_LITE_EXPORT void spine_skeleton_drawable_dispose(spine_skeleton_drawable drawable); +SPINE_CPP_LITE_EXPORT spine_skeleton spine_skeleton_drawable_get_skeleton(spine_skeleton_drawable drawable); +SPINE_CPP_LITE_EXPORT spine_animation_state spine_skeleton_drawable_get_animation_state(spine_skeleton_drawable drawable); +SPINE_CPP_LITE_EXPORT spine_animation_state_data spine_skeleton_drawable_get_animation_state_data(spine_skeleton_drawable drawable); +SPINE_CPP_LITE_EXPORT spine_animation_state_events spine_skeleton_drawable_get_animation_state_events(spine_skeleton_drawable drawable); + +// @ignore +SPINE_CPP_LITE_EXPORT float *spine_render_command_get_positions(spine_render_command command); +// @ignore +SPINE_CPP_LITE_EXPORT float *spine_render_command_get_uvs(spine_render_command command); +// @ignore +SPINE_CPP_LITE_EXPORT int32_t *spine_render_command_get_colors(spine_render_command command); +// @ignore +SPINE_CPP_LITE_EXPORT int32_t *spine_render_command_get_dark_colors(spine_render_command command); +SPINE_CPP_LITE_EXPORT int32_t spine_render_command_get_num_vertices(spine_render_command command); +SPINE_CPP_LITE_EXPORT uint16_t *spine_render_command_get_indices(spine_render_command command); +SPINE_CPP_LITE_EXPORT int32_t spine_render_command_get_num_indices(spine_render_command command); +SPINE_CPP_LITE_EXPORT int32_t spine_render_command_get_atlas_page(spine_render_command command); +SPINE_CPP_LITE_EXPORT spine_blend_mode spine_render_command_get_blend_mode(spine_render_command command); +SPINE_CPP_LITE_EXPORT spine_render_command spine_render_command_get_next(spine_render_command command); + +SPINE_CPP_LITE_EXPORT const utf8 *spine_animation_get_name(spine_animation animation); +// OMITTED getTimelines() +// OMITTED hasTimeline() +SPINE_CPP_LITE_EXPORT float spine_animation_get_duration(spine_animation animation); +// OMITTED setDuration() + +SPINE_CPP_LITE_EXPORT spine_skeleton_data spine_animation_state_data_get_skeleton_data(spine_animation_state_data stateData); +SPINE_CPP_LITE_EXPORT float spine_animation_state_data_get_default_mix(spine_animation_state_data stateData); +SPINE_CPP_LITE_EXPORT void spine_animation_state_data_set_default_mix(spine_animation_state_data stateData, float defaultMix); +SPINE_CPP_LITE_EXPORT void spine_animation_state_data_set_mix(spine_animation_state_data stateData, spine_animation from, spine_animation to, float duration); +SPINE_CPP_LITE_EXPORT float spine_animation_state_data_get_mix(spine_animation_state_data stateData, spine_animation from, spine_animation to); +SPINE_CPP_LITE_EXPORT void spine_animation_state_data_set_mix_by_name(spine_animation_state_data stateData, const utf8 *fromName, const utf8 *toName, float duration); +SPINE_CPP_LITE_EXPORT float spine_animation_state_data_get_mix_by_name(spine_animation_state_data stateData, const utf8 *fromName, const utf8 *toName); +SPINE_CPP_LITE_EXPORT void spine_animation_state_data_clear(spine_animation_state_data stateData); + +SPINE_CPP_LITE_EXPORT void spine_animation_state_update(spine_animation_state state, float delta); +SPINE_CPP_LITE_EXPORT void spine_animation_state_apply(spine_animation_state state, spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT void spine_animation_state_clear_tracks(spine_animation_state state); +SPINE_CPP_LITE_EXPORT void spine_animation_state_clear_track(spine_animation_state state, int32_t trackIndex); +SPINE_CPP_LITE_EXPORT int32_t spine_animation_state_get_num_tracks(spine_animation_state state); +SPINE_CPP_LITE_EXPORT spine_track_entry spine_animation_state_set_animation_by_name(spine_animation_state state, int32_t trackIndex, const utf8 *animationName, spine_bool loop); +SPINE_CPP_LITE_EXPORT spine_track_entry spine_animation_state_set_animation(spine_animation_state state, int32_t trackIndex, spine_animation animation, spine_bool loop); +SPINE_CPP_LITE_EXPORT spine_track_entry spine_animation_state_add_animation_by_name(spine_animation_state state, int32_t trackIndex, const utf8 *animationName, spine_bool loop, float delay); +SPINE_CPP_LITE_EXPORT spine_track_entry spine_animation_state_add_animation(spine_animation_state state, int32_t trackIndex, spine_animation animation, spine_bool loop, float delay); +SPINE_CPP_LITE_EXPORT spine_track_entry spine_animation_state_set_empty_animation(spine_animation_state state, int32_t trackIndex, float mixDuration); +SPINE_CPP_LITE_EXPORT spine_track_entry spine_animation_state_add_empty_animation(spine_animation_state state, int32_t trackIndex, float mixDuration, float delay); +SPINE_CPP_LITE_EXPORT void spine_animation_state_set_empty_animations(spine_animation_state state, float mixDuration); +// @optional +SPINE_CPP_LITE_EXPORT spine_track_entry spine_animation_state_get_current(spine_animation_state state, int32_t trackIndex); +SPINE_CPP_LITE_EXPORT spine_animation_state_data spine_animation_state_get_data(spine_animation_state state); +SPINE_CPP_LITE_EXPORT float spine_animation_state_get_time_scale(spine_animation_state state); +SPINE_CPP_LITE_EXPORT void spine_animation_state_set_time_scale(spine_animation_state state, float timeScale); +// OMITTED setListener() +// OMITTED setListener() +// OMITTED disableQueue() +// OMITTED enableQueue() +// OMITTED setManualTrackEntryDisposal() +// OMITTED getManualTrackEntryDisposal() +// @ignore +SPINE_CPP_LITE_EXPORT void spine_animation_state_dispose_track_entry(spine_animation_state state, spine_track_entry entry); + +SPINE_CPP_LITE_EXPORT int32_t spine_animation_state_events_get_num_events(spine_animation_state_events events); +SPINE_CPP_LITE_EXPORT spine_event_type spine_animation_state_events_get_event_type(spine_animation_state_events events, int32_t index); +SPINE_CPP_LITE_EXPORT spine_track_entry spine_animation_state_events_get_track_entry(spine_animation_state_events events, int32_t index); +// @optional +SPINE_CPP_LITE_EXPORT spine_event spine_animation_state_events_get_event(spine_animation_state_events events, int32_t index); +SPINE_CPP_LITE_EXPORT void spine_animation_state_events_reset(spine_animation_state_events events); + +SPINE_CPP_LITE_EXPORT int32_t spine_track_entry_get_track_index(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT spine_animation spine_track_entry_get_animation(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT spine_track_entry spine_track_entry_get_previous(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT spine_bool spine_track_entry_get_loop(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_loop(spine_track_entry entry, spine_bool loop); +SPINE_CPP_LITE_EXPORT spine_bool spine_track_entry_get_hold_previous(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_hold_previous(spine_track_entry entry, spine_bool holdPrevious); +SPINE_CPP_LITE_EXPORT spine_bool spine_track_entry_get_reverse(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_reverse(spine_track_entry entry, spine_bool reverse); +SPINE_CPP_LITE_EXPORT spine_bool spine_track_entry_get_shortest_rotation(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_shortest_rotation(spine_track_entry entry, spine_bool shortestRotation); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_delay(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_delay(spine_track_entry entry, float delay); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_track_time(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_track_time(spine_track_entry entry, float trackTime); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_track_end(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_track_end(spine_track_entry entry, float trackEnd); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_animation_start(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_animation_start(spine_track_entry entry, float animationStart); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_animation_end(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_animation_end(spine_track_entry entry, float animationEnd); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_animation_last(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_animation_last(spine_track_entry entry, float animationLast); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_animation_time(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_time_scale(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_time_scale(spine_track_entry entry, float timeScale); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_alpha(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_alpha(spine_track_entry entry, float alpha); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_event_threshold(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_event_threshold(spine_track_entry entry, float eventThreshold); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_alpha_attachment_threshold(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_alpha_attachment_threshold(spine_track_entry entry, float attachmentThreshold); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_mix_attachment_threshold(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_mix_attachment_threshold(spine_track_entry entry, float attachmentThreshold); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_mix_draw_order_threshold(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_mix_draw_order_threshold(spine_track_entry entry, float drawOrderThreshold); +// @optional +SPINE_CPP_LITE_EXPORT spine_track_entry spine_track_entry_get_next(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT spine_bool spine_track_entry_is_complete(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_mix_time(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_mix_time(spine_track_entry entry, float mixTime); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_mix_duration(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_mix_duration(spine_track_entry entry, float mixDuration); +SPINE_CPP_LITE_EXPORT spine_mix_blend spine_track_entry_get_mix_blend(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_set_mix_blend(spine_track_entry entry, spine_mix_blend mixBlend); +// @optional +SPINE_CPP_LITE_EXPORT spine_track_entry spine_track_entry_get_mixing_from(spine_track_entry entry); +// @optional +SPINE_CPP_LITE_EXPORT spine_track_entry spine_track_entry_get_mixing_to(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT void spine_track_entry_reset_rotation_directions(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT float spine_track_entry_get_track_complete(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT spine_bool spine_track_entry_was_applied(spine_track_entry entry); +SPINE_CPP_LITE_EXPORT spine_bool spine_track_entry_is_next_ready(spine_track_entry entry); +// OMITTED setListener() +// OMITTED setListener() + +SPINE_CPP_LITE_EXPORT void spine_skeleton_update_cache(spine_skeleton skeleton); +// OMITTED printUpdateCache() +SPINE_CPP_LITE_EXPORT void spine_skeleton_update_world_transform(spine_skeleton skeleton, spine_physics physics); +SPINE_CPP_LITE_EXPORT void spine_skeleton_update_world_transform_bone(spine_skeleton skeleton, spine_physics physics, spine_bone parent); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_to_setup_pose(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_bones_to_setup_pose(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_slots_to_setup_pose(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT spine_bone spine_skeleton_find_bone(spine_skeleton skeleton, const utf8 *boneName); +SPINE_CPP_LITE_EXPORT spine_slot spine_skeleton_find_slot(spine_skeleton skeleton, const utf8 *slotName); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_skin_by_name(spine_skeleton skeleton, const utf8 *skinName); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_skin(spine_skeleton skeleton, spine_skin skin); +// @optional +SPINE_CPP_LITE_EXPORT spine_attachment spine_skeleton_get_attachment_by_name(spine_skeleton skeleton, const utf8 *slotName, const utf8 *attachmentName); +// @optional +SPINE_CPP_LITE_EXPORT spine_attachment spine_skeleton_get_attachment(spine_skeleton skeleton, int32_t slotIndex, const utf8 *attachmentName); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_attachment(spine_skeleton skeleton, const utf8 *slotName, const utf8 *attachmentName); +SPINE_CPP_LITE_EXPORT spine_ik_constraint spine_skeleton_find_ik_constraint(spine_skeleton skeleton, const utf8 *constraintName); +SPINE_CPP_LITE_EXPORT spine_transform_constraint spine_skeleton_find_transform_constraint(spine_skeleton skeleton, const utf8 *constraintName); +SPINE_CPP_LITE_EXPORT spine_path_constraint spine_skeleton_find_path_constraint(spine_skeleton skeleton, const utf8 *constraintName); +SPINE_CPP_LITE_EXPORT spine_physics_constraint spine_skeleton_find_physics_constraint(spine_skeleton skeleton, const utf8 *constraintName); +SPINE_CPP_LITE_EXPORT spine_bounds spine_skeleton_get_bounds(spine_skeleton skeleton); +// @optional +SPINE_CPP_LITE_EXPORT spine_bone spine_skeleton_get_root_bone(spine_skeleton skeleton); +// @optional +SPINE_CPP_LITE_EXPORT spine_skeleton_data spine_skeleton_get_data(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_get_num_bones(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT spine_bone *spine_skeleton_get_bones(spine_skeleton skeleton); +// OMITTED getUpdateCacheList() +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_get_num_slots(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT spine_slot *spine_skeleton_get_slots(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_get_num_draw_order(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT spine_slot *spine_skeleton_get_draw_order(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_get_num_ik_constraints(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT spine_ik_constraint *spine_skeleton_get_ik_constraints(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_get_num_transform_constraints(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT spine_transform_constraint *spine_skeleton_get_transform_constraints(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_get_num_path_constraints(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT spine_path_constraint *spine_skeleton_get_path_constraints(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_get_num_physics_constraints(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT spine_physics_constraint *spine_skeleton_get_physics_constraints(spine_skeleton skeleton); +// @optional +SPINE_CPP_LITE_EXPORT spine_skin spine_skeleton_get_skin(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT spine_color spine_skeleton_get_color(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_color(spine_skeleton skeleton, float r, float g, float b, float a); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_position(spine_skeleton skeleton, float x, float y); +SPINE_CPP_LITE_EXPORT float spine_skeleton_get_x(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_x(spine_skeleton skeleton, float x); +SPINE_CPP_LITE_EXPORT float spine_skeleton_get_y(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_y(spine_skeleton skeleton, float y); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_scale(spine_skeleton skeleton, float scaleX, float scaleY); +SPINE_CPP_LITE_EXPORT float spine_skeleton_get_scale_x(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_scale_x(spine_skeleton skeleton, float scaleX); +SPINE_CPP_LITE_EXPORT float spine_skeleton_get_scale_y(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_scale_y(spine_skeleton skeleton, float scaleY); +SPINE_CPP_LITE_EXPORT float spine_skeleton_get_time(spine_skeleton skeleton); +SPINE_CPP_LITE_EXPORT void spine_skeleton_set_time(spine_skeleton skeleton, float time); +SPINE_CPP_LITE_EXPORT void spine_skeleton_update(spine_skeleton skeleton, float delta); + +SPINE_CPP_LITE_EXPORT const utf8 *spine_event_data_get_name(spine_event_data event); +SPINE_CPP_LITE_EXPORT int32_t spine_event_data_get_int_value(spine_event_data event); +SPINE_CPP_LITE_EXPORT void spine_event_data_set_int_value(spine_event_data event, int32_t value); +SPINE_CPP_LITE_EXPORT float spine_event_data_get_float_value(spine_event_data event); +SPINE_CPP_LITE_EXPORT void spine_event_data_set_float_value(spine_event_data event, float value); +SPINE_CPP_LITE_EXPORT const utf8 *spine_event_data_get_string_value(spine_event_data event); +SPINE_CPP_LITE_EXPORT void spine_event_data_set_string_value(spine_event_data event, const utf8 *value); +SPINE_CPP_LITE_EXPORT const utf8 *spine_event_data_get_audio_path(spine_event_data event); +// OMITTED setAudioPath() +SPINE_CPP_LITE_EXPORT float spine_event_data_get_volume(spine_event_data event); +SPINE_CPP_LITE_EXPORT void spine_event_data_set_volume(spine_event_data event, float volume); +SPINE_CPP_LITE_EXPORT float spine_event_data_get_balance(spine_event_data event); +SPINE_CPP_LITE_EXPORT void spine_event_data_set_balance(spine_event_data event, float balance); + +SPINE_CPP_LITE_EXPORT spine_event_data spine_event_get_data(spine_event event); +SPINE_CPP_LITE_EXPORT float spine_event_get_time(spine_event event); +SPINE_CPP_LITE_EXPORT int32_t spine_event_get_int_value(spine_event event); +SPINE_CPP_LITE_EXPORT void spine_event_set_int_value(spine_event event, int32_t value); +SPINE_CPP_LITE_EXPORT float spine_event_get_float_value(spine_event event); +SPINE_CPP_LITE_EXPORT void spine_event_set_float_value(spine_event event, float value); +SPINE_CPP_LITE_EXPORT const utf8 *spine_event_get_string_value(spine_event event); +SPINE_CPP_LITE_EXPORT void spine_event_set_string_value(spine_event event, const utf8 *value); +SPINE_CPP_LITE_EXPORT float spine_event_get_volume(spine_event event); +SPINE_CPP_LITE_EXPORT void spine_event_set_volume(spine_event event, float volume); +SPINE_CPP_LITE_EXPORT float spine_event_get_balance(spine_event event); +SPINE_CPP_LITE_EXPORT void spine_event_set_balance(spine_event event, float balance); + +SPINE_CPP_LITE_EXPORT int32_t spine_slot_data_get_index(spine_slot_data slot); +SPINE_CPP_LITE_EXPORT const utf8 *spine_slot_data_get_name(spine_slot_data slot); +SPINE_CPP_LITE_EXPORT spine_bone_data spine_slot_data_get_bone_data(spine_slot_data slot); +SPINE_CPP_LITE_EXPORT spine_color spine_slot_data_get_color(spine_slot_data slot); +SPINE_CPP_LITE_EXPORT void spine_slot_data_set_color(spine_slot_data slot, float r, float g, float b, float a); +SPINE_CPP_LITE_EXPORT spine_color spine_slot_data_get_dark_color(spine_slot_data slot); +SPINE_CPP_LITE_EXPORT void spine_slot_data_set_dark_color(spine_slot_data slot, float r, float g, float b, float a); +SPINE_CPP_LITE_EXPORT spine_bool spine_slot_data_get_has_dark_color(spine_slot_data slot); +SPINE_CPP_LITE_EXPORT void spine_slot_data_set_has_dark_color(spine_slot_data slot, spine_bool hasDarkColor); +SPINE_CPP_LITE_EXPORT const utf8 *spine_slot_data_get_attachment_name(spine_slot_data slot); +SPINE_CPP_LITE_EXPORT void spine_slot_data_set_attachment_name(spine_slot_data slot, const utf8 *attachmentName); +SPINE_CPP_LITE_EXPORT spine_blend_mode spine_slot_data_get_blend_mode(spine_slot_data slot); +SPINE_CPP_LITE_EXPORT void spine_slot_data_set_blend_mode(spine_slot_data slot, spine_blend_mode blendMode); +SPINE_CPP_LITE_EXPORT spine_bool spine_slot_data_is_visible(spine_slot_data slot); +SPINE_CPP_LITE_EXPORT void spine_slot_data_set_visible(spine_slot_data slot, spine_bool visible); +// OMITTED getPath()/setPath() + +SPINE_CPP_LITE_EXPORT void spine_slot_set_to_setup_pose(spine_slot slot); +SPINE_CPP_LITE_EXPORT spine_slot_data spine_slot_get_data(spine_slot slot); +SPINE_CPP_LITE_EXPORT spine_bone spine_slot_get_bone(spine_slot slot); +SPINE_CPP_LITE_EXPORT spine_skeleton spine_slot_get_skeleton(spine_slot slot); +SPINE_CPP_LITE_EXPORT spine_color spine_slot_get_color(spine_slot slot); +SPINE_CPP_LITE_EXPORT void spine_slot_set_color(spine_slot slot, float r, float g, float b, float a); +SPINE_CPP_LITE_EXPORT spine_color spine_slot_get_dark_color(spine_slot slot); +SPINE_CPP_LITE_EXPORT void spine_slot_set_dark_color(spine_slot slot, float r, float g, float b, float a); +SPINE_CPP_LITE_EXPORT spine_bool spine_slot_has_dark_color(spine_slot slot); +// @optional +SPINE_CPP_LITE_EXPORT spine_attachment spine_slot_get_attachment(spine_slot slot); +SPINE_CPP_LITE_EXPORT void spine_slot_set_attachment(spine_slot slot, spine_attachment attachment); +// OMITTED getDeform() +SPINE_CPP_LITE_EXPORT int32_t spine_slot_get_sequence_index(spine_slot slot); +SPINE_CPP_LITE_EXPORT void spine_slot_set_sequence_index(spine_slot slot, int32_t sequenceIndex); + +SPINE_CPP_LITE_EXPORT int32_t spine_bone_data_get_index(spine_bone_data data); +SPINE_CPP_LITE_EXPORT const utf8 *spine_bone_data_get_name(spine_bone_data data); +// @optional +SPINE_CPP_LITE_EXPORT spine_bone_data spine_bone_data_get_parent(spine_bone_data data); +SPINE_CPP_LITE_EXPORT float spine_bone_data_get_length(spine_bone_data data); +SPINE_CPP_LITE_EXPORT void spine_bone_data_set_length(spine_bone_data data, float length); +SPINE_CPP_LITE_EXPORT float spine_bone_data_get_x(spine_bone_data data); +SPINE_CPP_LITE_EXPORT void spine_bone_data_set_x(spine_bone_data data, float x); +SPINE_CPP_LITE_EXPORT float spine_bone_data_get_y(spine_bone_data data); +SPINE_CPP_LITE_EXPORT void spine_bone_data_set_y(spine_bone_data data, float y); +SPINE_CPP_LITE_EXPORT float spine_bone_data_get_rotation(spine_bone_data data); +SPINE_CPP_LITE_EXPORT void spine_bone_data_set_rotation(spine_bone_data data, float rotation); +SPINE_CPP_LITE_EXPORT float spine_bone_data_get_scale_x(spine_bone_data data); +SPINE_CPP_LITE_EXPORT void spine_bone_data_set_scale_x(spine_bone_data data, float scaleX); +SPINE_CPP_LITE_EXPORT float spine_bone_data_get_scale_y(spine_bone_data data); +SPINE_CPP_LITE_EXPORT void spine_bone_data_set_scale_y(spine_bone_data data, float scaleY); +SPINE_CPP_LITE_EXPORT float spine_bone_data_get_shear_x(spine_bone_data data); +SPINE_CPP_LITE_EXPORT void spine_bone_data_set_shear_x(spine_bone_data data, float shearx); +SPINE_CPP_LITE_EXPORT float spine_bone_data_get_shear_y(spine_bone_data data); +SPINE_CPP_LITE_EXPORT void spine_bone_data_set_shear_y(spine_bone_data data, float shearY); +SPINE_CPP_LITE_EXPORT spine_inherit spine_bone_data_get_inherit(spine_bone_data data); +SPINE_CPP_LITE_EXPORT void spine_bone_data_set_inherit(spine_bone_data data, spine_inherit inherit); +SPINE_CPP_LITE_EXPORT spine_bool spine_bone_data_get_is_skin_required(spine_bone_data data); +SPINE_CPP_LITE_EXPORT void spine_bone_data_set_is_skin_required(spine_bone_data data, spine_bool isSkinRequired); +SPINE_CPP_LITE_EXPORT spine_color spine_bone_data_get_color(spine_bone_data data); +SPINE_CPP_LITE_EXPORT void spine_bone_data_set_color(spine_bone_data data, float r, float g, float b, float a); +SPINE_CPP_LITE_EXPORT spine_bool spine_bone_data_is_visible(spine_bone_data data); +SPINE_CPP_LITE_EXPORT void spine_bone_data_set_visible(spine_bone_data data, spine_bool isVisible); +// Omitted getIcon()/setIcon() + +SPINE_CPP_LITE_EXPORT void spine_bone_set_is_y_down(spine_bool yDown); +SPINE_CPP_LITE_EXPORT spine_bool spine_bone_get_is_y_down(); +SPINE_CPP_LITE_EXPORT void spine_bone_update(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_update_world_transform(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_update_world_transform_with(spine_bone bone, float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY); +SPINE_CPP_LITE_EXPORT void spine_bone_update_applied_transform(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_to_setup_pose(spine_bone bone); +SPINE_CPP_LITE_EXPORT spine_vector spine_bone_world_to_local(spine_bone bone, float worldX, float worldY); +SPINE_CPP_LITE_EXPORT spine_vector spine_bone_world_to_parent(spine_bone bone, float worldX, float worldY); +SPINE_CPP_LITE_EXPORT spine_vector spine_bone_local_to_world(spine_bone bone, float localX, float localY); +SPINE_CPP_LITE_EXPORT spine_vector spine_bone_parent_to_world(spine_bone bone, float localX, float localY); +SPINE_CPP_LITE_EXPORT float spine_bone_world_to_local_rotation(spine_bone bone, float worldRotation); +SPINE_CPP_LITE_EXPORT float spine_bone_local_to_world_rotation(spine_bone bone, float localRotation); +SPINE_CPP_LITE_EXPORT void spine_bone_rotate_world(spine_bone bone, float degrees); +SPINE_CPP_LITE_EXPORT float spine_bone_get_world_to_local_rotation_x(spine_bone bone); +SPINE_CPP_LITE_EXPORT float spine_bone_get_world_to_local_rotation_y(spine_bone bone); +SPINE_CPP_LITE_EXPORT spine_bone_data spine_bone_get_data(spine_bone bone); +SPINE_CPP_LITE_EXPORT spine_skeleton spine_bone_get_skeleton(spine_bone bone); +// @optional +SPINE_CPP_LITE_EXPORT spine_bone spine_bone_get_parent(spine_bone bone); +SPINE_CPP_LITE_EXPORT int32_t spine_bone_get_num_children(spine_bone bone); +SPINE_CPP_LITE_EXPORT spine_bone *spine_bone_get_children(spine_bone bone); +SPINE_CPP_LITE_EXPORT float spine_bone_get_x(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_x(spine_bone bone, float x); +SPINE_CPP_LITE_EXPORT float spine_bone_get_y(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_y(spine_bone bone, float y); +SPINE_CPP_LITE_EXPORT float spine_bone_get_rotation(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_rotation(spine_bone bone, float rotation); +SPINE_CPP_LITE_EXPORT float spine_bone_get_scale_x(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_scale_x(spine_bone bone, float scaleX); +SPINE_CPP_LITE_EXPORT float spine_bone_get_scale_y(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_scale_y(spine_bone bone, float scaleY); +SPINE_CPP_LITE_EXPORT float spine_bone_get_shear_x(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_shear_x(spine_bone bone, float shearX); +SPINE_CPP_LITE_EXPORT float spine_bone_get_shear_y(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_shear_y(spine_bone bone, float shearY); +SPINE_CPP_LITE_EXPORT float spine_bone_get_applied_rotation(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_applied_rotation(spine_bone bone, float rotation); +SPINE_CPP_LITE_EXPORT float spine_bone_get_a_x(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_a_x(spine_bone bone, float x); +SPINE_CPP_LITE_EXPORT float spine_bone_get_a_y(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_a_y(spine_bone bone, float y); +SPINE_CPP_LITE_EXPORT float spine_bone_get_a_scale_x(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_a_scale_x(spine_bone bone, float scaleX); +SPINE_CPP_LITE_EXPORT float spine_bone_get_a_scale_y(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_a_scale_y(spine_bone bone, float scaleY); +SPINE_CPP_LITE_EXPORT float spine_bone_get_a_shear_x(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_a_shear_x(spine_bone bone, float shearX); +SPINE_CPP_LITE_EXPORT float spine_bone_get_a_shear_y(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_a_shear_y(spine_bone bone, float shearY); +SPINE_CPP_LITE_EXPORT float spine_bone_get_a(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_a(spine_bone bone, float a); +SPINE_CPP_LITE_EXPORT float spine_bone_get_b(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_b(spine_bone bone, float b); +SPINE_CPP_LITE_EXPORT float spine_bone_get_c(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_c(spine_bone bone, float c); +SPINE_CPP_LITE_EXPORT float spine_bone_get_d(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_d(spine_bone bone, float d); +SPINE_CPP_LITE_EXPORT float spine_bone_get_world_x(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_world_x(spine_bone bone, float worldX); +SPINE_CPP_LITE_EXPORT float spine_bone_get_world_y(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_world_y(spine_bone bone, float worldY); +SPINE_CPP_LITE_EXPORT float spine_bone_get_world_rotation_x(spine_bone bone); +SPINE_CPP_LITE_EXPORT float spine_bone_get_world_rotation_y(spine_bone bone); +SPINE_CPP_LITE_EXPORT float spine_bone_get_world_scale_x(spine_bone bone); +SPINE_CPP_LITE_EXPORT float spine_bone_get_world_scale_y(spine_bone bone); +SPINE_CPP_LITE_EXPORT spine_bool spine_bone_get_is_active(spine_bone bone); +SPINE_CPP_LITE_EXPORT void spine_bone_set_is_active(spine_bone bone, spine_bool isActive); +SPINE_CPP_LITE_EXPORT spine_inherit spine_bone_get_inherit(spine_bone data); +SPINE_CPP_LITE_EXPORT void spine_bone_set_inherit(spine_bone data, spine_inherit inherit); + +SPINE_CPP_LITE_EXPORT const utf8 *spine_attachment_get_name(spine_attachment attachment); +SPINE_CPP_LITE_EXPORT spine_attachment_type spine_attachment_get_type(spine_attachment attachment); +// @ignore +SPINE_CPP_LITE_EXPORT spine_attachment spine_attachment_copy(spine_attachment attachment); +// @optional +SPINE_CPP_LITE_EXPORT spine_bounding_box_attachment spine_attachment_cast_to_bounding_box_attachment(spine_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_attachment_dispose(spine_attachment attachment); + +SPINE_CPP_LITE_EXPORT spine_vector spine_point_attachment_compute_world_position(spine_point_attachment attachment, spine_bone bone); +SPINE_CPP_LITE_EXPORT float spine_point_attachment_compute_world_rotation(spine_point_attachment attachment, spine_bone bone); +SPINE_CPP_LITE_EXPORT float spine_point_attachment_get_x(spine_point_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_point_attachment_set_x(spine_point_attachment attachment, float x); +SPINE_CPP_LITE_EXPORT float spine_point_attachment_get_y(spine_point_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_point_attachment_set_y(spine_point_attachment attachment, float y); +SPINE_CPP_LITE_EXPORT float spine_point_attachment_get_rotation(spine_point_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_point_attachment_set_rotation(spine_point_attachment attachment, float rotation); +SPINE_CPP_LITE_EXPORT spine_color spine_point_attachment_get_color(spine_point_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_point_attachment_set_color(spine_point_attachment attachment, float r, float g, float b, float a); + +SPINE_CPP_LITE_EXPORT void spine_region_attachment_update_region(spine_region_attachment attachment); +// @ignore +SPINE_CPP_LITE_EXPORT void spine_region_attachment_compute_world_vertices(spine_region_attachment attachment, spine_slot slot, float *worldVertices); +SPINE_CPP_LITE_EXPORT float spine_region_attachment_get_x(spine_region_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_region_attachment_set_x(spine_region_attachment attachment, float x); +SPINE_CPP_LITE_EXPORT float spine_region_attachment_get_y(spine_region_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_region_attachment_set_y(spine_region_attachment attachment, float y); +SPINE_CPP_LITE_EXPORT float spine_region_attachment_get_rotation(spine_region_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_region_attachment_set_rotation(spine_region_attachment attachment, float rotation); +SPINE_CPP_LITE_EXPORT float spine_region_attachment_get_scale_x(spine_region_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_region_attachment_set_scale_x(spine_region_attachment attachment, float scaleX); +SPINE_CPP_LITE_EXPORT float spine_region_attachment_get_scale_y(spine_region_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_region_attachment_set_scale_y(spine_region_attachment attachment, float scaleY); +SPINE_CPP_LITE_EXPORT float spine_region_attachment_get_width(spine_region_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_region_attachment_set_width(spine_region_attachment attachment, float width); +SPINE_CPP_LITE_EXPORT float spine_region_attachment_get_height(spine_region_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_region_attachment_set_height(spine_region_attachment attachment, float height); +SPINE_CPP_LITE_EXPORT spine_color spine_region_attachment_get_color(spine_region_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_region_attachment_set_color(spine_region_attachment attachment, float r, float g, float b, float a); +SPINE_CPP_LITE_EXPORT const utf8 *spine_region_attachment_get_path(spine_region_attachment attachment); +// OMITTED setPath() +// @optional +SPINE_CPP_LITE_EXPORT spine_texture_region spine_region_attachment_get_region(spine_region_attachment attachment); +// OMITTED setRegion() +// @optional +SPINE_CPP_LITE_EXPORT spine_sequence spine_region_attachment_get_sequence(spine_region_attachment attachment); +// OMITTED setSequence() +SPINE_CPP_LITE_EXPORT int32_t spine_region_attachment_get_num_offset(spine_region_attachment attachment); +SPINE_CPP_LITE_EXPORT float *spine_region_attachment_get_offset(spine_region_attachment attachment); +SPINE_CPP_LITE_EXPORT int32_t spine_region_attachment_get_num_uvs(spine_region_attachment attachment); +SPINE_CPP_LITE_EXPORT float *spine_region_attachment_get_uvs(spine_region_attachment attachment); + +SPINE_CPP_LITE_EXPORT int32_t spine_vertex_attachment_get_world_vertices_length(spine_vertex_attachment attachment); +// @ignore +SPINE_CPP_LITE_EXPORT void spine_vertex_attachment_compute_world_vertices(spine_vertex_attachment attachment, spine_slot slot, float *worldVertices); +// OMITTED getId() +SPINE_CPP_LITE_EXPORT int32_t spine_vertex_attachment_get_num_bones(spine_vertex_attachment attachment); +SPINE_CPP_LITE_EXPORT int32_t *spine_vertex_attachment_get_bones(spine_vertex_attachment attachment); +SPINE_CPP_LITE_EXPORT int32_t spine_vertex_attachment_get_num_vertices(spine_vertex_attachment attachment); +SPINE_CPP_LITE_EXPORT float *spine_vertex_attachment_get_vertices(spine_vertex_attachment attachment); +// @optional +SPINE_CPP_LITE_EXPORT spine_attachment spine_vertex_attachment_get_timeline_attachment(spine_vertex_attachment timelineAttachment); +SPINE_CPP_LITE_EXPORT void spine_vertex_attachment_set_timeline_attachment(spine_vertex_attachment attachment, spine_attachment timelineAttachment); +// OMITTED copyTo() + +SPINE_CPP_LITE_EXPORT void spine_mesh_attachment_update_region(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT int32_t spine_mesh_attachment_get_hull_length(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_mesh_attachment_set_hull_length(spine_mesh_attachment attachment, int32_t hullLength); +SPINE_CPP_LITE_EXPORT int32_t spine_mesh_attachment_get_num_region_uvs(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT float *spine_mesh_attachment_get_region_uvs(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT int32_t spine_mesh_attachment_get_num_uvs(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT float *spine_mesh_attachment_get_uvs(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT int32_t spine_mesh_attachment_get_num_triangles(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT uint16_t *spine_mesh_attachment_get_triangles(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT spine_color spine_mesh_attachment_get_color(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_mesh_attachment_set_color(spine_mesh_attachment attachment, float r, float g, float b, float a); +SPINE_CPP_LITE_EXPORT const utf8 *spine_mesh_attachment_get_path(spine_mesh_attachment attachment); +// OMITTED setPath() +SPINE_CPP_LITE_EXPORT spine_texture_region spine_mesh_attachment_get_region(spine_mesh_attachment attachment); +// OMITTED setRegion() +// @optional +SPINE_CPP_LITE_EXPORT spine_sequence spine_mesh_attachment_get_sequence(spine_mesh_attachment attachment); +// OMITTED setSequence() +// @optional +SPINE_CPP_LITE_EXPORT spine_mesh_attachment spine_mesh_attachment_get_parent_mesh(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_mesh_attachment_set_parent_mesh(spine_mesh_attachment attachment, spine_mesh_attachment parentMesh); +SPINE_CPP_LITE_EXPORT int32_t spine_mesh_attachment_get_num_edges(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT uint16_t *spine_mesh_attachment_get_edges(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT float spine_mesh_attachment_get_width(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_mesh_attachment_set_width(spine_mesh_attachment attachment, float width); +SPINE_CPP_LITE_EXPORT float spine_mesh_attachment_get_height(spine_mesh_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_mesh_attachment_set_height(spine_mesh_attachment attachment, float height); +// OMITTED newLinkedMesh() + +// @optional +SPINE_CPP_LITE_EXPORT spine_slot_data spine_clipping_attachment_get_end_slot(spine_clipping_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_clipping_attachment_set_end_slot(spine_clipping_attachment attachment, spine_slot_data endSlot); +SPINE_CPP_LITE_EXPORT spine_color spine_clipping_attachment_get_color(spine_clipping_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_clipping_attachment_set_color(spine_clipping_attachment attachment, float r, float g, float b, float a); + +SPINE_CPP_LITE_EXPORT spine_color spine_bounding_box_attachment_get_color(spine_bounding_box_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_bounding_box_attachment_set_color(spine_bounding_box_attachment attachment, float r, float g, float b, float a); + +SPINE_CPP_LITE_EXPORT int32_t spine_path_attachment_get_num_lengths(spine_path_attachment attachment); +SPINE_CPP_LITE_EXPORT float *spine_path_attachment_get_lengths(spine_path_attachment attachment); +SPINE_CPP_LITE_EXPORT spine_bool spine_path_attachment_get_is_closed(spine_path_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_path_attachment_set_is_closed(spine_path_attachment attachment, spine_bool isClosed); +SPINE_CPP_LITE_EXPORT spine_bool spine_path_attachment_get_is_constant_speed(spine_path_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_path_attachment_set_is_constant_speed(spine_path_attachment attachment, spine_bool isConstantSpeed); +SPINE_CPP_LITE_EXPORT spine_color spine_path_attachment_get_color(spine_path_attachment attachment); +SPINE_CPP_LITE_EXPORT void spine_path_attachment_set_color(spine_path_attachment attachment, float r, float g, float b, float a); + +SPINE_CPP_LITE_EXPORT void spine_skin_set_attachment(spine_skin skin, int32_t slotIndex, const utf8 *name, spine_attachment attachment); +// @optional +SPINE_CPP_LITE_EXPORT spine_attachment spine_skin_get_attachment(spine_skin skin, int32_t slotIndex, const utf8 *name); +SPINE_CPP_LITE_EXPORT void spine_skin_remove_attachment(spine_skin skin, int32_t slotIndex, const utf8 *name); +// OMITTED findNamesForSlot() +// OMITTED findAttachmentsForSlot() +// OMITTED getColor() +SPINE_CPP_LITE_EXPORT const utf8 *spine_skin_get_name(spine_skin skin); +SPINE_CPP_LITE_EXPORT void spine_skin_add_skin(spine_skin skin, spine_skin other); +SPINE_CPP_LITE_EXPORT void spine_skin_copy_skin(spine_skin skin, spine_skin other); +SPINE_CPP_LITE_EXPORT spine_skin_entries spine_skin_get_entries(spine_skin skin); +SPINE_CPP_LITE_EXPORT int32_t spine_skin_entries_get_num_entries(spine_skin_entries entries); +SPINE_CPP_LITE_EXPORT spine_skin_entry spine_skin_entries_get_entry(spine_skin_entries entries, int32_t index); +SPINE_CPP_LITE_EXPORT void spine_skin_entries_dispose(spine_skin_entries entries); +SPINE_CPP_LITE_EXPORT int32_t spine_skin_entry_get_slot_index(spine_skin_entry entry); +SPINE_CPP_LITE_EXPORT utf8 *spine_skin_entry_get_name(spine_skin_entry entry); +SPINE_CPP_LITE_EXPORT spine_attachment spine_skin_entry_get_attachment(spine_skin_entry entry); +SPINE_CPP_LITE_EXPORT int32_t spine_skin_get_num_bones(spine_skin skin); +SPINE_CPP_LITE_EXPORT spine_bone_data *spine_skin_get_bones(spine_skin skin); +SPINE_CPP_LITE_EXPORT int32_t spine_skin_get_num_constraints(spine_skin skin); +SPINE_CPP_LITE_EXPORT spine_constraint_data *spine_skin_get_constraints(spine_skin skin); +// @ignore +SPINE_CPP_LITE_EXPORT spine_skin spine_skin_create(const utf8 *name); +SPINE_CPP_LITE_EXPORT void spine_skin_dispose(spine_skin skin); + +SPINE_CPP_LITE_EXPORT spine_constraint_type spine_constraint_data_get_type(spine_constraint_data data); +SPINE_CPP_LITE_EXPORT const utf8 *spine_constraint_data_get_name(spine_constraint_data data); +SPINE_CPP_LITE_EXPORT uint64_t spine_constraint_data_get_order(spine_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_constraint_data_set_order(spine_constraint_data data, uint64_t order); +SPINE_CPP_LITE_EXPORT spine_bool spine_constraint_data_get_is_skin_required(spine_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_constraint_data_set_is_skin_required(spine_constraint_data data, spine_bool isSkinRequired); + +SPINE_CPP_LITE_EXPORT int32_t spine_ik_constraint_data_get_num_bones(spine_ik_constraint_data data); +SPINE_CPP_LITE_EXPORT spine_bone_data *spine_ik_constraint_data_get_bones(spine_ik_constraint_data data); +SPINE_CPP_LITE_EXPORT spine_bone_data spine_ik_constraint_data_get_target(spine_ik_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_data_set_target(spine_ik_constraint_data data, spine_bone_data target); +SPINE_CPP_LITE_EXPORT int32_t spine_ik_constraint_data_get_bend_direction(spine_ik_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_data_set_bend_direction(spine_ik_constraint_data data, int32_t bendDirection); +SPINE_CPP_LITE_EXPORT spine_bool spine_ik_constraint_data_get_compress(spine_ik_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_data_set_compress(spine_ik_constraint_data data, spine_bool compress); +SPINE_CPP_LITE_EXPORT spine_bool spine_ik_constraint_data_get_stretch(spine_ik_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_data_set_stretch(spine_ik_constraint_data data, spine_bool stretch); +SPINE_CPP_LITE_EXPORT spine_bool spine_ik_constraint_data_get_uniform(spine_ik_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_data_set_uniform(spine_ik_constraint_data data, spine_bool uniform); +SPINE_CPP_LITE_EXPORT float spine_ik_constraint_data_get_mix(spine_ik_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_data_set_mix(spine_ik_constraint_data data, float mix); +SPINE_CPP_LITE_EXPORT float spine_ik_constraint_data_get_softness(spine_ik_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_data_set_softness(spine_ik_constraint_data data, float softness); + +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_update(spine_ik_constraint constraint); +SPINE_CPP_LITE_EXPORT int32_t spine_ik_constraint_get_order(spine_ik_constraint constraint); +SPINE_CPP_LITE_EXPORT spine_ik_constraint_data spine_ik_constraint_get_data(spine_ik_constraint constraint); +SPINE_CPP_LITE_EXPORT int32_t spine_ik_constraint_get_num_bones(spine_ik_constraint constraint); +SPINE_CPP_LITE_EXPORT spine_bone *spine_ik_constraint_get_bones(spine_ik_constraint constraint); +SPINE_CPP_LITE_EXPORT spine_bone spine_ik_constraint_get_target(spine_ik_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_set_target(spine_ik_constraint constraint, spine_bone target); +SPINE_CPP_LITE_EXPORT int32_t spine_ik_constraint_get_bend_direction(spine_ik_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_set_bend_direction(spine_ik_constraint constraint, int32_t bendDirection); +SPINE_CPP_LITE_EXPORT spine_bool spine_ik_constraint_get_compress(spine_ik_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_set_compress(spine_ik_constraint constraint, spine_bool compress); +SPINE_CPP_LITE_EXPORT spine_bool spine_ik_constraint_get_stretch(spine_ik_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_set_stretch(spine_ik_constraint constraint, spine_bool stretch); +SPINE_CPP_LITE_EXPORT float spine_ik_constraint_get_mix(spine_ik_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_set_mix(spine_ik_constraint constraint, float mix); +SPINE_CPP_LITE_EXPORT float spine_ik_constraint_get_softness(spine_ik_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_set_softness(spine_ik_constraint constraint, float softness); +SPINE_CPP_LITE_EXPORT spine_bool spine_ik_constraint_get_is_active(spine_ik_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_ik_constraint_set_is_active(spine_ik_constraint constraint, spine_bool isActive); +// OMITTED setToSetupPose() + +SPINE_CPP_LITE_EXPORT int32_t spine_transform_constraint_data_get_num_bones(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT spine_bone_data *spine_transform_constraint_data_get_bones(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT spine_bone_data spine_transform_constraint_data_get_target(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_target(spine_transform_constraint_data data, spine_bone_data target); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_data_get_mix_rotate(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_mix_rotate(spine_transform_constraint_data data, float mixRotate); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_data_get_mix_x(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_mix_x(spine_transform_constraint_data data, float mixX); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_data_get_mix_y(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_mix_y(spine_transform_constraint_data data, float mixY); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_data_get_mix_scale_x(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_mix_scale_x(spine_transform_constraint_data data, float mixScaleX); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_data_get_mix_scale_y(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_mix_scale_y(spine_transform_constraint_data data, float mixScaleY); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_data_get_mix_shear_y(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_mix_shear_y(spine_transform_constraint_data data, float mixShearY); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_data_get_offset_rotation(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_offset_rotation(spine_transform_constraint_data data, float offsetRotation); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_data_get_offset_x(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_offset_x(spine_transform_constraint_data data, float offsetX); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_data_get_offset_y(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_offset_y(spine_transform_constraint_data data, float offsetY); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_data_get_offset_scale_x(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_offset_scale_x(spine_transform_constraint_data data, float offsetScaleX); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_data_get_offset_scale_y(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_offset_scale_y(spine_transform_constraint_data data, float offsetScaleY); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_data_get_offset_shear_y(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_offset_shear_y(spine_transform_constraint_data data, float offsetShearY); +SPINE_CPP_LITE_EXPORT spine_bool spine_transform_constraint_data_get_is_relative(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_is_relative(spine_transform_constraint_data data, spine_bool isRelative); +SPINE_CPP_LITE_EXPORT spine_bool spine_transform_constraint_data_get_is_local(spine_transform_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_data_set_is_local(spine_transform_constraint_data data, spine_bool isLocal); + +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_update(spine_transform_constraint constraint); +SPINE_CPP_LITE_EXPORT int32_t spine_transform_constraint_get_order(spine_transform_constraint constraint); +SPINE_CPP_LITE_EXPORT spine_transform_constraint_data spine_transform_constraint_get_data(spine_transform_constraint constraint); +SPINE_CPP_LITE_EXPORT int32_t spine_transform_constraint_get_num_bones(spine_transform_constraint constraint); +SPINE_CPP_LITE_EXPORT spine_bone *spine_transform_constraint_get_bones(spine_transform_constraint constraint); +SPINE_CPP_LITE_EXPORT spine_bone spine_transform_constraint_get_target(spine_transform_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_set_target(spine_transform_constraint constraint, spine_bone target); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_get_mix_rotate(spine_transform_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_set_mix_rotate(spine_transform_constraint constraint, float mixRotate); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_get_mix_x(spine_transform_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_set_mix_x(spine_transform_constraint constraint, float mixX); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_get_mix_y(spine_transform_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_set_mix_y(spine_transform_constraint constraint, float mixY); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_get_mix_scale_x(spine_transform_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_set_mix_scale_x(spine_transform_constraint constraint, float mixScaleX); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_get_mix_scale_y(spine_transform_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_set_mix_scale_y(spine_transform_constraint constraint, float mixScaleY); +SPINE_CPP_LITE_EXPORT float spine_transform_constraint_get_mix_shear_y(spine_transform_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_set_mix_shear_y(spine_transform_constraint constraint, float mixShearY); +SPINE_CPP_LITE_EXPORT spine_bool spine_transform_constraint_get_is_active(spine_transform_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_transform_constraint_set_is_active(spine_transform_constraint constraint, spine_bool isActive); + +// OMITTED setToSetupPose() + +SPINE_CPP_LITE_EXPORT int32_t spine_path_constraint_data_get_num_bones(spine_path_constraint_data data); +SPINE_CPP_LITE_EXPORT spine_bone_data *spine_path_constraint_data_get_bones(spine_path_constraint_data data); +SPINE_CPP_LITE_EXPORT spine_slot_data spine_path_constraint_data_get_target(spine_path_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_data_set_target(spine_path_constraint_data data, spine_slot_data target); +SPINE_CPP_LITE_EXPORT spine_position_mode spine_path_constraint_data_get_position_mode(spine_path_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_data_set_position_mode(spine_path_constraint_data data, spine_position_mode positionMode); +SPINE_CPP_LITE_EXPORT spine_spacing_mode spine_path_constraint_data_get_spacing_mode(spine_path_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_data_set_spacing_mode(spine_path_constraint_data data, spine_spacing_mode spacingMode); +SPINE_CPP_LITE_EXPORT spine_rotate_mode spine_path_constraint_data_get_rotate_mode(spine_path_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_data_set_rotate_mode(spine_path_constraint_data data, spine_rotate_mode rotateMode); +SPINE_CPP_LITE_EXPORT float spine_path_constraint_data_get_offset_rotation(spine_path_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_data_set_offset_rotation(spine_path_constraint_data data, float offsetRotation); +SPINE_CPP_LITE_EXPORT float spine_path_constraint_data_get_position(spine_path_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_data_set_position(spine_path_constraint_data data, float position); +SPINE_CPP_LITE_EXPORT float spine_path_constraint_data_get_spacing(spine_path_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_data_set_spacing(spine_path_constraint_data data, float spacing); +SPINE_CPP_LITE_EXPORT float spine_path_constraint_data_get_mix_rotate(spine_path_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_data_set_mix_rotate(spine_path_constraint_data data, float mixRotate); +SPINE_CPP_LITE_EXPORT float spine_path_constraint_data_get_mix_x(spine_path_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_data_set_mix_x(spine_path_constraint_data data, float mixX); +SPINE_CPP_LITE_EXPORT float spine_path_constraint_data_get_mix_y(spine_path_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_data_set_mix_y(spine_path_constraint_data data, float mixY); + +SPINE_CPP_LITE_EXPORT void spine_path_constraint_update(spine_path_constraint constraint); +SPINE_CPP_LITE_EXPORT int32_t spine_path_constraint_get_order(spine_path_constraint constraint); +SPINE_CPP_LITE_EXPORT spine_path_constraint_data spine_path_constraint_get_data(spine_path_constraint constraint); +SPINE_CPP_LITE_EXPORT int32_t spine_path_constraint_get_num_bones(spine_path_constraint constraint); +SPINE_CPP_LITE_EXPORT spine_bone *spine_path_constraint_get_bones(spine_path_constraint constraint); +SPINE_CPP_LITE_EXPORT spine_slot spine_path_constraint_get_target(spine_path_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_set_target(spine_path_constraint constraint, spine_slot target); +SPINE_CPP_LITE_EXPORT float spine_path_constraint_get_position(spine_path_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_set_position(spine_path_constraint constraint, float position); +SPINE_CPP_LITE_EXPORT float spine_path_constraint_get_spacing(spine_path_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_set_spacing(spine_path_constraint constraint, float spacing); +SPINE_CPP_LITE_EXPORT float spine_path_constraint_get_mix_rotate(spine_path_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_set_mix_rotate(spine_path_constraint constraint, float mixRotate); +SPINE_CPP_LITE_EXPORT float spine_path_constraint_get_mix_x(spine_path_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_set_mix_x(spine_path_constraint constraint, float mixX); +SPINE_CPP_LITE_EXPORT float spine_path_constraint_get_mix_y(spine_path_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_set_mix_y(spine_path_constraint constraint, float mixY); +SPINE_CPP_LITE_EXPORT spine_bool spine_path_constraint_get_is_active(spine_path_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_path_constraint_set_is_active(spine_path_constraint constraint, spine_bool isActive); +// OMITTED setToSetupPose() + +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_bone(spine_physics_constraint_data data, spine_bone_data bone); +SPINE_CPP_LITE_EXPORT spine_bone_data spine_physics_constraint_data_get_bone(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_x(spine_physics_constraint_data data, float x); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_x(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_y(spine_physics_constraint_data data, float y); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_y(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_rotate(spine_physics_constraint_data data, float rotate); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_rotate(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_scale_x(spine_physics_constraint_data data, float scaleX); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_scale_x(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_shear_x(spine_physics_constraint_data data, float shearX); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_shear_x(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_limit(spine_physics_constraint_data data, float limit); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_limit(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_step(spine_physics_constraint_data data, float step); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_step(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_inertia(spine_physics_constraint_data data, float inertia); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_inertia(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_strength(spine_physics_constraint_data data, float strength); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_strength(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_damping(spine_physics_constraint_data data, float damping); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_damping(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_mass_inverse(spine_physics_constraint_data data, float massInverse); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_mass_inverse(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_wind(spine_physics_constraint_data data, float wind); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_wind(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_gravity(spine_physics_constraint_data data, float gravity); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_gravity(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_mix(spine_physics_constraint_data data, float mix); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_data_get_mix(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_inertia_global(spine_physics_constraint_data data, spine_bool inertiaGlobal); +SPINE_CPP_LITE_EXPORT spine_bool spine_physics_constraint_data_is_inertia_global(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_strength_global(spine_physics_constraint_data data, spine_bool strengthGlobal); +SPINE_CPP_LITE_EXPORT spine_bool spine_physics_constraint_data_is_strength_global(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_damping_global(spine_physics_constraint_data data, spine_bool dampingGlobal); +SPINE_CPP_LITE_EXPORT spine_bool spine_physics_constraint_data_is_damping_global(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_mass_global(spine_physics_constraint_data data, spine_bool massGlobal); +SPINE_CPP_LITE_EXPORT spine_bool spine_physics_constraint_data_is_mass_global(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_wind_global(spine_physics_constraint_data data, spine_bool windGlobal); +SPINE_CPP_LITE_EXPORT spine_bool spine_physics_constraint_data_is_wind_global(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_gravity_global(spine_physics_constraint_data data, spine_bool gravityGlobal); +SPINE_CPP_LITE_EXPORT spine_bool spine_physics_constraint_data_is_gravity_global(spine_physics_constraint_data data); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_data_set_mix_global(spine_physics_constraint_data data, spine_bool mixGlobal); +SPINE_CPP_LITE_EXPORT spine_bool spine_physics_constraint_data_is_mix_global(spine_physics_constraint_data data); + +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_bone(spine_physics_constraint constraint, spine_bone bone); +SPINE_CPP_LITE_EXPORT spine_bone spine_physics_constraint_get_bone(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_inertia(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_inertia(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_strength(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_strength(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_damping(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_damping(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_mass_inverse(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_mass_inverse(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_wind(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_wind(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_gravity(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_gravity(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_mix(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_mix(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_reset(spine_physics_constraint constraint, spine_bool value); +SPINE_CPP_LITE_EXPORT spine_bool spine_physics_constraint_get_reset(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_ux(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_ux(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_uy(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_uy(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_cx(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_cx(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_cy(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_cy(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_tx(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_tx(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_ty(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_ty(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_x_offset(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_x_offset(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_x_velocity(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_x_velocity(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_y_offset(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_y_offset(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_y_velocity(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_y_velocity(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_rotate_offset(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_rotate_offset(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_rotate_velocity(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_rotate_velocity(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_scale_offset(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_scale_offset(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_scale_velocity(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_scale_velocity(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_active(spine_physics_constraint constraint, spine_bool value); +SPINE_CPP_LITE_EXPORT spine_bool spine_physics_constraint_is_active(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_remaining(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_remaining(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_set_last_time(spine_physics_constraint constraint, float value); +SPINE_CPP_LITE_EXPORT float spine_physics_constraint_get_last_time(spine_physics_constraint constraint); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_reset_fully(spine_physics_constraint constraint); +// Omitted setToSetupPose() +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_update(spine_physics_constraint data, spine_physics physics); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_translate(spine_physics_constraint data, float x, float y); +SPINE_CPP_LITE_EXPORT void spine_physics_constraint_rotate(spine_physics_constraint data, float x, float y, float degrees); + + +// OMITTED copy() +SPINE_CPP_LITE_EXPORT void spine_sequence_apply(spine_sequence sequence, spine_slot slot, spine_attachment attachment); +SPINE_CPP_LITE_EXPORT const utf8 *spine_sequence_get_path(spine_sequence sequence, const utf8 *basePath, int32_t index); +SPINE_CPP_LITE_EXPORT int32_t spine_sequence_get_id(spine_sequence sequence); +SPINE_CPP_LITE_EXPORT void spine_sequence_set_id(spine_sequence sequence, int32_t id); +SPINE_CPP_LITE_EXPORT int32_t spine_sequence_get_start(spine_sequence sequence); +SPINE_CPP_LITE_EXPORT void spine_sequence_set_start(spine_sequence sequence, int32_t start); +SPINE_CPP_LITE_EXPORT int32_t spine_sequence_get_digits(spine_sequence sequence); +SPINE_CPP_LITE_EXPORT void spine_sequence_set_digits(spine_sequence sequence, int32_t digits); +SPINE_CPP_LITE_EXPORT int32_t spine_sequence_get_setup_index(spine_sequence sequence); +SPINE_CPP_LITE_EXPORT void spine_sequence_set_setup_index(spine_sequence sequence, int32_t setupIndex); +SPINE_CPP_LITE_EXPORT int32_t spine_sequence_get_num_regions(spine_sequence sequence); +SPINE_CPP_LITE_EXPORT spine_texture_region *spine_sequence_get_regions(spine_sequence sequence); + +SPINE_CPP_LITE_EXPORT void *spine_texture_region_get_texture(spine_texture_region textureRegion); +SPINE_CPP_LITE_EXPORT void spine_texture_region_set_texture(spine_texture_region textureRegion, void *texture); +SPINE_CPP_LITE_EXPORT float spine_texture_region_get_u(spine_texture_region textureRegion); +SPINE_CPP_LITE_EXPORT void spine_texture_region_set_u(spine_texture_region textureRegion, float u); +SPINE_CPP_LITE_EXPORT float spine_texture_region_get_v(spine_texture_region textureRegion); +SPINE_CPP_LITE_EXPORT void spine_texture_region_set_v(spine_texture_region textureRegion, float v); +SPINE_CPP_LITE_EXPORT float spine_texture_region_get_u2(spine_texture_region textureRegion); +SPINE_CPP_LITE_EXPORT void spine_texture_region_set_u2(spine_texture_region textureRegion, float u2); +SPINE_CPP_LITE_EXPORT float spine_texture_region_get_v2(spine_texture_region textureRegion); +SPINE_CPP_LITE_EXPORT void spine_texture_region_set_v2(spine_texture_region textureRegion, float v2); +SPINE_CPP_LITE_EXPORT int32_t spine_texture_region_get_degrees(spine_texture_region textureRegion); +SPINE_CPP_LITE_EXPORT void spine_texture_region_set_degrees(spine_texture_region textureRegion, int32_t degrees); +SPINE_CPP_LITE_EXPORT float spine_texture_region_get_offset_x(spine_texture_region textureRegion); +SPINE_CPP_LITE_EXPORT void spine_texture_region_set_offset_x(spine_texture_region textureRegion, float offsetX); +SPINE_CPP_LITE_EXPORT float spine_texture_region_get_offset_y(spine_texture_region textureRegion); +SPINE_CPP_LITE_EXPORT void spine_texture_region_set_offset_y(spine_texture_region textureRegion, float offsetY); +SPINE_CPP_LITE_EXPORT int32_t spine_texture_region_get_width(spine_texture_region textureRegion); +SPINE_CPP_LITE_EXPORT void spine_texture_region_set_width(spine_texture_region textureRegion, int32_t width); +SPINE_CPP_LITE_EXPORT int32_t spine_texture_region_get_height(spine_texture_region textureRegion); +SPINE_CPP_LITE_EXPORT void spine_texture_region_set_height(spine_texture_region textureRegion, int32_t height); +SPINE_CPP_LITE_EXPORT int32_t spine_texture_region_get_original_width(spine_texture_region textureRegion); +SPINE_CPP_LITE_EXPORT void spine_texture_region_set_original_width(spine_texture_region textureRegion, int32_t originalWidth); +SPINE_CPP_LITE_EXPORT int32_t spine_texture_region_get_original_height(spine_texture_region textureRegion); +SPINE_CPP_LITE_EXPORT void spine_texture_region_set_original_height(spine_texture_region textureRegion, int32_t originalHeight); + +// @ignore +SPINE_CPP_LITE_EXPORT spine_skeleton_bounds spine_skeleton_bounds_create(); +SPINE_CPP_LITE_EXPORT void spine_skeleton_bounds_dispose(spine_skeleton_bounds bounds); +SPINE_CPP_LITE_EXPORT void spine_skeleton_bounds_update(spine_skeleton_bounds bounds, spine_skeleton skeleton, spine_bool updateAabb); +SPINE_CPP_LITE_EXPORT spine_bool spine_skeleton_bounds_aabb_contains_point(spine_skeleton_bounds bounds, float x, float y); +SPINE_CPP_LITE_EXPORT spine_bool spine_skeleton_bounds_aabb_intersects_segment(spine_skeleton_bounds bounds, float x1, float y1, float x2, float y2); +SPINE_CPP_LITE_EXPORT spine_bool spine_skeleton_bounds_aabb_intersects_skeleton(spine_skeleton_bounds bounds, spine_skeleton_bounds otherBounds); +SPINE_CPP_LITE_EXPORT spine_bool spine_skeleton_bounds_contains_point(spine_skeleton_bounds bounds, spine_polygon polygon, float x, float y); +SPINE_CPP_LITE_EXPORT spine_bounding_box_attachment spine_skeleton_bounds_contains_point_attachment(spine_skeleton_bounds bounds, float x, float y); +SPINE_CPP_LITE_EXPORT spine_bounding_box_attachment spine_skeleton_bounds_intersects_segment_attachment(spine_skeleton_bounds bounds, float x1, float y1, float x2, float y2); +SPINE_CPP_LITE_EXPORT spine_bool spine_skeleton_bounds_intersects_segment(spine_skeleton_bounds bounds, spine_polygon polygon, float x1, float y1, float x2, float y2); +SPINE_CPP_LITE_EXPORT spine_polygon spine_skeleton_bounds_get_polygon(spine_skeleton_bounds bounds, spine_bounding_box_attachment attachment); +SPINE_CPP_LITE_EXPORT spine_bounding_box_attachment spine_skeleton_bounds_get_bounding_box(spine_skeleton_bounds bounds, spine_polygon polygon); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_bounds_get_num_polygons(spine_skeleton_bounds bounds); +SPINE_CPP_LITE_EXPORT spine_polygon *spine_skeleton_bounds_get_polygons(spine_skeleton_bounds bounds); +SPINE_CPP_LITE_EXPORT int32_t spine_skeleton_bounds_get_num_bounding_boxes(spine_skeleton_bounds bounds); +SPINE_CPP_LITE_EXPORT spine_bounding_box_attachment *spine_skeleton_bounds_get_bounding_boxes(spine_skeleton_bounds bounds); +SPINE_CPP_LITE_EXPORT float spine_skeleton_bounds_get_width(spine_skeleton_bounds bounds); +SPINE_CPP_LITE_EXPORT float spine_skeleton_bounds_get_height(spine_skeleton_bounds bounds); + +SPINE_CPP_LITE_EXPORT int32_t spine_polygon_get_num_vertices(spine_polygon polygon); +SPINE_CPP_LITE_EXPORT float *spine_polygon_get_vertices(spine_polygon polygon); + +// @end: function_declarations + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Animation.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Animation.h new file mode 100644 index 0000000..7c9355c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Animation.h @@ -0,0 +1,131 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Animation_h +#define Spine_Animation_h + +#include +#include +#include +#include +#include +#include +#include + +namespace spine { + class Timeline; + + class Skeleton; + + class Event; + + class AnimationState; + + class SP_API Animation : public SpineObject { + friend class AnimationState; + + friend class TrackEntry; + + friend class AnimationStateData; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class RotateTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + friend class TwoColorTimeline; + + public: + Animation(const String &name, Vector &timelines, float duration); + + ~Animation(); + + /// Applies all the animation's timelines to the specified skeleton. + /// See also Timeline::apply(Skeleton&, float, float, Vector, float, MixPose, MixDirection) + void apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction); + + const String &getName(); + + Vector &getTimelines(); + + bool hasTimeline(Vector &ids); + + float getDuration(); + + void setDuration(float inValue); + + /// @param target After the first and before the last entry. + static int search(Vector &values, float target); + + static int search(Vector &values, float target, int step); + private: + Vector _timelines; + HashMap _timelineIds; + float _duration; + String _name; + }; +} + +#endif /* Spine_Animation_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AnimationState.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AnimationState.h new file mode 100644 index 0000000..501e722 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -0,0 +1,521 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AnimationState_h +#define Spine_AnimationState_h + +#include +#include +#include +#include +#include +#include +#include +#include "Slot.h" + +#ifdef SPINE_USE_STD_FUNCTION +#include +#endif + +namespace spine { + enum EventType { + EventType_Start = 0, + EventType_Interrupt, + EventType_End, + EventType_Complete, + EventType_Dispose, + EventType_Event + }; + + class AnimationState; + + class TrackEntry; + + class Animation; + + class Event; + + class AnimationStateData; + + class Skeleton; + + class RotateTimeline; + + class AttachmentTimeline; + +#ifdef SPINE_USE_STD_FUNCTION + typedef std::function AnimationStateListener; +#else + + typedef void (*AnimationStateListener)(AnimationState *state, EventType type, TrackEntry *entry, Event *event); + +#endif + + /// Abstract class to inherit from to create a callback object + class SP_API AnimationStateListenerObject { + public: + AnimationStateListenerObject() {}; + + virtual ~AnimationStateListenerObject() {}; + public: + /// The callback function to be called + virtual void callback(AnimationState *state, EventType type, TrackEntry *entry, Event *event) = 0; + }; + + /// State for the playback of an animation + class SP_API TrackEntry : public SpineObject, public HasRendererObject { + friend class EventQueue; + + friend class AnimationState; + + public: + TrackEntry(); + + virtual ~TrackEntry(); + + /// The index of the track where this entry is either current or queued. + int getTrackIndex(); + + /// The animation to apply for this track entry. + Animation *getAnimation(); + + TrackEntry *getPrevious(); + + /// If true, the animation will repeat. If false, it will not, instead its last frame is applied if played beyond its duration. + bool getLoop(); + + void setLoop(bool inValue); + + /// If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead + /// of being mixed out. + /// + /// When mixing between animations that key the same property, if a lower track also keys that property then the value will + /// briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0% + /// while the second animation mixes from 0% to 100%. Setting holdPrevious to true applies the first animation + /// at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which + /// keys the property, only when a higher track also keys the property. + /// + /// Snapping will occur if holdPrevious is true and this animation does not key all the same properties as the + /// previous animation. + bool getHoldPrevious(); + + void setHoldPrevious(bool inValue); + + bool getReverse(); + + void setReverse(bool inValue); + + bool getShortestRotation(); + + void setShortestRotation(bool inValue); + + /// Seconds to postpone playing the animation. When a track entry is the current track entry, delay postpones incrementing + /// the track time. When a track entry is queued, delay is the time from the start of the previous animation to when the + /// track entry will become the current track entry. + float getDelay(); + + void setDelay(float inValue); + + /// Current time in seconds this track entry has been the current track entry. The track time determines + /// TrackEntry.AnimationTime. The track time can be set to start the animation at a time other than 0, without affecting looping. + float getTrackTime(); + + void setTrackTime(float inValue); + + /// The track time in seconds when this animation will be removed from the track. Defaults to the animation duration for + /// non-looping animations and to int.MaxValue for looping animations. If the track end time is reached and no + /// other animations are queued for playback, and mixing from any previous animations is complete, properties keyed by the animation, + /// are set to the setup pose and the track is cleared. + /// + /// It may be desired to use AnimationState.addEmptyAnimation(int, float, float) to mix the properties back to the + /// setup pose over time, rather than have it happen instantly. + float getTrackEnd(); + + void setTrackEnd(float inValue); + + /// Seconds when this animation starts, both initially and after looping. Defaults to 0. + /// + /// When changing the animation start time, it often makes sense to set TrackEntry.AnimationLast to the same value to + /// prevent timeline keys before the start time from triggering. + float getAnimationStart(); + + void setAnimationStart(float inValue); + + /// Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will + /// loop back to TrackEntry.AnimationStart at this time. Defaults to the animation duration. + float getAnimationEnd(); + + void setAnimationEnd(float inValue); + + /// The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this + /// animation is applied, event timelines will fire all events between the animation last time (exclusive) and animation time + /// (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation is applied. + float getAnimationLast(); + + void setAnimationLast(float inValue); + + /// Uses TrackEntry.TrackTime to compute the animation time between TrackEntry.AnimationStart. and + /// TrackEntry.AnimationEnd. When the track time is 0, the animation time is equal to the animation start time. + float getAnimationTime(); + + /// Multiplier for the delta time when the animation state is updated, causing time for this animation to play slower or + /// faster. Defaults to 1. + float getTimeScale(); + + void setTimeScale(float inValue); + + /// Values less than 1 mix this animation with the last skeleton pose. Defaults to 1, which overwrites the last skeleton pose with + /// this animation. + /// + /// Typically track 0 is used to completely pose the skeleton, then alpha can be used on higher tracks. It doesn't make sense + /// to use alpha on track 0 if the skeleton pose is from the last frame render. + float getAlpha(); + + void setAlpha(float inValue); + + /// + /// When the mix percentage (mix time / mix duration) is less than the event threshold, event timelines for the animation + /// being mixed out will be applied. Defaults to 0, so event timelines are not applied for an animation being mixed out. + float getEventThreshold(); + + void setEventThreshold(float inValue); + + /// When the mix percentage (mix time / mix duration) is less than the attachment threshold, attachment timelines for the + /// animation being mixed out will be applied. Defaults to 0, so attachment timelines are not applied for an animation being + /// mixed out. + float getMixAttachmentThreshold(); + + void setMixAttachmentThreshold(float inValue); + + /// When getAlpha() is greater than alphaAttachmentThreshold, attachment timelines are applied. + /// Defaults to 0, so attachment timelines are always applied. */ + float getAlphaAttachmentThreshold(); + + void setAlphaAttachmentThreshold(float inValue); + + /// When the mix percentage (mix time / mix duration) is less than the draw order threshold, draw order timelines for the + /// animation being mixed out will be applied. Defaults to 0, so draw order timelines are not applied for an animation being + /// mixed out. + float getMixDrawOrderThreshold(); + + void setMixDrawOrderThreshold(float inValue); + + /// The animation queued to start after this animation, or NULL. + TrackEntry *getNext(); + + /// Returns true if at least one loop has been completed. + bool isComplete(); + + /// Seconds from 0 to the mix duration when mixing from the previous animation to this animation. May be slightly more than + /// TrackEntry.MixDuration when the mix is complete. + float getMixTime(); + + void setMixTime(float inValue); + + /// Seconds for mixing from the previous animation to this animation. Defaults to the value provided by + /// AnimationStateData based on the animation before this animation (if any). + /// + /// The mix duration can be set manually rather than use the value from AnimationStateData.GetMix. + /// In that case, the mixDuration must be set before AnimationState.update(float) is next called. + /// + /// When using AnimationState::addAnimation(int, Animation, bool, float) with a delay + /// less than or equal to 0, note the Delay is set using the mix duration from the AnimationStateData + float getMixDuration(); + + void setMixDuration(float inValue); + + void setMixDuration(float mixDuration, float delay); + + MixBlend getMixBlend(); + + void setMixBlend(MixBlend blend); + + /// The track entry for the previous animation when mixing from the previous animation to this animation, or NULL if no + /// mixing is currently occuring. When mixing from multiple animations, MixingFrom makes up a double linked list with MixingTo. + TrackEntry *getMixingFrom(); + + /// The track entry for the next animation when mixing from this animation, or NULL if no mixing is currently occuring. + /// When mixing from multiple animations, MixingTo makes up a double linked list with MixingFrom. + TrackEntry *getMixingTo(); + + /// Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the + /// long way around when using alpha and starting animations on other tracks. + /// + /// Mixing involves finding a rotation between two others, which has two possible solutions: the short way or the long way around. + /// The two rotations likely change over time, so which direction is the short or long way also changes. + /// If the short way was always chosen, bones would flip to the other side when that direction became the long way. + /// TrackEntry chooses the short way the first time it is applied and remembers that direction. + void resetRotationDirections(); + + float getTrackComplete(); + + void setListener(AnimationStateListener listener); + + void setListener(AnimationStateListenerObject *listener); + + /// Returns true if this track entry has been applied at least once. + /// + /// See AnimationState::apply(Skeleton). + bool wasApplied(); + + /// Returns true if there is a getNext() track entry that is ready to become the current track entry during the + /// next AnimationState::update(float)} + bool isNextReady () { + return _next != NULL && _nextTrackLast - _next->_delay >= 0; + } + + private: + Animation *_animation; + TrackEntry *_previous; + TrackEntry *_next; + TrackEntry *_mixingFrom; + TrackEntry *_mixingTo; + int _trackIndex; + + bool _loop, _holdPrevious, _reverse, _shortestRotation; + float _eventThreshold, _mixAttachmentThreshold, _alphaAttachmentThreshold, _mixDrawOrderThreshold; + float _animationStart, _animationEnd, _animationLast, _nextAnimationLast; + float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale; + float _alpha, _mixTime, _mixDuration, _interruptAlpha, _totalAlpha; + MixBlend _mixBlend; + Vector _timelineMode; + Vector _timelineHoldMix; + Vector _timelinesRotation; + AnimationStateListener _listener; + AnimationStateListenerObject *_listenerObject; + + void reset(); + }; + + class SP_API EventQueueEntry : public SpineObject { + friend class EventQueue; + + public: + EventType _type; + TrackEntry *_entry; + Event *_event; + + EventQueueEntry(EventType eventType, TrackEntry *trackEntry, Event *event = NULL); + }; + + class SP_API EventQueue : public SpineObject { + friend class AnimationState; + + private: + Vector _eventQueueEntries; + AnimationState &_state; + bool _drainDisabled; + + static EventQueue *newEventQueue(AnimationState &state); + + static EventQueueEntry newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event = NULL); + + EventQueue(AnimationState &state); + + ~EventQueue(); + + void start(TrackEntry *entry); + + void interrupt(TrackEntry *entry); + + void end(TrackEntry *entry); + + void dispose(TrackEntry *entry); + + void complete(TrackEntry *entry); + + void event(TrackEntry *entry, Event *event); + + /// Raises all events in the queue and drains the queue. + void drain(); + }; + + class SP_API AnimationState : public SpineObject, public HasRendererObject { + friend class TrackEntry; + + friend class EventQueue; + + public: + explicit AnimationState(AnimationStateData *data); + + ~AnimationState(); + + /// Increments the track entry times, setting queued animations as current if needed + /// @param delta delta time + void update(float delta); + + /// Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the + /// animation state can be applied to multiple skeletons to pose them identically. + bool apply(Skeleton &skeleton); + + /// Removes all animations from all tracks, leaving skeletons in their previous pose. + /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, + /// rather than leaving them in their previous pose. + void clearTracks(); + + /// Removes all animations from the tracks, leaving skeletons in their previous pose. + /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, + /// rather than leaving them in their previous pose. + void clearTrack(size_t trackIndex); + + /// Sets an animation by name. setAnimation(int, Animation, bool) + TrackEntry *setAnimation(size_t trackIndex, const String &animationName, bool loop); + + /// Sets the current animation for a track, discarding any queued animations. + /// @param loop If true, the animation will repeat. + /// If false, it will not, instead its last frame is applied if played beyond its duration. + /// In either case TrackEntry.TrackEnd determines when the track is cleared. + /// @return + /// A track entry to allow further customization of animation playback. References to the track entry must not be kept + /// after AnimationState.Dispose. + TrackEntry *setAnimation(size_t trackIndex, Animation *animation, bool loop); + + /// Queues an animation by name. + /// addAnimation(int, Animation, bool, float) + TrackEntry *addAnimation(size_t trackIndex, const String &animationName, bool loop, float delay); + + /// Adds an animation to be played delay seconds after the current or last queued animation + /// for a track. If the track is empty, it is equivalent to calling setAnimation. + /// @param delay + /// Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation + /// duration of the previous track minus any mix duration plus the negative delay. + /// + /// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + /// after AnimationState.Dispose + TrackEntry *addAnimation(size_t trackIndex, Animation *animation, bool loop, float delay); + + /// Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration. + TrackEntry *setEmptyAnimation(size_t trackIndex, float mixDuration); + + /// Adds an empty animation to be played after the current or last queued animation for a track, and mixes to it over the + /// specified mix duration. + /// @return + /// A track entry to allow further customization of animation playback. References to the track entry must not be kept after AnimationState.Dispose. + /// + /// @param trackIndex Track number. + /// @param mixDuration Mix duration. + /// @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation + /// duration of the previous track minus any mix duration plus the negative delay. + TrackEntry *addEmptyAnimation(size_t trackIndex, float mixDuration, float delay); + + /// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration. + void setEmptyAnimations(float mixDuration); + + /// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing. + TrackEntry *getCurrent(size_t trackIndex); + + AnimationStateData *getData(); + + /// A list of tracks that have animations, which may contain NULLs. + Vector &getTracks(); + + float getTimeScale(); + + void setTimeScale(float inValue); + + void setListener(AnimationStateListener listener); + + void setListener(AnimationStateListenerObject *listener); + + void disableQueue(); + + void enableQueue(); + + void setManualTrackEntryDisposal(bool inValue); + + bool getManualTrackEntryDisposal(); + + void disposeTrackEntry(TrackEntry *entry); + + private: + static const int Subsequent = 0; + static const int First = 1; + static const int HoldSubsequent = 2; + static const int HoldFirst = 3; + static const int HoldMix = 4; + + static const int Setup = 1; + static const int Current = 2; + + AnimationStateData *_data; + + Pool _trackEntryPool; + Vector _tracks; + Vector _events; + EventQueue *_queue; + + HashMap _propertyIDs; + bool _animationsChanged; + + AnimationStateListener _listener; + AnimationStateListenerObject *_listenerObject; + + int _unkeyedState; + + float _timeScale; + + bool _manualTrackEntryDisposal; + + static Animation *getEmptyAnimation(); + + static void + applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, MixBlend pose, + Vector &timelinesRotation, size_t i, bool firstFrame); + + void applyAttachmentTimeline(AttachmentTimeline *attachmentTimeline, Skeleton &skeleton, float animationTime, + MixBlend pose, bool firstFrame); + + /// Returns true when all mixing from entries are complete. + bool updateMixingFrom(TrackEntry *to, float delta); + + float applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBlend currentPose); + + void queueEvents(TrackEntry *entry, float animationTime); + + /// Sets the active TrackEntry for a given track number. + void setCurrent(size_t index, TrackEntry *current, bool interrupt); + + /// Removes the next entry and all entries after it for the specified entry. */ + void clearNext(TrackEntry *entry); + + TrackEntry *expandToIndex(size_t index); + + /// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values. + /// @param last May be NULL. + TrackEntry *newTrackEntry(size_t trackIndex, Animation *animation, bool loop, TrackEntry *last); + + void animationsChanged(); + + void computeHold(TrackEntry *entry); + + void setAttachment(Skeleton &skeleton, spine::Slot &slot, const String &attachmentName, bool attachments); + }; +} + +#endif /* Spine_AnimationState_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AnimationStateData.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AnimationStateData.h new file mode 100644 index 0000000..a315e76 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AnimationStateData.h @@ -0,0 +1,90 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AnimationStateData_h +#define Spine_AnimationStateData_h + +#include +#include +#include + +#include + +namespace spine { + class SkeletonData; + + class Animation; + + /// Stores mix (crossfade) durations to be applied when AnimationState animations are changed. + class SP_API AnimationStateData : public SpineObject { + friend class AnimationState; + + public: + explicit AnimationStateData(SkeletonData *skeletonData); + + /// The SkeletonData to look up animations when they are specified by name. + SkeletonData *getSkeletonData(); + + /// The mix duration to use when no mix duration has been specifically defined between two animations. + float getDefaultMix(); + + void setDefaultMix(float inValue); + + /// Sets a mix duration by animation names. + void setMix(const String &fromName, const String &toName, float duration); + + /// Sets a mix duration when changing from the specified animation to the other. + /// See TrackEntry.MixDuration. + void setMix(Animation *from, Animation *to, float duration); + + /// The mix duration to use when changing from the specified animation to the other, + /// or the DefaultMix if no mix duration has been set. + float getMix(Animation *from, Animation *to); + + /// Removes all mixes and sets the default mix to 0. + void clear(); + + private: + class AnimationPair : public SpineObject { + public: + Animation *_a1; + Animation *_a2; + + explicit AnimationPair(Animation *a1 = NULL, Animation *a2 = NULL); + + bool operator==(const AnimationPair &other) const; + }; + + SkeletonData *_skeletonData; + float _defaultMix; + HashMap _animationToMixTime; + }; +} + +#endif /* Spine_AnimationStateData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Atlas.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Atlas.h new file mode 100644 index 0000000..f6c7931 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Atlas.h @@ -0,0 +1,139 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Atlas_h +#define Spine_Atlas_h + +#include +#include +#include +#include +#include +#include "TextureRegion.h" + +namespace spine { + enum Format { + Format_Alpha, + Format_Intensity, + Format_LuminanceAlpha, + Format_RGB565, + Format_RGBA4444, + Format_RGB888, + Format_RGBA8888 + }; + + // Our TextureFilter collides with UE4's TextureFilter in unity builds. We rename + // TextureFilter to SpineTextureFilter in UE4. +#ifdef SPINE_UE4 + #define TEXTURE_FILTER_ENUM SpineTextureFilter +#else + #define TEXTURE_FILTER_ENUM TextureFilter +#endif + + enum TEXTURE_FILTER_ENUM { + TextureFilter_Unknown, + TextureFilter_Nearest, + TextureFilter_Linear, + TextureFilter_MipMap, + TextureFilter_MipMapNearestNearest, + TextureFilter_MipMapLinearNearest, + TextureFilter_MipMapNearestLinear, + TextureFilter_MipMapLinearLinear + }; + + enum TextureWrap { + TextureWrap_MirroredRepeat, + TextureWrap_ClampToEdge, + TextureWrap_Repeat + }; + + class SP_API AtlasPage : public SpineObject { + public: + String name; + String texturePath; + Format format; + TEXTURE_FILTER_ENUM minFilter; + TEXTURE_FILTER_ENUM magFilter; + TextureWrap uWrap; + TextureWrap vWrap; + int width, height; + bool pma; + int index; + void *texture; + + explicit AtlasPage(const String &inName) : name(inName), format(Format_RGBA8888), + minFilter(TextureFilter_Nearest), + magFilter(TextureFilter_Nearest), uWrap(TextureWrap_ClampToEdge), + vWrap(TextureWrap_ClampToEdge), width(0), height(0), pma(false), index(0), texture(NULL) { + } + }; + + class SP_API AtlasRegion : public TextureRegion { + public: + AtlasPage *page; + String name; + int index; + int x, y; + Vector splits; + Vector pads; + Vector names; + Vector values; + }; + + class TextureLoader; + + class SP_API Atlas : public SpineObject { + public: + Atlas(const String &path, TextureLoader *textureLoader, bool createTexture = true); + + Atlas(const char *data, int length, const char *dir, TextureLoader *textureLoader, bool createTexture = true); + + ~Atlas(); + + void flipV(); + + /// Returns the first region found with the specified name. This method uses String comparison to find the region, so the result + /// should be cached rather than calling this method multiple times. + /// @return The region, or NULL. + AtlasRegion *findRegion(const String &name); + + Vector &getPages(); + + Vector &getRegions(); + + private: + Vector _pages; + Vector _regions; + TextureLoader *_textureLoader; + + void load(const char *begin, int length, const char *dir, bool createTexture); + }; +} + +#endif /* Spine_Atlas_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h new file mode 100644 index 0000000..8511167 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AtlasAttachmentLoader_h +#define Spine_AtlasAttachmentLoader_h + +#include +#include +#include + + +namespace spine { + class Atlas; + + class AtlasRegion; + + /// An AttachmentLoader that configures attachments using texture regions from an Atlas. + /// See http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data about Loading Skeleton Data in the Spine Runtimes Guide. + class SP_API AtlasAttachmentLoader : public AttachmentLoader { + public: + RTTI_DECL + + explicit AtlasAttachmentLoader(Atlas *atlas); + + virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence); + + virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence); + + virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &skin, const String &name); + + virtual PathAttachment *newPathAttachment(Skin &skin, const String &name); + + virtual PointAttachment *newPointAttachment(Skin &skin, const String &name); + + virtual ClippingAttachment *newClippingAttachment(Skin &skin, const String &name); + + virtual void configureAttachment(Attachment *attachment); + + AtlasRegion *findRegion(const String &name); + + private: + Atlas *_atlas; + }; +} + +#endif /* Spine_AtlasAttachmentLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Attachment.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Attachment.h new file mode 100644 index 0000000..ae72b18 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Attachment.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Attachment_h +#define Spine_Attachment_h + +#include +#include +#include + +namespace spine { + class SP_API Attachment : public SpineObject { + RTTI_DECL + + public: + explicit Attachment(const String &name); + + virtual ~Attachment(); + + const String &getName() const; + + virtual Attachment *copy() = 0; + + int getRefCount(); + + void reference(); + + void dereference(); + + private: + const String _name; + int _refCount; + }; +} + +#endif /* Spine_Attachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h new file mode 100644 index 0000000..9f02302 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h @@ -0,0 +1,84 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentLoader_h +#define Spine_AttachmentLoader_h + +#include +#include +#include + +namespace spine { + class Skin; + + class Attachment; + + class RegionAttachment; + + class MeshAttachment; + + class BoundingBoxAttachment; + + class PathAttachment; + + class PointAttachment; + + class ClippingAttachment; + + class Sequence; + + class SP_API AttachmentLoader : public SpineObject { + public: + RTTI_DECL + + AttachmentLoader(); + + virtual ~AttachmentLoader(); + + /// @return May be NULL to not load any attachment. + virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) = 0; + + /// @return May be NULL to not load any attachment. + virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) = 0; + + /// @return May be NULL to not load any attachment. + virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &skin, const String &name) = 0; + + /// @return May be NULL to not load any attachment + virtual PathAttachment *newPathAttachment(Skin &skin, const String &name) = 0; + + virtual PointAttachment *newPointAttachment(Skin &skin, const String &name) = 0; + + virtual ClippingAttachment *newClippingAttachment(Skin &skin, const String &name) = 0; + + virtual void configureAttachment(Attachment *attachment) = 0; + }; +} + +#endif /* Spine_AttachmentLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h new file mode 100644 index 0000000..a42280f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentTimeline_h +#define Spine_AttachmentTimeline_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + + class Skeleton; + + class Slot; + + class Event; + + class SP_API AttachmentTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit AttachmentTimeline(size_t frameCount, int slotIndex); + + virtual ~AttachmentTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, const String &attachmentName); + + Vector &getAttachmentNames(); + + int getSlotIndex() { return _slotIndex; } + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + Vector _attachmentNames; + + void setAttachment(Skeleton &skeleton, Slot &slot, String *attachmentName); + }; +} + +#endif /* Spine_AttachmentTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AttachmentType.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AttachmentType.h new file mode 100644 index 0000000..8b1a7ed --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/AttachmentType.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentType_h +#define Spine_AttachmentType_h + +namespace spine { + enum AttachmentType { + AttachmentType_Region, + AttachmentType_Boundingbox, + AttachmentType_Mesh, + AttachmentType_Linkedmesh, + AttachmentType_Path, + AttachmentType_Point, + AttachmentType_Clipping + }; +} + +#endif /* Spine_AttachmentType_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/BlendMode.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/BlendMode.h new file mode 100644 index 0000000..f34e95b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/BlendMode.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BlendMode_h +#define Spine_BlendMode_h + +namespace spine { + enum BlendMode { + BlendMode_Normal = 0, + BlendMode_Additive, + BlendMode_Multiply, + BlendMode_Screen + }; +} + +#endif /* Spine_BlendMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/BlockAllocator.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/BlockAllocator.h new file mode 100644 index 0000000..749a69c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/BlockAllocator.h @@ -0,0 +1,114 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BlockAllocator_h +#define Spine_BlockAllocator_h + +#include +#include +#include +#include +#include + +namespace spine { + struct Block { + int size; + int allocated; + uint8_t *memory; + + int free() { + return size - allocated; + } + + bool canFit(int numBytes) { + return free() >= numBytes; + } + + uint8_t *allocate(int numBytes) { + uint8_t *ptr = memory + allocated; + allocated += numBytes; + return ptr; + } + }; + + class BlockAllocator : public SpineObject { + int initialBlockSize; + Vector blocks; + + public: + BlockAllocator(int initialBlockSize) : initialBlockSize(initialBlockSize) { + blocks.add(newBlock(initialBlockSize)); + } + + ~BlockAllocator() { + for (int i = 0, n = (int) blocks.size(); i < n; i++) { + SpineExtension::free(blocks[i].memory, __FILE__, __LINE__); + } + } + + template + T *allocate(size_t num) { + return (T *) _allocate((int) (sizeof(T) * num)); + } + + void compress() { + if (blocks.size() == 1) { + blocks[0].allocated = 0; + return; + } + int totalSize = 0; + for (int i = 0, n = (int)blocks.size(); i < n; i++) { + totalSize += blocks[i].size; + SpineExtension::free(blocks[i].memory, __FILE__, __LINE__); + } + blocks.clear(); + blocks.add(newBlock(totalSize)); + } + + private: + void *_allocate(int numBytes) { + // 16-byte align allocations + int alignedNumBytes = numBytes + (numBytes % 16 != 0 ? 16 - (numBytes % 16) : 0); + Block *block = &blocks[blocks.size() - 1]; + if (!block->canFit(alignedNumBytes)) { + blocks.add(newBlock(MathUtil::max(initialBlockSize, alignedNumBytes))); + block = &blocks[blocks.size() - 1]; + } + return block->allocate(alignedNumBytes); + } + + Block newBlock(int numBytes) { + Block block = {MathUtil::max(initialBlockSize, numBytes), 0, nullptr}; + block.memory = SpineExtension::alloc(block.size, __FILE__, __LINE__); + return block; + } + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Bone.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Bone.h new file mode 100644 index 0000000..845fc58 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Bone.h @@ -0,0 +1,286 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Bone_h +#define Spine_Bone_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class Skeleton; + +/// Stores a bone's current pose. +/// +/// A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a +/// local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a +/// constraint or application code modifies the world transform after it was computed from the local transform. + class SP_API Bone : public Updatable { + friend class AnimationState; + + friend class RotateTimeline; + + friend class IkConstraint; + + friend class TransformConstraint; + + friend class VertexAttachment; + + friend class PathConstraint; + + friend class PhysicsConstraint; + + friend class Skeleton; + + friend class RegionAttachment; + + friend class PointAttachment; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class ScaleTimeline; + + friend class ScaleXTimeline; + + friend class ScaleYTimeline; + + friend class ShearTimeline; + + friend class ShearXTimeline; + + friend class ShearYTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + friend class InheritTimeline; + + RTTI_DECL + + public: + static void setYDown(bool inValue); + + static bool isYDown(); + + /// @param parent May be NULL. + Bone(BoneData &data, Skeleton &skeleton, Bone *parent = NULL); + + /// Same as updateWorldTransform. This method exists for Bone to implement Spine::Updatable. + virtual void update(Physics physics); + + /// Computes the world transform using the parent bone and this bone's local transform. + void updateWorldTransform(); + + /// Computes the world transform using the parent bone and the specified local transform. + void + updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY); + + /// Computes the individual applied transform values from the world transform. This can be useful to perform processing using + /// the applied transform after the world transform has been modified directly (eg, by a constraint).. + /// + /// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. + void updateAppliedTransform(); + + void setToSetupPose(); + + void worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY); + + void worldToParent(float worldX, float worldY, float &outParentX, float &outParentY); + + void localToWorld(float localX, float localY, float &outWorldX, float &outWorldY); + + void parentToWorld(float worldX, float worldY, float &outX, float &outY); + + float worldToLocalRotation(float worldRotation); + + float localToWorldRotation(float localRotation); + + /// Rotates the world transform the specified amount and sets isAppliedValid to false. + /// @param degrees Degrees. + void rotateWorld(float degrees); + + float getWorldToLocalRotationX(); + + float getWorldToLocalRotationY(); + + BoneData &getData(); + + Skeleton &getSkeleton(); + + Bone *getParent(); + + Vector &getChildren(); + + /// The local X translation. + float getX(); + + void setX(float inValue); + + /// The local Y translation. + float getY(); + + void setY(float inValue); + + /// The local rotation. + float getRotation(); + + void setRotation(float inValue); + + /// The local scaleX. + float getScaleX(); + + void setScaleX(float inValue); + + /// The local scaleY. + float getScaleY(); + + void setScaleY(float inValue); + + /// The local shearX. + float getShearX(); + + void setShearX(float inValue); + + /// The local shearY. + float getShearY(); + + void setShearY(float inValue); + + /// The rotation, as calculated by any constraints. + float getAppliedRotation(); + + void setAppliedRotation(float inValue); + + /// The applied local x translation. + float getAX(); + + void setAX(float inValue); + + /// The applied local y translation. + float getAY(); + + void setAY(float inValue); + + /// The applied local scaleX. + float getAScaleX(); + + void setAScaleX(float inValue); + + /// The applied local scaleY. + float getAScaleY(); + + void setAScaleY(float inValue); + + /// The applied local shearX. + float getAShearX(); + + void setAShearX(float inValue); + + /// The applied local shearY. + float getAShearY(); + + void setAShearY(float inValue); + + float getA(); + + void setA(float inValue); + + float getB(); + + void setB(float inValue); + + float getC(); + + void setC(float inValue); + + float getD(); + + void setD(float inValue); + + float getWorldX(); + + void setWorldX(float inValue); + + float getWorldY(); + + void setWorldY(float inValue); + + float getWorldRotationX(); + + float getWorldRotationY(); + + /// Returns the magnitide (always positive) of the world scale X. + float getWorldScaleX(); + + /// Returns the magnitide (always positive) of the world scale Y. + float getWorldScaleY(); + + bool isActive(); + + void setActive(bool inValue); + + Inherit getInherit() { return _inherit; } + + void setInherit(Inherit inValue) { _inherit = inValue; } + + private: + static bool yDown; + + BoneData &_data; + Skeleton &_skeleton; + Bone *_parent; + Vector _children; + float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; + float _ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY; + float _a, _b, _worldX; + float _c, _d, _worldY; + bool _sorted; + bool _active; + Inherit _inherit; + }; +} + +#endif /* Spine_Bone_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/BoneData.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/BoneData.h new file mode 100644 index 0000000..eb53487 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -0,0 +1,150 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BoneData_h +#define Spine_BoneData_h + +#include +#include +#include +#include + +namespace spine { + class SP_API BoneData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + + friend class RotateTimeline; + + friend class ScaleTimeline; + + friend class ScaleXTimeline; + + friend class ScaleYTimeline; + + friend class ShearTimeline; + + friend class ShearXTimeline; + + friend class ShearYTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + public: + BoneData(int index, const String &name, BoneData *parent = NULL); + + /// The index of the bone in Skeleton.Bones + int getIndex(); + + /// The name of the bone, which is unique within the skeleton. + const String &getName(); + + /// May be NULL. + BoneData *getParent(); + + float getLength(); + + void setLength(float inValue); + + /// Local X translation. + float getX(); + + void setX(float inValue); + + /// Local Y translation. + float getY(); + + void setY(float inValue); + + /// Local rotation. + float getRotation(); + + void setRotation(float inValue); + + /// Local scaleX. + float getScaleX(); + + void setScaleX(float inValue); + + /// Local scaleY. + float getScaleY(); + + void setScaleY(float inValue); + + /// Local shearX. + float getShearX(); + + void setShearX(float inValue); + + /// Local shearY. + float getShearY(); + + void setShearY(float inValue); + + /// The transform mode for how parent world transforms affect this bone. + Inherit getInherit(); + + void setInherit(Inherit inValue); + + bool isSkinRequired(); + + void setSkinRequired(bool inValue); + + Color &getColor(); + + const String &getIcon(); + + void setIcon(const String &icon); + + bool isVisible(); + + void setVisible(bool inValue); + + private: + const int _index; + const String _name; + BoneData *_parent; + float _length; + float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; + Inherit _inherit; + bool _skinRequired; + Color _color; + String _icon; + bool _visible; + }; +} + +#endif /* Spine_BoneData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h new file mode 100644 index 0000000..b57d796 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BoundingBoxAttachment_h +#define Spine_BoundingBoxAttachment_h + +#include +#include +#include + +namespace spine { + /// Attachment that has a polygon for bounds checking. + class SP_API BoundingBoxAttachment : public VertexAttachment { + RTTI_DECL + + public: + explicit BoundingBoxAttachment(const String &name); + + Color &getColor(); + + virtual Attachment *copy(); + + private: + Color _color; + }; +} + +#endif /* Spine_BoundingBoxAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h new file mode 100644 index 0000000..7969ea8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ClippingAttachment_h +#define Spine_ClippingAttachment_h + +#include +#include + +namespace spine { + class SlotData; + + class SP_API ClippingAttachment : public VertexAttachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class SkeletonClipping; + + RTTI_DECL + + public: + explicit ClippingAttachment(const String &name); + + SlotData *getEndSlot(); + + void setEndSlot(SlotData *inValue); + + Color &getColor(); + + virtual Attachment *copy(); + + private: + SlotData *_endSlot; + Color _color; + }; +} + +#endif /* Spine_ClippingAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Color.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Color.h new file mode 100644 index 0000000..9a8cdeb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Color.h @@ -0,0 +1,110 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_COLOR_H +#define SPINE_COLOR_H + +#include + +namespace spine { + class SP_API Color : public SpineObject { + public: + Color() : r(0), g(0), b(0), a(0) { + } + + Color(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) { + clamp(); + } + + inline Color &set(float _r, float _g, float _b, float _a) { + this->r = _r; + this->g = _g; + this->b = _b; + this->a = _a; + clamp(); + return *this; + } + + inline Color &set(float _r, float _g, float _b) { + this->r = _r; + this->g = _g; + this->b = _b; + clamp(); + return *this; + } + + inline Color &set(const Color &other) { + r = other.r; + g = other.g; + b = other.b; + a = other.a; + clamp(); + return *this; + } + + inline Color &add(float _r, float _g, float _b, float _a) { + this->r += _r; + this->g += _g; + this->b += _b; + this->a += _a; + clamp(); + return *this; + } + + inline Color &add(float _r, float _g, float _b) { + this->r += _r; + this->g += _g; + this->b += _b; + clamp(); + return *this; + } + + inline Color &add(const Color &other) { + r += other.r; + g += other.g; + b += other.b; + a += other.a; + clamp(); + return *this; + } + + inline Color &clamp() { + r = MathUtil::clamp(this->r, 0, 1); + g = MathUtil::clamp(this->g, 0, 1); + b = MathUtil::clamp(this->b, 0, 1); + a = MathUtil::clamp(this->a, 0, 1); + return *this; + } + + float r, g, b, a; + }; +} + + +#endif //SPINE_COLOR_H diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ColorTimeline.h new file mode 100644 index 0000000..3760b1b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -0,0 +1,197 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ColorTimeline_h +#define Spine_ColorTimeline_h + +#include + +namespace spine { + class SP_API RGBATimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGBATimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, float r, float g, float b, float a); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + static const int ENTRIES = 5; + static const int R = 1; + static const int G = 2; + static const int B = 3; + static const int A = 4; + }; + + class SP_API RGBTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGBTimeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGBTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, float r, float g, float b); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + static const int ENTRIES = 4; + static const int R = 1; + static const int G = 2; + static const int B = 3; + }; + + class SP_API AlphaTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit AlphaTimeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~AlphaTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + }; + + class SP_API RGBA2Timeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGBA2Timeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGBA2Timeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + static const int ENTRIES = 8; + static const int R = 1; + static const int G = 2; + static const int B = 3; + static const int A = 4; + static const int R2 = 5; + static const int G2 = 6; + static const int B2 = 7; + }; + + class SP_API RGB2Timeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGB2Timeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGB2Timeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + static const int ENTRIES = 7; + static const int R = 1; + static const int G = 2; + static const int B = 3; + static const int R2 = 4; + static const int G2 = 5; + static const int B2 = 6; + }; +} + +#endif /* Spine_ColorTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ConstraintData.h new file mode 100644 index 0000000..ab51f32 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ConstraintData.h @@ -0,0 +1,69 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Constraint_h +#define Spine_Constraint_h + +#include +#include + +namespace spine { + /// The interface for all constraints. + class SP_API ConstraintData : public SpineObject { + + friend class SkeletonBinary; + + RTTI_DECL + + public: + ConstraintData(const String &name); + + virtual ~ConstraintData(); + + /// The IK constraint's name, which is unique within the skeleton. + const String &getName(); + + /// The ordinal for the order a skeleton's constraints will be applied. + size_t getOrder(); + + void setOrder(size_t inValue); + + /// Whether the constraint is only active for a specific skin. + bool isSkinRequired(); + + void setSkinRequired(bool inValue); + + private: + const String _name; + size_t _order; + bool _skinRequired; + }; +} + +#endif /* Spine_Constraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ContainerUtil.h new file mode 100644 index 0000000..410e2eb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ContainerUtil_h +#define Spine_ContainerUtil_h + +#include +#include +#include +#include +#include + +#include + +namespace spine { + class SP_API ContainerUtil : public SpineObject { + public: + /// Finds an item by comparing each item's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + template + static T *findWithName(Vector &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0; i < items.size(); ++i) { + T *item = items[i]; + if (item->getName() == name) { + return item; + } + } + + return NULL; + } + + /// @return -1 if the item was not found. + template + static int findIndexWithName(Vector &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0, len = items.size(); i < len; ++i) { + T *item = items[i]; + if (item->getName() == name) { + return static_cast(i); + } + } + + return -1; + } + + /// Finds an item by comparing each item's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + template + static T *findWithDataName(Vector &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0; i < items.size(); ++i) { + T *item = items[i]; + if (item->getData().getName() == name) { + return item; + } + } + + return NULL; + } + + /// @return -1 if the item was not found. + template + static int findIndexWithDataName(Vector &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0, len = items.size(); i < len; ++i) { + T *item = items[i]; + if (item->getData().getName() == name) { + return static_cast(i); + } + } + + return -1; + } + + template + static void cleanUpVectorOfPointers(Vector &items) { + for (int i = (int) items.size() - 1; i >= 0; i--) { + T *item = items[i]; + + delete item; + + items.removeAt(i); + } + } + + private: + // ctor, copy ctor, and assignment should be private in a Singleton + ContainerUtil(); + + ContainerUtil(const ContainerUtil &); + + ContainerUtil &operator=(const ContainerUtil &); + }; +} + +#endif /* Spine_ContainerUtil_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/CurveTimeline.h new file mode 100644 index 0000000..7eaac0e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_CurveTimeline_h +#define Spine_CurveTimeline_h + +#include +#include + +namespace spine { + /// Base class for frames that use an interpolation bezier curve. + class SP_API CurveTimeline : public Timeline { + RTTI_DECL + + public: + explicit CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount); + + virtual ~CurveTimeline(); + + void setLinear(size_t frame); + + void setStepped(size_t frame); + + virtual void + setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, + float cy2, float time2, float value2); + + float getBezierValue(float time, size_t frame, size_t valueOffset, size_t i); + + Vector &getCurves(); + + protected: + static const int LINEAR = 0; + static const int STEPPED = 1; + static const int BEZIER = 2; + static const int BEZIER_SIZE = 18; + + Vector _curves; // type, x, y, ... + }; + + class SP_API CurveTimeline1 : public CurveTimeline { + RTTI_DECL + + public: + explicit CurveTimeline1(size_t frameCount, size_t bezierCount); + + virtual ~CurveTimeline1(); + + void setFrame(size_t frame, float time, float value); + + float getCurveValue(float time); + + float getRelativeValue(float time, float alpha, MixBlend blend, float current, float setup); + + float getAbsoluteValue(float time, float alpha, MixBlend blend, float current, float setup); + + float getAbsoluteValue (float time, float alpha, MixBlend blend, float current, float setup, float value); + + float getScaleValue (float time, float alpha, MixBlend blend, MixDirection direction, float current, float setup); + + protected: + static const int ENTRIES = 2; + static const int VALUE = 1; + }; + + class SP_API CurveTimeline2 : public CurveTimeline { + RTTI_DECL + + public: + explicit CurveTimeline2(size_t frameCount, size_t bezierCount); + + virtual ~CurveTimeline2(); + + void setFrame(size_t frame, float time, float value1, float value2); + + float getCurveValue(float time); + + protected: + static const int ENTRIES = 3; + static const int VALUE1 = 1; + static const int VALUE2 = 2; + }; +} + +#endif /* Spine_CurveTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Debug.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Debug.h new file mode 100644 index 0000000..914afa5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Debug.h @@ -0,0 +1,139 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_LOG_H +#define SPINE_LOG_H + +#include +#include + +#include + +namespace spine { + + class SP_API DebugExtension : public SpineExtension { + struct Allocation { + void *address; + size_t size; + const char *fileName; + int line; + + Allocation() : address(NULL), size(0), fileName(NULL), line(0) { + } + + Allocation(void *a, size_t s, const char *f, int l) : address(a), size(s), fileName(f), line(l) { + } + }; + + public: + DebugExtension(SpineExtension *extension) : _extension(extension), _allocations(0), _reallocations(0), + _frees(0) { + } + + void reportLeaks() { + for (std::map::iterator it = _allocated.begin(); it != _allocated.end(); it++) { + printf("\"%s:%i (%zu bytes at %p)\n", it->second.fileName, it->second.line, it->second.size, + it->second.address); + } + printf("allocations: %zu, reallocations: %zu, frees: %zu\n", _allocations, _reallocations, _frees); + if (_allocated.empty()) printf("No leaks detected\n"); + } + + void clearAllocations() { + _allocated.clear(); + _usedMemory = 0; + } + + virtual void *_alloc(size_t size, const char *file, int line) { + void *result = _extension->_alloc(size, file, line); + _allocated[result] = Allocation(result, size, file, line); + _allocations++; + _usedMemory += size; + return result; + } + + virtual void *_calloc(size_t size, const char *file, int line) { + void *result = _extension->_calloc(size, file, line); + _allocated[result] = Allocation(result, size, file, line); + _allocations++; + _usedMemory += size; + return result; + } + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) { + if (_allocated.count(ptr)) _usedMemory -= _allocated[ptr].size; + _allocated.erase(ptr); + void *result = _extension->_realloc(ptr, size, file, line); + _reallocations++; + _allocated[result] = Allocation(result, size, file, line); + _usedMemory += size; + return result; + } + + virtual void _free(void *mem, const char *file, int line) { + if (_allocated.count(mem)) { + _extension->_free(mem, file, line); + _frees++; + _usedMemory -= _allocated[mem].size; + _allocated.erase(mem); + return; + } + + printf("%s:%i (address %p): Double free or not allocated through SpineExtension\n", file, line, mem); + _extension->_free(mem, file, line); + } + + virtual char *_readFile(const String &path, int *length) { + auto data = _extension->_readFile(path, length); + + if (_allocated.count(data) == 0) { + _allocated[data] = Allocation(data, sizeof(char) * (*length), nullptr, 0); + _allocations++; + _usedMemory += sizeof(char) * (*length); + } + + return data; + } + + size_t getUsedMemory() { + return _usedMemory; + } + + private: + SpineExtension *_extension; + std::map _allocated; + size_t _allocations; + size_t _reallocations; + size_t _frees; + size_t _usedMemory; + }; +} + + +#endif //SPINE_LOG_H diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/DeformTimeline.h new file mode 100644 index 0000000..4209d20 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -0,0 +1,80 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DeformTimeline_h +#define Spine_DeformTimeline_h + +#include + +namespace spine { + class VertexAttachment; + + class SP_API DeformTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit DeformTimeline(size_t frameCount, size_t bezierCount, int slotIndex, VertexAttachment *attachment); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, Vector &vertices); + + Vector > &getVertices(); + + VertexAttachment *getAttachment(); + + void setAttachment(VertexAttachment *inValue); + + virtual void + setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, + float cy2, float time2, float value2); + + float getCurvePercent(float time, int frame); + + int getSlotIndex() { return _slotIndex; } + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + protected: + int _slotIndex; + + Vector > _vertices; + + VertexAttachment *_attachment; + }; +} + +#endif /* Spine_DeformTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h new file mode 100644 index 0000000..7d2ab55 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DrawOrderTimeline_h +#define Spine_DrawOrderTimeline_h + +#include + +namespace spine { + class SP_API DrawOrderTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit DrawOrderTimeline(size_t frameCount); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + /// @param drawOrder May be NULL to use bind pose draw order + void setFrame(size_t frame, float time, Vector &drawOrder); + + Vector > &getDrawOrders(); + + private: + Vector > _drawOrders; + }; +} + +#endif /* Spine_DrawOrderTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Event.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Event.h new file mode 100644 index 0000000..b838a48 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Event.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Event_h +#define Spine_Event_h + +#include +#include + +namespace spine { + class EventData; + +/// Stores the current pose values for an Event. + class SP_API Event : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + + public: + Event(float time, const EventData &data); + + const EventData &getData(); + + /// The animation time this event was keyed. + float getTime(); + + int getIntValue(); + + void setIntValue(int inValue); + + float getFloatValue(); + + void setFloatValue(float inValue); + + const String &getStringValue(); + + void setStringValue(const String &inValue); + + float getVolume(); + + void setVolume(float inValue); + + float getBalance(); + + void setBalance(float inValue); + + private: + const EventData &_data; + const float _time; + int _intValue; + float _floatValue; + String _stringValue; + float _volume; + float _balance; + }; +} + +#endif /* Spine_Event_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/EventData.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/EventData.h new file mode 100644 index 0000000..fa35160 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/EventData.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_EventData_h +#define Spine_EventData_h + +#include +#include + +namespace spine { +/// Stores the setup pose values for an Event. + class SP_API EventData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class Event; + + public: + explicit EventData(const String &name); + + /// The name of the event, which is unique within the skeleton. + const String &getName() const; + + int getIntValue() const; + + void setIntValue(int inValue); + + float getFloatValue() const; + + void setFloatValue(float inValue); + + const String &getStringValue() const; + + void setStringValue(const String &inValue); + + const String &getAudioPath() const; + + void setAudioPath(const String &inValue); + + float getVolume() const; + + void setVolume(float inValue); + + float getBalance() const; + + void setBalance(float inValue); + + private: + const String _name; + int _intValue; + float _floatValue; + String _stringValue; + String _audioPath; + float _volume; + float _balance; + }; +} + +#endif /* Spine_EventData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/EventTimeline.h new file mode 100644 index 0000000..bd05a49 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_EventTimeline_h +#define Spine_EventTimeline_h + +#include + +namespace spine { + class SP_API EventTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit EventTimeline(size_t frameCount); + + ~EventTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and value of the specified keyframe. + void setFrame(size_t frame, Event *event); + + Vector &getEvents(); + + private: + Vector _events; + }; +} + +#endif /* Spine_EventTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Extension.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Extension.h new file mode 100644 index 0000000..babb397 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Extension.h @@ -0,0 +1,125 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Extension_h +#define Spine_Extension_h + + +#include +#include + +#define SP_UNUSED(x) (void)(x) + +namespace spine { + class String; + + class SP_API SpineExtension { + public: + template + static T *alloc(size_t num, const char *file, int line) { + return (T *) getInstance()->_alloc(sizeof(T) * num, file, line); + } + + template + static T *calloc(size_t num, const char *file, int line) { + return (T *) getInstance()->_calloc(sizeof(T) * num, file, line); + } + + template + static T *realloc(T *ptr, size_t num, const char *file, int line) { + return (T *) getInstance()->_realloc(ptr, sizeof(T) * num, file, line); + } + + template + static void free(T *ptr, const char *file, int line) { + getInstance()->_free((void *) ptr, file, line); + } + + template + static void beforeFree(T *ptr) { + getInstance()->_beforeFree((void *) ptr); + } + + static char *readFile(const String &path, int *length) { + return getInstance()->_readFile(path, length); + } + + static void setInstance(SpineExtension *inSpineExtension); + + static SpineExtension *getInstance(); + + virtual ~SpineExtension(); + + /// Implement this function to use your own memory allocator + virtual void *_alloc(size_t size, const char *file, int line) = 0; + + virtual void *_calloc(size_t size, const char *file, int line) = 0; + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) = 0; + + /// If you provide a spineAllocFunc, you should also provide a spineFreeFunc + virtual void _free(void *mem, const char *file, int line) = 0; + + virtual char *_readFile(const String &path, int *length) = 0; + + virtual void _beforeFree(void *ptr) { SP_UNUSED(ptr); } + + protected: + SpineExtension(); + + private: + static SpineExtension *_instance; + }; + + class SP_API DefaultSpineExtension : public SpineExtension { + public: + DefaultSpineExtension(); + + virtual ~DefaultSpineExtension(); + + protected: + virtual void *_alloc(size_t size, const char *file, int line) override; + + virtual void *_calloc(size_t size, const char *file, int line) override; + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) override; + + virtual void _free(void *mem, const char *file, int line) override; + + virtual char *_readFile(const String &path, int *length) override; + }; + +// This function is to be implemented by engine specific runtimes to provide +// the default extension for that engine. It is called the first time +// SpineExtension::getInstance() is called, when no instance has been set +// yet. + extern SpineExtension *getDefaultExtension(); +} + +#endif /* Spine_Extension_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/HasRendererObject.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/HasRendererObject.h new file mode 100644 index 0000000..db49a48 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/HasRendererObject.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_HasRendererObject_h +#define Spine_HasRendererObject_h + +#include + +namespace spine { + + typedef void (*DisposeRendererObject)(void *rendererObject); + + class SP_API HasRendererObject { + public: + explicit HasRendererObject() : _rendererObject(0), _dispose(0) {}; + + virtual ~HasRendererObject() { + if (_dispose && _rendererObject) + _dispose(_rendererObject); + } + + void *getRendererObject() { return _rendererObject; } + + void setRendererObject(void *rendererObject, DisposeRendererObject dispose = 0) { + if (_dispose && _rendererObject && _rendererObject != rendererObject) + _dispose(_rendererObject); + + _rendererObject = rendererObject; + _dispose = dispose; + } + + private: + void *_rendererObject; + DisposeRendererObject _dispose; + }; + +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/HashMap.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/HashMap.h new file mode 100755 index 0000000..45c54b8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -0,0 +1,200 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_HashMap_h +#define Spine_HashMap_h + +#include +#include + +// Required for new with line number and file name in MSVC +#ifdef _MSC_VER +#pragma warning(disable:4291) + +#pragma warning(disable:4251) + +#endif + +namespace spine { + template + class SP_API HashMap : public SpineObject { + private: + class Entry; + + public: + class SP_API Pair { + public: + explicit Pair(K &k, V &v) : key(k), value(v) {} + + K &key; + V &value; + }; + + class SP_API Entries { + public: + friend class HashMap; + + explicit Entries(Entry *entry) : _entry(NULL), _hasChecked(false) { + _start.next = entry; + _entry = &_start; + } + + Pair next() { + assert(_entry); + assert(_hasChecked); + _entry = _entry->next; + Pair pair(_entry->_key, _entry->_value); + _hasChecked = false; + return pair; + } + + bool hasNext() { + _hasChecked = true; + return _entry->next; + } + + private: + bool _hasChecked; + Entry _start; + Entry *_entry; + }; + + HashMap() : + _head(NULL), + _size(0) { + } + + ~HashMap() { + clear(); + } + + void clear() { + for (Entry *entry = _head; entry != NULL;) { + Entry *next = entry->next; + delete entry; + entry = next; + } + _head = NULL; + _size = 0; + } + + size_t size() { + return _size; + } + + void put(const K &key, const V &value) { + Entry *entry = find(key); + if (entry) { + entry->_key = key; + entry->_value = value; + } else { + entry = new(__FILE__, __LINE__) Entry(); + entry->_key = key; + entry->_value = value; + + Entry *oldHead = _head; + + if (oldHead) { + _head = entry; + oldHead->prev = entry; + entry->next = oldHead; + } else { + _head = entry; + } + _size++; + } + } + + bool addAll(Vector &keys, const V &value) { + size_t oldSize = _size; + for (size_t i = 0; i < keys.size(); i++) { + put(keys[i], value); + } + return _size != oldSize; + } + + bool containsKey(const K &key) { + return find(key) != NULL; + } + + bool remove(const K &key) { + Entry *entry = find(key); + if (!entry) return false; + + Entry *prev = entry->prev; + Entry *next = entry->next; + + if (prev) prev->next = next; + else _head = next; + if (next) next->prev = entry->prev; + + delete entry; + _size--; + + return true; + } + + V operator[](const K &key) { + Entry *entry = find(key); + if (entry) return entry->_value; + else { + assert(false); + return 0; + } + } + + Entries getEntries() const { + return Entries(_head); + } + + private: + Entry *find(const K &key) { + for (Entry *entry = _head; entry != NULL; entry = entry->next) { + if (entry->_key == key) + return entry; + } + return NULL; + } + + class SP_API Entry : public SpineObject { + public: + K _key; + V _value; + Entry *next; + Entry *prev; + + Entry() : next(NULL), prev(NULL) {} + }; + + Entry *_head; + size_t _size; + }; +} + +#endif /* Spine_HashMap_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/IkConstraint.h new file mode 100644 index 0000000..077f4f0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -0,0 +1,118 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraint_h +#define Spine_IkConstraint_h + +#include + +#include + +namespace spine { + class IkConstraintData; + + class Skeleton; + + class Bone; + + class SP_API IkConstraint : public Updatable { + friend class Skeleton; + + friend class IkConstraintTimeline; + + RTTI_DECL + + public: + /// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified + /// in the world coordinate system. + static void + apply(Bone &bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha); + + /// Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as + /// possible. The target is specified in the world coordinate system. + /// @param child A direct descendant of the parent bone. + static void + apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, bool uniform, + float softness, + float alpha); + + IkConstraint(IkConstraintData &data, Skeleton &skeleton); + + virtual void update(Physics physics); + + virtual int getOrder(); + + IkConstraintData &getData(); + + Vector &getBones(); + + Bone *getTarget(); + + void setTarget(Bone *inValue); + + int getBendDirection(); + + void setBendDirection(int inValue); + + bool getCompress(); + + void setCompress(bool inValue); + + bool getStretch(); + + void setStretch(bool inValue); + + float getMix(); + + void setMix(float inValue); + + float getSoftness(); + + void setSoftness(float inValue); + + bool isActive(); + + void setActive(bool inValue); + + void setToSetupPose(); + + private: + IkConstraintData &_data; + Vector _bones; + int _bendDirection; + bool _compress; + bool _stretch; + float _mix; + float _softness; + Bone *_target; + bool _active; + }; +} + +#endif /* Spine_IkConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/IkConstraintData.h new file mode 100644 index 0000000..2d953d4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraintData_h +#define Spine_IkConstraintData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SP_API IkConstraintData : public ConstraintData { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class IkConstraint; + + friend class Skeleton; + + friend class IkConstraintTimeline; + + public: + RTTI_DECL + + explicit IkConstraintData(const String &name); + + /// The bones that are constrained by this IK Constraint. + Vector &getBones(); + + /// The bone that is the IK target. + BoneData *getTarget(); + + void setTarget(BoneData *inValue); + + /// Controls the bend direction of the IK bones, either 1 or -1. + int getBendDirection(); + + void setBendDirection(int inValue); + + bool getCompress(); + + void setCompress(bool inValue); + + bool getStretch(); + + void setStretch(bool inValue); + + bool getUniform(); + + void setUniform(bool inValue); + + float getMix(); + + void setMix(float inValue); + + float getSoftness(); + + void setSoftness(float inValue); + + private: + Vector _bones; + BoneData *_target; + int _bendDirection; + bool _compress; + bool _stretch; + bool _uniform; + float _mix; + float _softness; + }; +} + +#endif /* Spine_IkConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h new file mode 100644 index 0000000..11dcf2e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraintTimeline_h +#define Spine_IkConstraintTimeline_h + +#include + +namespace spine { + + class SP_API IkConstraintTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit IkConstraintTimeline(size_t frameCount, size_t bezierCount, int ikConstraintIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time, mix and bend direction of the specified keyframe. + void setFrame(int frame, float time, float mix, float softness, int bendDirection, bool compress, bool stretch); + + int getIkConstraintIndex() { return _constraintIndex; } + + void setIkConstraintIndex(int inValue) { _constraintIndex = inValue; } + + private: + int _constraintIndex; + + static const int ENTRIES = 6; + static const int MIX = 1; + static const int SOFTNESS = 2; + static const int BEND_DIRECTION = 3; + static const int COMPRESS = 4; + static const int STRETCH = 5; + }; +} + +#endif /* Spine_IkConstraintTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Inherit.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Inherit.h new file mode 100644 index 0000000..fcc3a74 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Inherit.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformMode_h +#define Spine_TransformMode_h + +namespace spine { + enum Inherit { + Inherit_Normal = 0, + Inherit_OnlyTranslation, + Inherit_NoRotationOrReflection, + Inherit_NoScale, + Inherit_NoScaleOrReflection + }; +} + +#endif /* Spine_TransformMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/InheritTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/InheritTimeline.h new file mode 100644 index 0000000..6c79eed --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/InheritTimeline.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_InheritTimeline_h +#define Spine_InheritTimeline_h + +#include + +#include +#include +#include + +namespace spine { + + class SP_API InheritTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit InheritTimeline(size_t frameCount, int boneIndex); + + virtual ~InheritTimeline(); + + void setFrame(int frame, float time, Inherit inherit); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + + static const int ENTRIES = 2; + static const int INHERIT = 1; + }; +} + +#endif /* Spine_InheritTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Json.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Json.h new file mode 100644 index 0000000..03809a1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Json.h @@ -0,0 +1,116 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Json_h +#define Spine_Json_h + +#include + +#ifndef SPINE_JSON_HAVE_PREV +/* spine doesn't use the "prev" link in the Json sibling lists. */ +#define SPINE_JSON_HAVE_PREV 0 +#endif + +namespace spine { + class SP_API Json : public SpineObject { + friend class SkeletonJson; + + public: + /* Json Types: */ + static const int JSON_FALSE; + static const int JSON_TRUE; + static const int JSON_NULL; + static const int JSON_NUMBER; + static const int JSON_STRING; + static const int JSON_ARRAY; + static const int JSON_OBJECT; + + /* Get item "string" from object. Case insensitive. */ + static Json *getItem(Json *object, const char *string); + + static Json *getItem(Json *object, int childIndex); + + static const char *getString(Json *object, const char *name, const char *defaultValue); + + static float getFloat(Json *object, const char *name, float defaultValue); + + static int getInt(Json *object, const char *name, int defaultValue); + + static bool getBoolean(Json *object, const char *name, bool defaultValue); + + /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when Json_create() returns 0. 0 when Json_create() succeeds. */ + static const char *getError(); + + /* Supply a block of JSON, and this returns a Json object you can interrogate. Call Json_dispose when finished. */ + explicit Json(const char *value); + + ~Json(); + + + private: + static const char *_error; + + Json *_next; +#if SPINE_JSON_HAVE_PREV + Json* _prev; /* next/prev allow you to walk array/object chains. Alternatively, use getSize/getItem */ +#endif + Json *_child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int _type; /* The type of the item, as above. */ + int _size; /* The number of children. */ + + const char *_valueString; /* The item's string, if type==JSON_STRING */ + int _valueInt; /* The item's number, if type==JSON_NUMBER */ + float _valueFloat; /* The item's number, if type==JSON_NUMBER */ + + const char *_name; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + + /* Utility to jump whitespace and cr/lf */ + static const char *skip(const char *inValue); + + /* Parser core - when encountering text, process appropriately. */ + static const char *parseValue(Json *item, const char *value); + + /* Parse the input text into an unescaped cstring, and populate item. */ + static const char *parseString(Json *item, const char *str); + + /* Parse the input text to generate a number, and populate the result into item. */ + static const char *parseNumber(Json *item, const char *num); + + /* Build an array from input text. */ + static const char *parseArray(Json *item, const char *value); + + /* Build an object from the text. */ + static const char *parseObject(Json *item, const char *value); + + static int json_strcasecmp(const char *s1, const char *s2); + }; +} + +#endif /* Spine_Json_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/LinkedMesh.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/LinkedMesh.h new file mode 100644 index 0000000..bd71970 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/LinkedMesh.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_LinkedMesh_h +#define Spine_LinkedMesh_h + +#include +#include + +namespace spine { + class MeshAttachment; + + class SP_API LinkedMesh : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + public: + LinkedMesh(MeshAttachment *mesh, const int skinIndex, size_t slotIndex, const String &parent, + bool inheritTimeline); + + LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, + bool inheritTimeline); + + private: + MeshAttachment *_mesh; + int _skinIndex; + String _skin; + size_t _slotIndex; + String _parent; + bool _inheritTimeline; + }; +} + +#endif /* Spine_LinkedMesh_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Log.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Log.h new file mode 100644 index 0000000..ce66f44 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Log.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_DEBUG_LOG_H +#define SPINE_DEBUG_LOG_H + +#include + +namespace spine { + SP_API void spDebug_printSkeletonData(SkeletonData *skeletonData); + + SP_API void spDebug_printAnimation(Animation *animation); + + SP_API void spDebug_printTimeline(Timeline *timeline); + + SP_API void spDebug_printBoneDatas(Vector &boneDatas); + + SP_API void spDebug_printBoneData(BoneData *boneData); + + SP_API void spDebug_printSkeleton(Skeleton *skeleton); + + SP_API void spDebug_printBones(Vector &bones); + + SP_API void spDebug_printBone(Bone *bone); + + SP_API void spDebug_printFloats(float *values, int numFloats); + + SP_API void spDebug_printFloats(Vector &values); +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/MathUtil.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/MathUtil.h new file mode 100644 index 0000000..fb6d24b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -0,0 +1,139 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MathUtil_h +#define Spine_MathUtil_h + +#include + +#include +// Needed for older MSVC versions +#undef min +#undef max + +namespace spine { + + class SP_API MathUtil : public SpineObject { + private: + MathUtil(); + + public: + static const float Pi; + static const float Pi_2; + static const float InvPi_2; + static const float Deg_Rad; + static const float Rad_Deg; + + template + static inline T min(T a, T b) { return a < b ? a : b; } + + template + static inline T max(T a, T b) { return a > b ? a : b; } + + static float sign(float val); + + static float clamp(float x, float lower, float upper); + + static float abs(float v); + + /// Returns the sine in radians from a lookup table. + static float sin(float radians); + + /// Returns the cosine in radians from a lookup table. + static float cos(float radians); + + /// Returns the sine in radians from a lookup table. + static float sinDeg(float degrees); + + /// Returns the cosine in radians from a lookup table. + static float cosDeg(float degrees); + + /// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 + /// degrees), largest error of 0.00488 radians (0.2796 degrees). + static float atan2(float y, float x); + + static float atan2Deg(float x, float y); + + static float acos(float v); + + static float sqrt(float v); + + static float fmod(float a, float b); + + static bool isNan(float v); + + static float quietNan(); + + static float random(); + + static float randomTriangular(float min, float max); + + static float randomTriangular(float min, float max, float mode); + + static float pow(float a, float b); + + static float ceil(float v); + }; + + struct SP_API Interpolation { + virtual float apply(float a) = 0; + + virtual float interpolate(float start, float end, float a) { + return start + (end - start) * apply(a); + } + + virtual ~Interpolation() {}; + }; + + struct SP_API PowInterpolation : public Interpolation { + PowInterpolation(int power) : power(power) { + } + + float apply(float a) { + if (a <= 0.5f) return MathUtil::pow(a * 2.0f, (float) power) / 2.0f; + return MathUtil::pow((a - 1.0f) * 2.0f, (float) power) / (power % 2 == 0 ? -2.0f : 2.0f) + 1.0f; + } + + int power; + }; + + struct SP_API PowOutInterpolation : public Interpolation { + PowOutInterpolation(int power) : power(power) { + } + + float apply(float a) { + return MathUtil::pow(a - 1, (float) power) * (power % 2 == 0 ? -1.0f : 1.0f) + 1.0f; + } + + int power; + }; + +} + +#endif /* Spine_MathUtil_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/MeshAttachment.h new file mode 100644 index 0000000..a553766 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MeshAttachment_h +#define Spine_MeshAttachment_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + /// Attachment that displays a texture region using a mesh. + class SP_API MeshAttachment : public VertexAttachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AtlasAttachmentLoader; + + RTTI_DECL + + public: + explicit MeshAttachment(const String &name); + + virtual ~MeshAttachment(); + + using VertexAttachment::computeWorldVertices; + + virtual void computeWorldVertices(Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride = 2); + + void updateRegion(); + + int getHullLength(); + + void setHullLength(int inValue); + + Vector &getRegionUVs(); + + /// The UV pair for each vertex, normalized within the entire texture. See also MeshAttachment::updateRegion + Vector &getUVs(); + + Vector &getTriangles(); + + Color &getColor(); + + const String &getPath(); + + void setPath(const String &inValue); + + TextureRegion *getRegion(); + + void setRegion(TextureRegion *region); + + Sequence *getSequence(); + + void setSequence(Sequence *sequence); + + MeshAttachment *getParentMesh(); + + void setParentMesh(MeshAttachment *inValue); + + // Nonessential. + Vector &getEdges(); + + float getWidth(); + + void setWidth(float inValue); + + float getHeight(); + + void setHeight(float inValue); + + virtual Attachment *copy(); + + MeshAttachment *newLinkedMesh(); + + private: + MeshAttachment *_parentMesh; + Vector _uvs; + Vector _regionUVs; + Vector _triangles; + Vector _edges; + String _path; + Color _color; + int _hullLength; + int _width, _height; + TextureRegion *_region; + Sequence *_sequence; + }; +} + +#endif /* Spine_MeshAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/MixBlend.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/MixBlend.h new file mode 100644 index 0000000..3aa0faf --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/MixBlend.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MixPose_h +#define Spine_MixPose_h + +namespace spine { + +/// Controls how a timeline is mixed with the setup or current pose. +/// See also Timeline::apply(Skeleton&, float, float, Vector&, float, Blend, MixDirection) + enum MixBlend { + MixBlend_Setup = 0, + MixBlend_First, + MixBlend_Replace, + MixBlend_Add + }; +} + +#endif /* Spine_MixPose_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/MixDirection.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/MixDirection.h new file mode 100644 index 0000000..dbb1287 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/MixDirection.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MixDirection_h +#define Spine_MixDirection_h + +namespace spine { + +/// Indicates whether a timeline's alpha is mixing out over time toward 0 (the setup or current pose) or mixing in toward 1 (the timeline's pose). +/// See also Timeline::apply(Skeleton&, float, float, Vector&, float, MixPose, MixDirection) + enum MixDirection { + MixDirection_In = 0, + MixDirection_Out + }; + +} + +#endif /* Spine_MixDirection_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathAttachment.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathAttachment.h new file mode 100644 index 0000000..e137849 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathAttachment.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathAttachment_h +#define Spine_PathAttachment_h + +#include +#include + +namespace spine { + class SP_API PathAttachment : public VertexAttachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathAttachment(const String &name); + + /// The length in the setup pose from the start of the path to the end of each curve. + Vector &getLengths(); + + bool isClosed(); + + void setClosed(bool inValue); + + bool isConstantSpeed(); + + void setConstantSpeed(bool inValue); + + Color &getColor(); + + virtual Attachment *copy(); + + private: + Vector _lengths; + bool _closed; + bool _constantSpeed; + Color _color; + }; +} + +#endif /* Spine_PathAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraint.h new file mode 100644 index 0000000..924b354 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraint_h +#define Spine_PathConstraint_h + +#include + +#include + +namespace spine { + class PathConstraintData; + + class Skeleton; + + class PathAttachment; + + class Bone; + + class Slot; + + class SP_API PathConstraint : public Updatable { + friend class Skeleton; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + RTTI_DECL + + public: + PathConstraint(PathConstraintData &data, Skeleton &skeleton); + + virtual void update(Physics physics); + + virtual int getOrder(); + + PathConstraintData &getData(); + + Vector &getBones(); + + Slot *getTarget(); + + void setTarget(Slot *inValue); + + float getPosition(); + + void setPosition(float inValue); + + float getSpacing(); + + void setSpacing(float inValue); + + float getMixRotate(); + + void setMixRotate(float inValue); + + float getMixX(); + + void setMixX(float inValue); + + float getMixY(); + + void setMixY(float inValue); + + bool isActive(); + + void setActive(bool inValue); + + void setToSetupPose(); + + private: + static const float EPSILON; + static const int NONE; + static const int BEFORE; + static const int AFTER; + + PathConstraintData &_data; + Vector _bones; + Slot *_target; + float _position, _spacing; + float _mixRotate, _mixX, _mixY; + + Vector _spaces; + Vector _positions; + Vector _world; + Vector _curves; + Vector _lengths; + Vector _segments; + + bool _active; + + Vector &computeWorldPositions(PathAttachment &path, int spacesCount, bool tangents); + + static void addBeforePosition(float p, Vector &temp, int i, Vector &output, int o); + + static void addAfterPosition(float p, Vector &temp, int i, Vector &output, int o); + + static void + addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, + Vector &output, int o, bool tangents); + }; +} + +#endif /* Spine_PathConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraintData.h new file mode 100644 index 0000000..b018ad3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -0,0 +1,119 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintData_h +#define Spine_PathConstraintData_h + +#include +#include +#include +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SlotData; + + class SP_API PathConstraintData : public ConstraintData { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class PathConstraint; + + friend class Skeleton; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + public: + RTTI_DECL + + explicit PathConstraintData(const String &name); + + Vector &getBones(); + + SlotData *getTarget(); + + void setTarget(SlotData *inValue); + + PositionMode getPositionMode(); + + void setPositionMode(PositionMode inValue); + + SpacingMode getSpacingMode(); + + void setSpacingMode(SpacingMode inValue); + + RotateMode getRotateMode(); + + void setRotateMode(RotateMode inValue); + + float getOffsetRotation(); + + void setOffsetRotation(float inValue); + + float getPosition(); + + void setPosition(float inValue); + + float getSpacing(); + + void setSpacing(float inValue); + + float getMixRotate(); + + void setMixRotate(float inValue); + + float getMixX(); + + void setMixX(float inValue); + + float getMixY(); + + void setMixY(float inValue); + + private: + Vector _bones; + SlotData *_target; + PositionMode _positionMode; + SpacingMode _spacingMode; + RotateMode _rotateMode; + float _offsetRotation; + float _position, _spacing; + float _mixRotate, _mixX, _mixY; + }; +} + +#endif /* Spine_PathConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h new file mode 100644 index 0000000..72c189b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintMixTimeline_h +#define Spine_PathConstraintMixTimeline_h + +#include + +namespace spine { + + class SP_API PathConstraintMixTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathConstraintMixTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + /// Sets the time and mixes of the specified keyframe. + void setFrame(int frameIndex, float time, float mixRotate, float mixX, float mixY); + + int getPathConstraintIndex() { return _constraintIndex; } + + void setPathConstraintIndex(int inValue) { _constraintIndex = inValue; } + + private: + int _constraintIndex; + + static const int ENTRIES = 4; + static const int ROTATE = 1; + static const int X = 2; + static const int Y = 3; + }; +} + +#endif /* Spine_PathConstraintMixTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h new file mode 100644 index 0000000..73e4842 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintPositionTimeline_h +#define Spine_PathConstraintPositionTimeline_h + +#include + +namespace spine { + + class SP_API PathConstraintPositionTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + static const int ENTRIES; + + explicit PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex); + + virtual ~PathConstraintPositionTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getPathConstraintIndex() { return _constraintIndex; } + + void setPathConstraintIndex(int inValue) { _constraintIndex = inValue; } + + protected: + int _constraintIndex; + }; +} + +#endif /* Spine_PathConstraintPositionTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h new file mode 100644 index 0000000..6d7bee3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintSpacingTimeline_h +#define Spine_PathConstraintSpacingTimeline_h + +#include + +namespace spine { + class SP_API PathConstraintSpacingTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathConstraintSpacingTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getPathConstraintIndex() { return _pathConstraintIndex; } + + void setPathConstraintIndex(int inValue) { _pathConstraintIndex = inValue; } + + protected: + int _pathConstraintIndex; + }; +} + +#endif /* Spine_PathConstraintSpacingTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Physics.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Physics.h new file mode 100644 index 0000000..e7b9f7a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Physics.h @@ -0,0 +1,50 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Physics_h +#define Spine_Physics_h + +/** Determines how physics and other non-deterministic updates are applied. */ +namespace spine { + enum Physics { + /** Physics are not updated or applied. */ + Physics_None, + + /** Physics are reset to the current pose. */ + Physics_Reset, + + /** Physics are updated and the pose from physics is applied. */ + Physics_Update, + + /** Physics are not updated but the pose from physics is applied. */ + Physics_Pose + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PhysicsConstraint.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PhysicsConstraint.h new file mode 100644 index 0000000..b63060e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PhysicsConstraint.h @@ -0,0 +1,197 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PhysicsConstraint_h +#define Spine_PhysicsConstraint_h + +#include + +#include + +namespace spine { + class PhysicsConstraintData; + + class Skeleton; + + class Bone; + + class SP_API PhysicsConstraint : public Updatable { + + friend class Skeleton; + + friend class PhysicsConstraintTimeline; + + friend class PhysicsConstraintInertiaTimeline; + + friend class PhysicsConstraintStrengthTimeline; + + friend class PhysicsConstraintDampingTimeline; + + friend class PhysicsConstraintMassTimeline; + + friend class PhysicsConstraintWindTimeline; + + friend class PhysicsConstraintGravityTimeline; + + friend class PhysicsConstraintMixTimeline; + + friend class PhysicsConstraintResetTimeline; + + RTTI_DECL + + public: + PhysicsConstraint(PhysicsConstraintData& data, Skeleton& skeleton); + + PhysicsConstraintData &getData(); + + void setBone(Bone* bone); + Bone* getBone(); + + void setInertia(float value); + float getInertia(); + + void setStrength(float value); + float getStrength(); + + void setDamping(float value); + float getDamping(); + + void setMassInverse(float value); + float getMassInverse(); + + void setWind(float value); + float getWind(); + + void setGravity(float value); + float getGravity(); + + void setMix(float value); + float getMix(); + + void setReset(bool value); + bool getReset(); + + void setUx(float value); + float getUx(); + + void setUy(float value); + float getUy(); + + void setCx(float value); + float getCx(); + + void setCy(float value); + float getCy(); + + void setTx(float value); + float getTx(); + + void setTy(float value); + float getTy(); + + void setXOffset(float value); + float getXOffset(); + + void setXVelocity(float value); + float getXVelocity(); + + void setYOffset(float value); + float getYOffset(); + + void setYVelocity(float value); + float getYVelocity(); + + void setRotateOffset(float value); + float getRotateOffset(); + + void setRotateVelocity(float value); + float getRotateVelocity(); + + void setScaleOffset(float value); + float getScaleOffset(); + + void setScaleVelocity(float value); + float getScaleVelocity(); + + void setActive(bool value); + bool isActive(); + + void setRemaining(float value); + float getRemaining(); + + void setLastTime(float value); + float getLastTime(); + + void reset(); + + void setToSetupPose(); + + virtual void update(Physics physics); + + void translate(float x, float y); + + void rotate(float x, float y, float degrees); + + private: + PhysicsConstraintData& _data; + Bone* _bone; + + float _inertia; + float _strength; + float _damping; + float _massInverse; + float _wind; + float _gravity; + float _mix; + + bool _reset; + float _ux; + float _uy; + float _cx; + float _cy; + float _tx; + float _ty; + float _xOffset; + float _xVelocity; + float _yOffset; + float _yVelocity; + float _rotateOffset; + float _rotateVelocity; + float _scaleOffset; + float _scaleVelocity; + + bool _active; + + Skeleton& _skeleton; + float _remaining; + float _lastTime; + }; +} + +#endif /* Spine_PhysicsConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h new file mode 100644 index 0000000..32aa3cc --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h @@ -0,0 +1,151 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PhysicsConstraintData_h +#define Spine_PhysicsConstraintData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SP_API PhysicsConstraintData : public ConstraintData { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class Skeleton; + + friend class PhysicsConstraint; + + public: + RTTI_DECL + + explicit PhysicsConstraintData(const String &name); + + void setBone(BoneData* bone); + + BoneData* getBone() const; + + void setX(float x); + + float getX() const; + + void setY(float y); + + float getY() const; + + void setRotate(float rotate); + + float getRotate() const; + + void setScaleX(float scaleX); + + float getScaleX() const; + + void setShearX(float shearX); + + float getShearX() const; + + void setLimit(float limit); + + float getLimit() const; + + void setStep(float step); + + float getStep() const; + + void setInertia(float inertia); + + float getInertia() const; + + void setStrength(float strength); + + float getStrength() const; + + void setDamping(float damping); + + float getDamping() const; + + void setMassInverse(float massInverse); + + float getMassInverse() const; + + void setWind(float wind); + + float getWind() const; + + void setGravity(float gravity); + + float getGravity() const; + + void setMix(float mix); + + float getMix() const; + + void setInertiaGlobal(bool inertiaGlobal); + + bool isInertiaGlobal() const; + + void setStrengthGlobal(bool strengthGlobal); + + bool isStrengthGlobal() const; + + void setDampingGlobal(bool dampingGlobal); + + bool isDampingGlobal() const; + + void setMassGlobal(bool massGlobal); + + bool isMassGlobal() const; + + void setWindGlobal(bool windGlobal); + + bool isWindGlobal() const; + + void setGravityGlobal(bool gravityGlobal); + + bool isGravityGlobal() const; + + void setMixGlobal(bool mixGlobal); + + bool isMixGlobal() const; + + private: + BoneData *_bone; + float _x, _y, _rotate, _scaleX, _shearX, _limit; + float _step, _inertia, _strength, _damping, _massInverse, _wind, _gravity, _mix; + bool _inertiaGlobal, _strengthGlobal, _dampingGlobal, _massGlobal, _windGlobal, _gravityGlobal, _mixGlobal; + }; +} + +#endif /* Spine_PhysicsConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PhysicsConstraintTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PhysicsConstraintTimeline.h new file mode 100644 index 0000000..e119378 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PhysicsConstraintTimeline.h @@ -0,0 +1,288 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PhysicsConstraintTimeline_h +#define Spine_PhysicsConstraintTimeline_h + +#include +#include +#include + +namespace spine { + + class SP_API PhysicsConstraintTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex, Property property); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getPhysicsConstraintIndex() { return _constraintIndex; } + + void setPhysicsConstraintIndex(int inValue) { _constraintIndex = inValue; } + + protected: + virtual float setup(PhysicsConstraint *constraint) = 0; + virtual float get(PhysicsConstraint *constraint) = 0; + virtual void set(PhysicsConstraint *constraint, float value) = 0; + virtual bool global(PhysicsConstraintData &constraintData) = 0; + + private: + int _constraintIndex; + }; + + class SP_API PhysicsConstraintInertiaTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintInertiaTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex): PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintInertia) {}; + + protected: + float setup(PhysicsConstraint *constraint) { + return constraint->_data.getInertia(); + } + + float get(PhysicsConstraint *constraint) { + return constraint->_inertia; + } + + void set(PhysicsConstraint *constraint, float value) { + constraint->_inertia = value; + } + + bool global(PhysicsConstraintData &constraintData) { + return constraintData.isInertiaGlobal(); + } + }; + + class SP_API PhysicsConstraintStrengthTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintStrengthTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex): PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintStrength) {}; + + protected: + float setup(PhysicsConstraint *constraint) { + return constraint->_data.getStrength(); + } + + float get(PhysicsConstraint *constraint) { + return constraint->_strength; + } + + void set(PhysicsConstraint *constraint, float value) { + constraint->_strength = value; + } + + bool global(PhysicsConstraintData &constraintData) { + return constraintData.isStrengthGlobal(); + } + }; + + class SP_API PhysicsConstraintDampingTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintDampingTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex): PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintDamping) {}; + + protected: + float setup(PhysicsConstraint *constraint) { + return constraint->_data.getDamping(); + } + + float get(PhysicsConstraint *constraint) { + return constraint->_damping; + } + + void set(PhysicsConstraint *constraint, float value) { + constraint->_damping = value; + } + + bool global(PhysicsConstraintData &constraintData) { + return constraintData.isDampingGlobal(); + } + }; + + class SP_API PhysicsConstraintMassTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintMassTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex): PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintMass) {}; + + protected: + float setup(PhysicsConstraint *constraint) { + return 1 / constraint->_data.getMassInverse(); + } + + float get(PhysicsConstraint *constraint) { + return 1 / constraint->_massInverse; + } + + void set(PhysicsConstraint *constraint, float value) { + constraint->_massInverse = 1 / value; + } + + bool global(PhysicsConstraintData &constraintData) { + return constraintData.isMassGlobal(); + } + }; + + class SP_API PhysicsConstraintWindTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintWindTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex): PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintWind) {}; + + protected: + float setup(PhysicsConstraint *constraint) { + return constraint->_data.getWind(); + } + + float get(PhysicsConstraint *constraint) { + return constraint->_wind; + } + + void set(PhysicsConstraint *constraint, float value) { + constraint->_wind = value; + } + + bool global(PhysicsConstraintData &constraintData) { + return constraintData.isWindGlobal(); + } + }; + + class SP_API PhysicsConstraintGravityTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintGravityTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex): PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintGravity) {}; + + protected: + float setup(PhysicsConstraint *constraint) { + return constraint->_data.getGravity(); + } + + float get(PhysicsConstraint *constraint) { + return constraint->_gravity; + } + + void set(PhysicsConstraint *constraint, float value) { + constraint->_gravity = value; + } + + bool global(PhysicsConstraintData &constraintData) { + return constraintData.isGravityGlobal(); + } + }; + + class SP_API PhysicsConstraintMixTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintMixTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex): PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintMix) {}; + + protected: + float setup(PhysicsConstraint *constraint) { + return constraint->_data.getMix(); + } + + float get(PhysicsConstraint *constraint) { + return constraint->_mix; + } + + void set(PhysicsConstraint *constraint, float value) { + constraint->_mix = value; + } + + bool global(PhysicsConstraintData &constraintData) { + return constraintData.isMixGlobal(); + } + }; + + class SP_API PhysicsConstraintResetTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintResetTimeline(size_t frameCount, int physicsConstraintIndex): Timeline(frameCount, 1), _constraintIndex(physicsConstraintIndex) { + PropertyId ids[] = {((PropertyId)Property_PhysicsConstraintReset) << 32}; + setPropertyIds(ids, 1); + } + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + void setFrame(int frame, float time) { + _frames[frame] = time; + } + private: + int _constraintIndex; + }; +} + +#endif /* Spine_PhysicsConstraintTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PointAttachment.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PointAttachment.h new file mode 100644 index 0000000..45f47cf --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PointAttachment.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PointAttachment_h +#define Spine_PointAttachment_h + +#include +#include + +namespace spine { + class Bone; + + /// An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be + /// used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a + /// skin. + /// + /// See http://esotericsoftware.com/spine-point-attachments for Point Attachments in the Spine User Guide. + /// + class SP_API PointAttachment : public Attachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PointAttachment(const String &name); + + void computeWorldPosition(Bone &bone, float &ox, float &oy); + + float computeWorldRotation(Bone &bone); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getRotation(); + + void setRotation(float inValue); + + Color &getColor(); + + virtual Attachment *copy(); + + private: + float _x, _y, _rotation; + Color _color; + }; +} + +#endif /* Spine_PointAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Pool.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Pool.h new file mode 100644 index 0000000..2f2b43a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Pool.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Pool_h +#define Spine_Pool_h + +#include +#include +#include +#include + +namespace spine { + template + class SP_API Pool : public SpineObject { + public: + Pool() { + } + + ~Pool() { + ContainerUtil::cleanUpVectorOfPointers(_objects); + } + + T *obtain() { + if (_objects.size() > 0) { + T **object = &_objects[_objects.size() - 1]; + T *ret = *object; + _objects.removeAt(_objects.size() - 1); + + return ret; + } else { + T *ret = new(__FILE__, __LINE__) T(); + + return ret; + } + } + + void free(T *object) { + if (!_objects.contains(object)) { + _objects.add(object); + } + } + + private: + Vector _objects; + }; +} + +#endif /* Spine_Pool_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PositionMode.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PositionMode.h new file mode 100644 index 0000000..ee5b4b0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/PositionMode.h @@ -0,0 +1,40 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PositionMode_h +#define Spine_PositionMode_h + +namespace spine { + enum PositionMode { + PositionMode_Fixed = 0, + PositionMode_Percent + }; +} + +#endif /* Spine_PositionMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Property.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Property.h new file mode 100644 index 0000000..69fa24f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Property.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Property_h +#define Spine_Property_h + +namespace spine { + typedef long long PropertyId; + enum Property { + Property_Rotate = 1 << 0, + Property_X = 1 << 1, + Property_Y = 1 << 2, + Property_ScaleX = 1 << 3, + Property_ScaleY = 1 << 4, + Property_ShearX = 1 << 5, + Property_ShearY = 1 << 6, + Property_Inherit = 1 << 7, + Property_Rgb = 1 << 8, + Property_Alpha = 1 << 9, + Property_Rgb2 = 1 << 10, + Property_Attachment = 1 << 11, + Property_Deform = 1 << 12, + Property_Event = 1 << 13, + Property_DrawOrder = 1 << 14, + Property_IkConstraint = 1 << 15, + Property_TransformConstraint = 1 << 16, + Property_PathConstraintPosition = 1 << 17, + Property_PathConstraintSpacing = 1 << 18, + Property_PathConstraintMix = 1 << 19, + Property_PhysicsConstraintInertia = 1 << 20, + Property_PhysicsConstraintStrength = 1 << 21, + Property_PhysicsConstraintDamping = 1 << 22, + Property_PhysicsConstraintMass = 1 << 23, + Property_PhysicsConstraintWind = 1 << 24, + Property_PhysicsConstraintGravity = 1 << 25, + Property_PhysicsConstraintMix = 1 << 26, + Property_PhysicsConstraintReset = 1 << 27, + Property_Sequence = 1 << 28 + }; +} + +#endif /* Spine_Property_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/RTTI.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/RTTI.h new file mode 100644 index 0000000..18d6371 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/RTTI.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RTTI_h +#define Spine_RTTI_h + +#include + +namespace spine { + class SP_API RTTI { + public: + explicit RTTI(const char *className); + + RTTI(const char *className, const RTTI &baseRTTI); + + const char *getClassName() const; + + bool isExactly(const RTTI &rtti) const; + + bool instanceOf(const RTTI &rtti) const; + + private: + // Prevent copying + RTTI(const RTTI &obj); + + RTTI &operator=(const RTTI &obj); + + const char *_className; + const RTTI *_pBaseRTTI; + }; +} + +#define RTTI_DECL \ +public: \ +static const spine::RTTI rtti; \ +virtual const spine::RTTI& getRTTI() const; + +#define RTTI_IMPL_NOPARENT(name) \ +const spine::RTTI name::rtti(#name); \ +const spine::RTTI& name::getRTTI() const { return rtti; } + +#define RTTI_IMPL(name, parent) \ +const spine::RTTI name::rtti(#name, parent::rtti); \ +const spine::RTTI& name::getRTTI() const { return rtti; } + +#endif /* Spine_RTTI_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/RegionAttachment.h new file mode 100644 index 0000000..3d28885 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -0,0 +1,140 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RegionAttachment_h +#define Spine_RegionAttachment_h + +#include +#include +#include +#include +#include + +#include + +#define NUM_UVS 8 + +namespace spine { + class Bone; + + /// Attachment that displays a texture region. + class SP_API RegionAttachment : public Attachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AtlasAttachmentLoader; + + RTTI_DECL + + public: + explicit RegionAttachment(const String &name); + + virtual ~RegionAttachment(); + + void updateRegion(); + + /// Transforms the attachment's four vertices to world coordinates. + /// @param slot The parent slot. + /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8. + /// @param offset The worldVertices index to begin writing values. + /// @param stride The number of worldVertices entries between the value pairs written. + void computeWorldVertices(Slot &slot, float *worldVertices, size_t offset, size_t stride = 2); + + void computeWorldVertices(Slot &slot, Vector &worldVertices, size_t offset, size_t stride = 2); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getRotation(); + + void setRotation(float inValue); + + float getScaleX(); + + void setScaleX(float inValue); + + float getScaleY(); + + void setScaleY(float inValue); + + float getWidth(); + + void setWidth(float inValue); + + float getHeight(); + + void setHeight(float inValue); + + Color &getColor(); + + const String &getPath(); + + void setPath(const String &inValue); + + TextureRegion *getRegion(); + + void setRegion(TextureRegion *region); + + Sequence *getSequence(); + + void setSequence(Sequence *sequence); + + Vector &getOffset(); + + Vector &getUVs(); + + virtual Attachment *copy(); + + private: + static const int BLX; + static const int BLY; + static const int ULX; + static const int ULY; + static const int URX; + static const int URY; + static const int BRX; + static const int BRY; + + float _x, _y, _rotation, _scaleX, _scaleY, _width, _height; + Vector _vertexOffset; + Vector _uvs; + String _path; + Color _color; + TextureRegion *_region; + Sequence *_sequence; + }; +} + +#endif /* Spine_RegionAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/RotateMode.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/RotateMode.h new file mode 100644 index 0000000..fd3e373 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/RotateMode.h @@ -0,0 +1,41 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RotateMode_h +#define Spine_RotateMode_h + +namespace spine { + enum RotateMode { + RotateMode_Tangent = 0, + RotateMode_Chain, + RotateMode_ChainScale + }; +} + +#endif /* Spine_RotateMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/RotateTimeline.h new file mode 100644 index 0000000..89b8621 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RotateTimeline_h +#define Spine_RotateTimeline_h + +#include + +namespace spine { + class SP_API RotateTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + + RTTI_DECL + + public: + explicit RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; +} + +#endif /* Spine_RotateTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h new file mode 100644 index 0000000..ef9f3ac --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -0,0 +1,109 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ScaleTimeline_h +#define Spine_ScaleTimeline_h + +#include + +namespace spine { + class SP_API ScaleTimeline : public CurveTimeline2 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ScaleTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API ScaleXTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ScaleXTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API ScaleYTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ScaleYTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; +} + +#endif /* Spine_ScaleTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Sequence.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Sequence.h new file mode 100644 index 0000000..8bf0fd7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Sequence.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Sequence_h +#define Spine_Sequence_h + +#include +#include +#include + +namespace spine { + class Slot; + + class Attachment; + + class SkeletonBinary; + class SkeletonJson; + + class SP_API Sequence : public SpineObject { + friend class SkeletonBinary; + friend class SkeletonJson; + public: + Sequence(int count); + + ~Sequence(); + + Sequence *copy(); + + void apply(Slot *slot, Attachment *attachment); + + String getPath(const String &basePath, int index); + + int getId() { return _id; } + + void setId(int id) { _id = id; } + + int getStart() { return _start; } + + void setStart(int start) { _start = start; } + + int getDigits() { return _digits; } + + void setDigits(int digits) { _digits = digits; } + + int getSetupIndex() { return _setupIndex; } + + void setSetupIndex(int setupIndex) { _setupIndex = setupIndex; } + + Vector &getRegions() { return _regions; } + + private: + int _id; + Vector _regions; + int _start; + int _digits; + int _setupIndex; + + int getNextID(); + }; + + enum SequenceMode { + hold = 0, + once = 1, + loop = 2, + pingpong = 3, + onceReverse = 4, + loopReverse = 5, + pingpongReverse = 6 + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SequenceTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SequenceTimeline.h new file mode 100644 index 0000000..7dd2ae3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SequenceTimeline.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SequenceTimeline_h +#define Spine_SequenceTimeline_h + +#include +#include + +namespace spine { + class Attachment; + + class SP_API SequenceTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit SequenceTimeline(size_t frameCount, int slotIndex, spine::Attachment *attachment); + + virtual ~SequenceTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + void setFrame(int frame, float time, SequenceMode mode, int index, float delay); + + int getSlotIndex() { return _slotIndex; }; + + void setSlotIndex(int inValue) { _slotIndex = inValue; } + + Attachment *getAttachment() { return _attachment; } + + protected: + int _slotIndex; + Attachment *_attachment; + + static const int ENTRIES = 3; + static const int MODE = 1; + static const int DELAY = 2; + }; +} + +#endif /* Spine_SequenceTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ShearTimeline.h new file mode 100644 index 0000000..6717743 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -0,0 +1,109 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ShearTimeline_h +#define Spine_ShearTimeline_h + +#include + +namespace spine { + class SP_API ShearTimeline : public CurveTimeline2 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ShearTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API ShearXTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ShearXTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API ShearYTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~ShearYTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; +} + +#endif /* Spine_ShearTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Skeleton.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Skeleton.h new file mode 100644 index 0000000..82304d6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -0,0 +1,285 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Skeleton_h +#define Spine_Skeleton_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + class SkeletonData; + + class Bone; + + class Updatable; + + class Slot; + + class IkConstraint; + + class PathConstraint; + + class PhysicsConstraint; + + class TransformConstraint; + + class Skin; + + class Attachment; + + class SkeletonClipping; + + class SP_API Skeleton : public SpineObject { + friend class AnimationState; + + friend class SkeletonBounds; + + friend class SkeletonClipping; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class ScaleTimeline; + + friend class ScaleXTimeline; + + friend class ScaleYTimeline; + + friend class ShearTimeline; + + friend class ShearXTimeline; + + friend class ShearYTimeline; + + friend class TransformConstraintTimeline; + + friend class RotateTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + friend class TwoColorTimeline; + + public: + explicit Skeleton(SkeletonData *skeletonData); + + ~Skeleton(); + + /// Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added + /// or removed. + void updateCache(); + + void printUpdateCache(); + + /// Updates the world transform for each bone and applies all constraints. + /// + /// See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + /// Runtimes Guide. + void updateWorldTransform(Physics physics); + + void updateWorldTransform(Physics physics, Bone *parent); + + /// Sets the bones, constraints, and slots to their setup pose values. + void setToSetupPose(); + + /// Sets the bones and constraints to their setup pose values. + void setBonesToSetupPose(); + + void setSlotsToSetupPose(); + + /// @return May be NULL. + Bone *findBone(const String &boneName); + + /// @return May be NULL. + Slot *findSlot(const String &slotName); + + /// Sets a skin by name (see setSkin). + void setSkin(const String &skinName); + + /// Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. + /// If there was no old skin, each slot's setup mode attachment is attached from the new skin. + /// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling + /// See Skeleton::setSlotsToSetupPose() + /// Also, often AnimationState::apply(Skeleton&) is called before the next time the + /// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. + /// @param newSkin May be NULL. + void setSkin(Skin *newSkin); + + /// @return May be NULL. + Attachment *getAttachment(const String &slotName, const String &attachmentName); + + /// @return May be NULL. + Attachment *getAttachment(int slotIndex, const String &attachmentName); + + /// @param attachmentName May be empty. + void setAttachment(const String &slotName, const String &attachmentName); + + /// @return May be NULL. + IkConstraint *findIkConstraint(const String &constraintName); + + /// @return May be NULL. + TransformConstraint *findTransformConstraint(const String &constraintName); + + /// @return May be NULL. + PathConstraint *findPathConstraint(const String &constraintName); + + /// @return May be NULL. + PhysicsConstraint *findPhysicsConstraint(const String &constraintName); + + /// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. + /// @param outX The horizontal distance between the skeleton origin and the left side of the AABB. + /// @param outY The vertical distance between the skeleton origin and the bottom side of the AABB. + /// @param outWidth The width of the AABB + /// @param outHeight The height of the AABB. + /// @param outVertexBuffer Reference to hold a Vector of floats. This method will assign it with new floats as needed. + // @param clipping Pointer to a SkeletonClipping instance or NULL. If a clipper is given, clipping attachments will be taken into account. + void getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector &outVertexBuffer); + void getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector &outVertexBuffer, SkeletonClipping *clipper); + + Bone *getRootBone(); + + SkeletonData *getData(); + + Vector &getBones(); + + Vector &getUpdateCacheList(); + + Vector &getSlots(); + + Vector &getDrawOrder(); + + Vector &getIkConstraints(); + + Vector &getPathConstraints(); + + Vector &getTransformConstraints(); + + Vector &getPhysicsConstraints(); + + Skin *getSkin(); + + Color &getColor(); + + void setPosition(float x, float y); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getScaleX(); + + void setScaleX(float inValue); + + float getScaleY(); + + void setScaleY(float inValue); + + float getTime(); + + void setTime(float time); + + void update(float delta); + + /// Rotates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone rotated around the + /// specified point in world space. + void physicsTranslate(float x, float y); + + /// Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */ + void physicsRotate(float x, float y, float degrees); + + private: + SkeletonData *_data; + Vector _bones; + Vector _slots; + Vector _drawOrder; + Vector _ikConstraints; + Vector _transformConstraints; + Vector _pathConstraints; + Vector _physicsConstraints; + Vector _updateCache; + Skin *_skin; + Color _color; + float _scaleX, _scaleY; + float _x, _y; + float _time; + + void sortIkConstraint(IkConstraint *constraint); + + void sortPathConstraint(PathConstraint *constraint); + + void sortPhysicsConstraint(PhysicsConstraint *constraint); + + void sortTransformConstraint(TransformConstraint *constraint); + + void sortPathConstraintAttachment(Skin *skin, size_t slotIndex, Bone &slotBone); + + void sortPathConstraintAttachment(Attachment *attachment, Bone &slotBone); + + void sortBone(Bone *bone); + + static void sortReset(Vector &bones); + }; +} + +#endif /* Spine_Skeleton_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h new file mode 100644 index 0000000..cd74070 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -0,0 +1,178 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonBinary_h +#define Spine_SkeletonBinary_h + +#include +#include +#include +#include +#include + +namespace spine { + class SkeletonData; + + class Atlas; + + class AttachmentLoader; + + class LinkedMesh; + + class Skin; + + class Attachment; + + class VertexAttachment; + + class Animation; + + class Timeline; + + class CurveTimeline; + + class CurveTimeline1; + + class CurveTimeline2; + + class Sequence; + + class SP_API SkeletonBinary : public SpineObject { + public: + static const int BONE_ROTATE = 0; + static const int BONE_TRANSLATE = 1; + static const int BONE_TRANSLATEX = 2; + static const int BONE_TRANSLATEY = 3; + static const int BONE_SCALE = 4; + static const int BONE_SCALEX = 5; + static const int BONE_SCALEY = 6; + static const int BONE_SHEAR = 7; + static const int BONE_SHEARX = 8; + static const int BONE_SHEARY = 9; + static const int BONE_INHERIT = 10; + + static const int SLOT_ATTACHMENT = 0; + static const int SLOT_RGBA = 1; + static const int SLOT_RGB = 2; + static const int SLOT_RGBA2 = 3; + static const int SLOT_RGB2 = 4; + static const int SLOT_ALPHA = 5; + + static const int ATTACHMENT_DEFORM = 0; + static const int ATTACHMENT_SEQUENCE = 1; + + static const int PATH_POSITION = 0; + static const int PATH_SPACING = 1; + static const int PATH_MIX = 2; + + static const int PHYSICS_INERTIA = 0; + static const int PHYSICS_STRENGTH = 1; + static const int PHYSICS_DAMPING = 2; + static const int PHYSICS_MASS = 4; + static const int PHYSICS_WIND = 5; + static const int PHYSICS_GRAVITY = 6; + static const int PHYSICS_MIX = 7; + static const int PHYSICS_RESET = 8; + + static const int CURVE_LINEAR = 0; + static const int CURVE_STEPPED = 1; + static const int CURVE_BEZIER = 2; + + explicit SkeletonBinary(Atlas *atlasArray); + + explicit SkeletonBinary(AttachmentLoader *attachmentLoader, bool ownsLoader = false); + + ~SkeletonBinary(); + + SkeletonData *readSkeletonData(const unsigned char *binary, int length); + + SkeletonData *readSkeletonDataFile(const String &path); + + void setScale(float scale) { _scale = scale; } + + String &getError() { return _error; } + + private: + struct DataInput : public SpineObject { + const unsigned char *cursor; + const unsigned char *end; + }; + + AttachmentLoader *_attachmentLoader; + Vector _linkedMeshes; + String _error; + float _scale; + const bool _ownsLoader; + + void setError(const char *value1, const char *value2); + + char *readString(DataInput *input); + + char *readStringRef(DataInput *input, SkeletonData *skeletonData); + + float readFloat(DataInput *input); + + unsigned char readByte(DataInput *input); + + signed char readSByte(DataInput *input); + + bool readBoolean(DataInput *input); + + int readInt(DataInput *input); + + void readColor(DataInput *input, Color &color); + + int readVarint(DataInput *input, bool optimizePositive); + + Skin *readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential); + + Sequence *readSequence(DataInput *input); + + Attachment *readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName, + SkeletonData *skeletonData, bool nonessential); + + int readVertices(DataInput *input, Vector &vertices, Vector &bones, bool weighted); + + void readFloatArray(DataInput *input, int n, float scale, Vector &array); + + void readShortArray(DataInput *input, Vector &array, int n); + + Animation *readAnimation(const String &name, DataInput *input, SkeletonData *skeletonData); + + void + setBezier(DataInput *input, CurveTimeline *timeline, int bezier, int frame, int value, float time1, float time2, + float value1, float value2, float scale); + + void readTimeline(DataInput *input, Vector &timelines, CurveTimeline1 *timeline, float scale); + + void readTimeline2(DataInput *input, Vector &timelines, CurveTimeline2 *timeline, float scale); + }; +} + +#endif /* Spine_SkeletonBinary_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h new file mode 100644 index 0000000..00c5942 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonBounds_h +#define Spine_SkeletonBounds_h + +#include +#include +#include + +namespace spine { + class Skeleton; + + class BoundingBoxAttachment; + + class Polygon; + + /// Collects each BoundingBoxAttachment that is visible and computes the world vertices for its polygon. + /// The polygon vertices are provided along with convenience methods for doing hit detection. + class SP_API SkeletonBounds : public SpineObject { + public: + SkeletonBounds(); + + ~SkeletonBounds(); + + /// Clears any previous polygons, finds all visible bounding box attachments, + /// and computes the world vertices for each bounding box's polygon. + /// @param skeleton The skeleton. + /// @param updateAabb + /// If true, the axis aligned bounding box containing all the polygons is computed. + /// If false, the SkeletonBounds AABB methods will always return true. + /// + void update(Skeleton &skeleton, bool updateAabb); + + /// Returns true if the axis aligned bounding box contains the point. + bool aabbcontainsPoint(float x, float y); + + /// Returns true if the axis aligned bounding box intersects the line segment. + bool aabbintersectsSegment(float x1, float y1, float x2, float y2); + + /// Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. + bool aabbIntersectsSkeleton(SkeletonBounds &bounds); + + /// Returns true if the polygon contains the point. + bool containsPoint(Polygon *polygon, float x, float y); + + /// Returns the first bounding box attachment that contains the point, or NULL. When doing many checks, it is usually more + /// efficient to only call this method if {@link #aabbcontainsPoint(float, float)} returns true. + BoundingBoxAttachment *containsPoint(float x, float y); + + /// Returns the first bounding box attachment that contains the line segment, or NULL. When doing many checks, it is usually + /// more efficient to only call this method if {@link #aabbintersectsSegment(float, float, float, float)} returns true. + BoundingBoxAttachment *intersectsSegment(float x1, float y1, float x2, float y2); + + /// Returns true if the polygon contains the line segment. + bool intersectsSegment(Polygon *polygon, float x1, float y1, float x2, float y2); + + /// Returns the polygon for the given bounding box attachment or null if no + /// polygon can be found for the attachment. Requires a call to update() first. + Polygon *getPolygon(BoundingBoxAttachment *attachment); + + /// Returns the bounding box for the given polygon or null. Requires a call to update() first. + BoundingBoxAttachment * getBoundingBox(Polygon *polygon); + + /// Returns all polygons or an empty vector. Requires a call to update() first. + Vector &getPolygons(); + + /// Returns all bounding boxes. Requires a call to update() first. + Vector &getBoundingBoxes(); + + float getWidth(); + + float getHeight(); + + private: + Pool _polygonPool; + Vector _boundingBoxes; + Vector _polygons; + float _minX, _minY, _maxX, _maxY; + + void aabbCompute(); + }; + + class Polygon : public SpineObject { + public: + Vector _vertices; + int _count; + + Polygon() : _count(0) { + _vertices.ensureCapacity(16); + } + }; +} + +#endif /* Spine_SkeletonBounds_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h new file mode 100644 index 0000000..52b868a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h @@ -0,0 +1,88 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonClipping_h +#define Spine_SkeletonClipping_h + +#include +#include + +namespace spine { + class Slot; + + class ClippingAttachment; + + class SP_API SkeletonClipping : public SpineObject { + public: + SkeletonClipping(); + + size_t clipStart(Slot &slot, ClippingAttachment *clip); + + void clipEnd(Slot &slot); + + void clipEnd(); + + void + clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength); + + void + clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength, float *uvs, size_t stride); + + void + clipTriangles(Vector &vertices, Vector &triangles, Vector &uvs, size_t stride); + + bool isClipping(); + + Vector &getClippedVertices(); + + Vector &getClippedTriangles(); + + Vector &getClippedUVs(); + + private: + Triangulator _triangulator; + Vector _clippingPolygon; + Vector _clipOutput; + Vector _clippedVertices; + Vector _clippedTriangles; + Vector _clippedUVs; + Vector _scratch; + ClippingAttachment *_clipAttachment; + Vector *> *_clippingPolygons; + + /** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping + * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */ + bool clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector *clippingArea, + Vector *output); + + static void makeClockwise(Vector &polygon); + }; +} + +#endif /* Spine_SkeletonClipping_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonData.h new file mode 100644 index 0000000..71afa14 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonData.h @@ -0,0 +1,195 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonData_h +#define Spine_SkeletonData_h + +#include +#include + +namespace spine { + class BoneData; + + class SlotData; + + class Skin; + + class EventData; + + class Animation; + + class IkConstraintData; + + class TransformConstraintData; + + class PathConstraintData; + + class PhysicsConstraintData; + +/// Stores the setup pose and all of the stateless data for a skeleton. + class SP_API SkeletonData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class Skeleton; + + public: + SkeletonData(); + + ~SkeletonData(); + + /// Finds a bone by comparing each bone's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + BoneData *findBone(const String &boneName); + + /// @return May be NULL. + SlotData *findSlot(const String &slotName); + + /// @return May be NULL. + Skin *findSkin(const String &skinName); + + /// @return May be NULL. + spine::EventData *findEvent(const String &eventDataName); + + /// @return May be NULL. + Animation *findAnimation(const String &animationName); + + /// @return May be NULL. + IkConstraintData *findIkConstraint(const String &constraintName); + + /// @return May be NULL. + TransformConstraintData *findTransformConstraint(const String &constraintName); + + /// @return May be NULL. + PathConstraintData *findPathConstraint(const String &constraintName); + + /// @return May be NULL. + PhysicsConstraintData *findPhysicsConstraint(const String &constraintName); + + const String &getName(); + + void setName(const String &inValue); + + /// The skeleton's bones, sorted parent first. The root bone is always the first bone. + Vector &getBones(); + + Vector &getSlots(); + + /// All skins, including the default skin. + Vector &getSkins(); + + /// The skeleton's default skin. + /// By default this skin contains all attachments that were not in a skin in Spine. + /// @return May be NULL. + Skin *getDefaultSkin(); + + void setDefaultSkin(Skin *inValue); + + Vector &getEvents(); + + Vector &getAnimations(); + + Vector &getIkConstraints(); + + Vector &getTransformConstraints(); + + Vector &getPathConstraints(); + + Vector &getPhysicsConstraints(); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + float getWidth(); + + void setWidth(float inValue); + + float getHeight(); + + void setHeight(float inValue); + + float getReferenceScale(); + + void setReferenceScale(float inValue); + + /// The Spine version used to export this data, or NULL. + const String &getVersion(); + + void setVersion(const String &inValue); + + const String &getHash(); + + void setHash(const String &inValue); + + const String &getImagesPath(); + + void setImagesPath(const String &inValue); + + const String &getAudioPath(); + + void setAudioPath(const String &inValue); + + /// The dopesheet FPS in Spine. Available only when nonessential data was exported. + float getFps(); + + void setFps(float inValue); + + private: + String _name; + Vector _bones; // Ordered parents first + Vector _slots; // Setup pose draw order. + Vector _skins; + Skin *_defaultSkin; + Vector _events; + Vector _animations; + Vector _ikConstraints; + Vector _transformConstraints; + Vector _pathConstraints; + Vector _physicsConstraints; + float _x, _y, _width, _height; + float _referenceScale; + String _version; + String _hash; + Vector _strings; + + // Nonessential. + float _fps; + String _imagesPath; + String _audioPath; + }; +} + +#endif /* Spine_SkeletonData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonJson.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonJson.h new file mode 100644 index 0000000..73ac5a0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonJson.h @@ -0,0 +1,114 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonJson_h +#define Spine_SkeletonJson_h + +#include +#include +#include + +namespace spine { + class Timeline; + + class CurveTimeline; + + class CurveTimeline1; + + class CurveTimeline2; + + class VertexAttachment; + + class Animation; + + class Json; + + class SkeletonData; + + class Atlas; + + class AttachmentLoader; + + class LinkedMesh; + + class String; + + class Sequence; + + class SP_API SkeletonJson : public SpineObject { + public: + explicit SkeletonJson(Atlas *atlas); + + explicit SkeletonJson(AttachmentLoader *attachmentLoader, bool ownsLoader = false); + + ~SkeletonJson(); + + SkeletonData *readSkeletonDataFile(const String &path); + + SkeletonData *readSkeletonData(const char *json); + + void setScale(float scale) { _scale = scale; } + + String &getError() { return _error; } + + private: + AttachmentLoader *_attachmentLoader; + Vector _linkedMeshes; + float _scale; + const bool _ownsLoader; + String _error; + + static Sequence *readSequence(Json *sequence); + + static void + setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1, + float cy1, + float cx2, float cy2, float time2, float value2); + + static int + readCurve(Json *curve, CurveTimeline *timeline, int bezier, int frame, int value, float time1, float time2, + float value1, float value2, float scale); + + static Timeline *readTimeline(Json *keyMap, CurveTimeline1 *timeline, float defaultValue, float scale); + + static Timeline * + readTimeline(Json *keyMap, CurveTimeline2 *timeline, const char *name1, const char *name2, float defaultValue, + float scale); + + Animation *readAnimation(Json *root, SkeletonData *skeletonData); + + void readVertices(Json *attachmentMap, VertexAttachment *attachment, size_t verticesLength); + + void setError(Json *root, const String &value1, const String &value2); + + int findSlotIndex(SkeletonData *skeletonData, const String &slotName, Vector timelines); + }; +} + +#endif /* Spine_SkeletonJson_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonRenderer.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonRenderer.h new file mode 100644 index 0000000..7da2b62 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SkeletonRenderer.h @@ -0,0 +1,69 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonRenderer_h +#define Spine_SkeletonRenderer_h + +#include +#include +#include + +namespace spine { + class Skeleton; + + struct SP_API RenderCommand { + float *positions; + float *uvs; + uint32_t *colors; + uint32_t *darkColors; + int32_t numVertices; + uint16_t *indices; + int32_t numIndices; + BlendMode blendMode; + void *texture; + RenderCommand *next; + }; + + class SP_API SkeletonRenderer: public SpineObject { + public: + explicit SkeletonRenderer(); + + ~SkeletonRenderer(); + + RenderCommand *render(Skeleton &skeleton); + private: + BlockAllocator _allocator; + Vector _worldVertices; + Vector _quadIndices; + SkeletonClipping _clipping; + Vector _renderCommands; + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Skin.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Skin.h new file mode 100644 index 0000000..9b2383c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Skin.h @@ -0,0 +1,171 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Skin_h +#define Spine_Skin_h + +#include +#include +#include + +namespace spine { + class Attachment; + + class Skeleton; + + class BoneData; + + class ConstraintData; + +/// Stores attachments by slot index and attachment name. +/// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and +/// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide. + class SP_API Skin : public SpineObject { + friend class Skeleton; + + public: + class SP_API AttachmentMap : public SpineObject { + friend class Skin; + + public: + struct SP_API Entry { + size_t _slotIndex; + String _name; + Attachment *_attachment; + + Entry(size_t slotIndex, const String &name, Attachment *attachment) : + _slotIndex(slotIndex), + _name(name), + _attachment(attachment) { + } + }; + + class SP_API Entries { + friend class AttachmentMap; + + public: + bool hasNext() { + while (true) { + if (_slotIndex >= _buckets.size()) return false; + if (_bucketIndex >= _buckets[_slotIndex].size()) { + _bucketIndex = 0; + ++_slotIndex; + continue; + }; + return true; + } + } + + Entry &next() { + Entry &result = _buckets[_slotIndex][_bucketIndex]; + ++_bucketIndex; + return result; + } + + protected: + Entries(Vector > &buckets) : _buckets(buckets), _slotIndex(0), _bucketIndex(0) { + } + + private: + Vector > &_buckets; + size_t _slotIndex; + size_t _bucketIndex; + }; + + void put(size_t slotIndex, const String &attachmentName, Attachment *attachment); + + Attachment *get(size_t slotIndex, const String &attachmentName); + + void remove(size_t slotIndex, const String &attachmentName); + + Entries getEntries(); + + protected: + AttachmentMap(); + + private: + + int findInBucket(Vector &, const String &attachmentName); + + Vector > _buckets; + }; + + explicit Skin(const String &name); + + ~Skin(); + + /// Adds an attachment to the skin for the specified slot index and name. + /// If the name already exists for the slot, the previous value is replaced. + void setAttachment(size_t slotIndex, const String &name, Attachment *attachment); + + /// Returns the attachment for the specified slot index and name, or NULL. + Attachment *getAttachment(size_t slotIndex, const String &name); + + // Removes the attachment from the skin. + void removeAttachment(size_t slotIndex, const String &name); + + /// Finds the skin keys for a given slot. The results are added to the passed array of names. + /// @param slotIndex The target slotIndex. To find the slot index, use SkeletonData::findSlot and SlotData::getIndex. + /// @param names Found skin key names will be added to this array. + void findNamesForSlot(size_t slotIndex, Vector &names); + + /// Finds the attachments for a given slot. The results are added to the passed array of Attachments. + /// @param slotIndex The target slotIndex. To find the slot index, use SkeletonData::findSlot and SlotData::getIndex. + /// @param attachments Found Attachments will be added to this array. + void findAttachmentsForSlot(size_t slotIndex, Vector &attachments); + + const String &getName(); + + /// Adds all attachments, bones, and constraints from the specified skin to this skin. + void addSkin(Skin *other); + + /// Adds all attachments, bones, and constraints from the specified skin to this skin. Attachments are deep copied. + void copySkin(Skin *other); + + AttachmentMap::Entries getAttachments(); + + Vector &getBones(); + + Vector &getConstraints(); + + Color &getColor() { return _color; } + + private: + const String _name; + AttachmentMap _attachments; + Vector _bones; + Vector _constraints; + Color _color; + + /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. + void attachAll(Skeleton &skeleton, Skin &oldSkin); + }; +} + +#endif /* Spine_Skin_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Slot.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Slot.h new file mode 100644 index 0000000..1c828ed --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Slot.h @@ -0,0 +1,137 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Slot_h +#define Spine_Slot_h + +#include +#include +#include + +namespace spine { + class SlotData; + + class Bone; + + class Skeleton; + + class Attachment; + + class SP_API Slot : public SpineObject { + friend class VertexAttachment; + + friend class Skeleton; + + friend class SkeletonBounds; + + friend class SkeletonClipping; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TwoColorTimeline; + + public: + Slot(SlotData &data, Bone &bone); + + void setToSetupPose(); + + SlotData &getData(); + + Bone &getBone(); + + Skeleton &getSkeleton(); + + Color &getColor(); + + Color &getDarkColor(); + + bool hasDarkColor(); + + /// May be NULL. + Attachment *getAttachment(); + + void setAttachment(Attachment *inValue); + + int getAttachmentState(); + + void setAttachmentState(int state); + + Vector &getDeform(); + + int getSequenceIndex(); + + void setSequenceIndex(int index); + + private: + SlotData &_data; + Bone &_bone; + Skeleton &_skeleton; + Color _color; + Color _darkColor; + bool _hasDarkColor; + Attachment *_attachment; + int _attachmentState; + int _sequenceIndex; + Vector _deform; + }; +} + +#endif /* Spine_Slot_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SlotData.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SlotData.h new file mode 100644 index 0000000..8e16ea9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -0,0 +1,126 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SlotData_h +#define Spine_SlotData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SP_API SlotData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TwoColorTimeline; + + public: + SlotData(int index, const String &name, BoneData &boneData); + + int getIndex(); + + const String &getName(); + + BoneData &getBoneData(); + + Color &getColor(); + + Color &getDarkColor(); + + bool hasDarkColor(); + + void setHasDarkColor(bool inValue); + + /// May be empty. + const String &getAttachmentName(); + + void setAttachmentName(const String &inValue); + + BlendMode getBlendMode(); + + void setBlendMode(BlendMode inValue); + + bool isVisible(); + + void setVisible(bool inValue); + + private: + const int _index; + String _name; + BoneData &_boneData; + Color _color; + Color _darkColor; + + bool _hasDarkColor; + String _attachmentName; + BlendMode _blendMode; + bool _visible; + }; +} + +#endif /* Spine_SlotData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SpacingMode.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SpacingMode.h new file mode 100644 index 0000000..84a311b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SpacingMode.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SpacingMode_h +#define Spine_SpacingMode_h + +namespace spine { + enum SpacingMode { + SpacingMode_Length = 0, + SpacingMode_Fixed, + SpacingMode_Percent, + SpacingMode_Proportional + }; +} + +#endif /* Spine_SpacingMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SpineObject.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SpineObject.h new file mode 100644 index 0000000..dc89369 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SpineObject.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Object_h +#define Spine_Object_h + +#include +#include + +#include + +namespace spine { + class String; + + class SP_API SpineObject { + public: + void *operator new(size_t sz); + + void *operator new(size_t sz, const char *file, int line); + + void *operator new(size_t sz, void *ptr); + + void operator delete(void *p, const char *file, int line); + + void operator delete(void *p, void *mem); + + void operator delete(void *p); + + virtual ~SpineObject(); + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SpineString.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SpineString.h new file mode 100644 index 0000000..3f77431 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/SpineString.h @@ -0,0 +1,246 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_STRING_H +#define SPINE_STRING_H + +#include +#include + +#include +#include + +namespace spine { + class SP_API String : public SpineObject { + public: + String() : _length(0), _buffer(NULL), _tempowner(true) { + } + + String(const char *chars, bool own = false, bool tofree = true) { + _tempowner = tofree; + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + if (!own) { + _buffer = SpineExtension::calloc(_length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, chars, _length + 1); + } else { + _buffer = (char *) chars; + } + } + } + + String(const String &other) { + _tempowner = true; + if (!other._buffer) { + _length = 0; + _buffer = NULL; + } else { + _length = other._length; + _buffer = SpineExtension::calloc(other._length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, other._buffer, other._length + 1); + } + } + + size_t length() const { + return _length; + } + + bool isEmpty() const { + return _length == 0; + } + + const char *buffer() const { + return _buffer; + } + + void own(const String &other) { + if (this == &other) return; + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + _length = other._length; + _buffer = other._buffer; + other._length = 0; + other._buffer = NULL; + } + + void own(const char *chars) { + if (_buffer == chars) return; + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + _buffer = (char *) chars; + } + } + + void unown() { + _length = 0; + _buffer = NULL; + } + + String &operator=(const String &other) { + if (this == &other) return *this; + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + if (!other._buffer) { + _length = 0; + _buffer = NULL; + } else { + _length = other._length; + _buffer = SpineExtension::calloc(other._length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, other._buffer, other._length + 1); + } + return *this; + } + + String &operator=(const char *chars) { + if (_buffer == chars) return *this; + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + _buffer = SpineExtension::calloc(_length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, chars, _length + 1); + } + return *this; + } + + String &append(const char *chars) { + size_t len = strlen(chars); + size_t thisLen = _length; + _length = _length + len; + bool same = chars == _buffer; + _buffer = SpineExtension::realloc(_buffer, _length + 1, __FILE__, __LINE__); + memcpy((void *) (_buffer + thisLen), (void *) (same ? _buffer : chars), len + 1); + return *this; + } + + String &append(const String &other) { + size_t len = other.length(); + size_t thisLen = _length; + _length = _length + len; + bool same = other._buffer == _buffer; + _buffer = SpineExtension::realloc(_buffer, _length + 1, __FILE__, __LINE__); + memcpy((void *) (_buffer + thisLen), (void *) (same ? _buffer : other._buffer), len + 1); + return *this; + } + + String &append(int other) { + char str[100]; + snprintf(str, 100, "%i", other); + append(str); + return *this; + } + + String &append(float other) { + char str[100]; + snprintf(str, 100, "%f", other); + append(str); + return *this; + } + + bool startsWith(const String &needle) const { + if (needle.length() > length()) return false; + for (int i = 0; i < (int)needle.length(); i++) { + if (buffer()[i] != needle.buffer()[i]) return false; + } + return true; + } + + int lastIndexOf(const char c) const { + for (int i = (int)length() - 1; i >= 0; i--) { + if (buffer()[i] == c) return i; + } + return -1; + } + + String substring(int startIndex, int length) const { + if (startIndex < 0 || startIndex >= (int)_length || length < 0 || startIndex + length > (int)_length) { + return String(); + } + char* subStr = SpineExtension::calloc(length + 1, __FILE__, __LINE__); + memcpy(subStr, _buffer + startIndex, length); + subStr[length] = '\0'; + return String(subStr, true, true); + } + + String substring(int startIndex) const { + if (startIndex < 0 || startIndex >= (int)_length) { + return String(); + } + int length = (int)_length - startIndex; + char* subStr = SpineExtension::calloc(length + 1, __FILE__, __LINE__); + memcpy(subStr, _buffer + startIndex, length); + subStr[length] = '\0'; + return String(subStr, true, true); + } + + friend bool operator==(const String &a, const String &b) { + if (a._buffer == b._buffer) return true; + if (a._length != b._length) return false; + if (a._buffer && b._buffer) { + return strcmp(a._buffer, b._buffer) == 0; + } else { + return false; + } + } + + friend bool operator!=(const String &a, const String &b) { + return !(a == b); + } + + ~String() { + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + } + + private: + mutable size_t _length; + mutable char *_buffer; + mutable bool _tempowner; + }; +} + + +#endif //SPINE_STRING_H diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TextureLoader.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TextureLoader.h new file mode 100644 index 0000000..60f86af --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TextureLoader.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TextureLoader_h +#define Spine_TextureLoader_h + +#include +#include + +namespace spine { + class AtlasPage; + + class SP_API TextureLoader : public SpineObject { + public: + TextureLoader(); + + virtual ~TextureLoader(); + + virtual void load(AtlasPage &page, const String &path) = 0; + + virtual void unload(void *texture) = 0; + }; +} + +#endif /* Spine_TextureLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TextureRegion.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TextureRegion.h new file mode 100644 index 0000000..1082c5d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TextureRegion.h @@ -0,0 +1,50 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TextureRegion_h +#define Spine_TextureRegion_h + +#include + +namespace spine { + class SP_API TextureRegion : public SpineObject { + public: + void *rendererObject; + float u, v, u2, v2; + int degrees; + float offsetX, offsetY; + int width, height; + int originalWidth, originalHeight; + + TextureRegion(): rendererObject(NULL), u(0), v(0), u2(0), v2(0), degrees(0), offsetX(0), offsetY(0), width(0), height(0), originalWidth(0), originalHeight(0) {}; + ~TextureRegion() {}; + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Timeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Timeline.h new file mode 100644 index 0000000..c9ded4b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Timeline_h +#define Spine_Timeline_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + class Skeleton; + + class Event; + + class SP_API Timeline : public SpineObject { + RTTI_DECL + + public: + Timeline(size_t frameCount, size_t frameEntries); + + virtual ~Timeline(); + + /// Sets the value(s) for the specified time. + /// @param skeleton The skeleton the timeline is being applied to. This provides access to the bones, slots, and other skeleton components the timeline may change. + /// @param lastTime lastTime The time this timeline was last applied. Timelines such as EventTimeline trigger only at specific times rather than every frame. In that case, the timeline triggers everything between lastTime (exclusive) and time (inclusive). + /// @param time The time within the animation. Most timelines find the key before and the key after this time so they can interpolate between the keys. + /// @param pEvents If any events are fired, they are added to this array. Can be NULL to ignore firing events or if the timeline does not fire events. May be NULL. + /// @param alpha alpha 0 applies the current or setup pose value (depending on pose parameter). 1 applies the timeline + /// value. Between 0 and 1 applies a value between the current or setup pose and the timeline value. By adjusting alpha over + /// time, an animation can be mixed in or out. alpha can also be useful to apply animations on top of each other (layered). + /// @param blend Controls how mixing is applied when alpha is than 1. + /// @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions such as DrawOrderTimeline and AttachmentTimeline. + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction) = 0; + + size_t getFrameEntries(); + + size_t getFrameCount(); + + Vector &getFrames(); + + float getDuration(); + + virtual Vector &getPropertyIds(); + + protected: + void setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount); + + Vector _propertyIds; + Vector _frames; + size_t _frameEntries; + }; +} + +#endif /* Spine_Timeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TransformConstraint.h new file mode 100644 index 0000000..cc85902 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraint_h +#define Spine_TransformConstraint_h + +#include + +#include + +namespace spine { + class TransformConstraintData; + + class Skeleton; + + class Bone; + + class SP_API TransformConstraint : public Updatable { + friend class Skeleton; + + friend class TransformConstraintTimeline; + + RTTI_DECL + + public: + TransformConstraint(TransformConstraintData &data, Skeleton &skeleton); + + virtual void update(Physics physics); + + virtual int getOrder(); + + TransformConstraintData &getData(); + + Vector &getBones(); + + Bone *getTarget(); + + void setTarget(Bone *inValue); + + float getMixRotate(); + + void setMixRotate(float inValue); + + float getMixX(); + + void setMixX(float inValue); + + float getMixY(); + + void setMixY(float inValue); + + float getMixScaleX(); + + void setMixScaleX(float inValue); + + float getMixScaleY(); + + void setMixScaleY(float inValue); + + float getMixShearY(); + + void setMixShearY(float inValue); + + bool isActive(); + + void setActive(bool inValue); + + void setToSetupPose(); + + private: + TransformConstraintData &_data; + Vector _bones; + Bone *_target; + float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY; + bool _active; + + void applyAbsoluteWorld(); + + void applyRelativeWorld(); + + void applyAbsoluteLocal(); + + void applyRelativeLocal(); + }; +} + +#endif /* Spine_TransformConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h new file mode 100644 index 0000000..9446bf8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -0,0 +1,128 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraintData_h +#define Spine_TransformConstraintData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SP_API TransformConstraintData : public ConstraintData { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class TransformConstraint; + + friend class Skeleton; + + friend class TransformConstraintTimeline; + + public: + RTTI_DECL + + explicit TransformConstraintData(const String &name); + + Vector &getBones(); + + BoneData *getTarget(); + + void setTarget(BoneData *target); + + float getMixRotate(); + + void setMixRotate(float mixRotate); + + float getMixX(); + + void setMixX(float mixX); + + float getMixY(); + + void setMixY(float mixY); + + float getMixScaleX(); + + void setMixScaleX(float mixScaleX); + + float getMixScaleY(); + + void setMixScaleY(float mixScaleY); + + float getMixShearY(); + + void setMixShearY(float mixShearY); + + float getOffsetRotation(); + + void setOffsetRotation(float offsetRotation); + + float getOffsetX(); + + void setOffsetX(float offsetX); + + float getOffsetY(); + + void setOffsetY(float offsetY); + + float getOffsetScaleX(); + + void setOffsetScaleX(float offsetScaleX); + + float getOffsetScaleY(); + + void setOffsetScaleY(float offsetScaleY); + + float getOffsetShearY(); + + void setOffsetShearY(float offsetShearY); + + bool isRelative(); + + void setRelative(bool isRelative); + + bool isLocal(); + + void setLocal(bool isLocal); + + private: + Vector _bones; + BoneData *_target; + float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY; + float _offsetRotation, _offsetX, _offsetY, _offsetScaleX, _offsetScaleY, _offsetShearY; + bool _relative, _local; + }; +} + +#endif /* Spine_TransformConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h new file mode 100644 index 0000000..514c6d3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraintTimeline_h +#define Spine_TransformConstraintTimeline_h + +#include + +namespace spine { + + class SP_API TransformConstraintTimeline : public CurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TransformConstraintTimeline(size_t frameCount, size_t bezierCount, int transformConstraintIndex); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + void setFrame(size_t frameIndex, float time, float mixRotate, float mixX, float mixY, float mixScaleX, + float mixScaleY, float mixShearY); + + int getTransformConstraintIndex() { return _constraintIndex; } + + void setTransformConstraintIndex(int inValue) { _constraintIndex = inValue; } + + private: + int _constraintIndex; + + static const int ENTRIES = 7; + static const int ROTATE = 1; + static const int X = 2; + static const int Y = 3; + static const int SCALEX = 4; + static const int SCALEY = 5; + static const int SHEARY = 6; + }; +} + +#endif /* Spine_TransformConstraintTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h new file mode 100644 index 0000000..77dbf7e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TranslateTimeline_h +#define Spine_TranslateTimeline_h + +#include + +#include +#include + +namespace spine { + + class SP_API TranslateTimeline : public CurveTimeline2 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~TranslateTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API TranslateXTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~TranslateXTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; + + class SP_API TranslateYTimeline : public CurveTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + virtual ~TranslateYTimeline(); + + virtual void + apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, MixBlend blend, + MixDirection direction); + + int getBoneIndex() { return _boneIndex; } + + void setBoneIndex(int inValue) { _boneIndex = inValue; } + + private: + int _boneIndex; + }; +} + +#endif /* Spine_TranslateTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Triangulator.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Triangulator.h new file mode 100644 index 0000000..801167d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Triangulator.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Triangulator_h +#define Spine_Triangulator_h + +#include +#include + +namespace spine { + class SP_API Triangulator : public SpineObject { + public: + ~Triangulator(); + + Vector &triangulate(Vector &vertices); + + Vector* > & + decompose(Vector + &vertices, + Vector &triangles + ); + + private: + Vector* > + _convexPolygons; + Vector* > + _convexPolygonsIndices; + + Vector _indices; + Vector _isConcaveArray; + Vector _triangles; + + Pool > _polygonPool; + Pool > _polygonIndicesPool; + + static bool isConcave(int index, int vertexCount, Vector &vertices, Vector &indices); + + static bool positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y); + + static int winding(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y); + }; +} + +#endif /* Spine_Triangulator_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Updatable.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Updatable.h new file mode 100644 index 0000000..dc5b4d3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Updatable.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Updatable_h +#define Spine_Updatable_h + +#include +#include +#include + +namespace spine { + class SP_API Updatable : public SpineObject { + RTTI_DECL + + public: + Updatable(); + + virtual ~Updatable(); + + virtual void update(Physics physics) = 0; + + virtual bool isActive() = 0; + + virtual void setActive(bool inValue) = 0; + }; +} + +#endif /* Spine_Updatable_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Vector.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Vector.h new file mode 100644 index 0000000..8ad9196 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Vector.h @@ -0,0 +1,245 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Vector_h +#define Spine_Vector_h + +#include +#include +#include +#include + +namespace spine { + template + class SP_API Vector : public SpineObject { + public: + using size_type = size_t; + using value_type = T; + + Vector() : _size(0), _capacity(0), _buffer(NULL) { + } + + Vector(const Vector &inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL) { + if (_capacity > 0) { + _buffer = allocate(_capacity); + for (size_t i = 0; i < _size; ++i) { + construct(_buffer + i, inVector._buffer[i]); + } + } + } + + ~Vector() { + clear(); + deallocate(_buffer); + } + + inline void clear() { + for (size_t i = 0; i < _size; ++i) { + destroy(_buffer + (_size - 1 - i)); + } + + _size = 0; + } + + inline size_t getCapacity() const { + return _capacity; + } + + inline size_t size() const { + return _size; + } + + inline void setSize(size_t newSize, const T &defaultValue) { + assert(newSize >= 0); + size_t oldSize = _size; + _size = newSize; + if (_capacity < newSize) { + if (_capacity == 0) { + _capacity = _size; + } else { + _capacity = (int) (_size * 1.75f); + } + if (_capacity < 8) _capacity = 8; + _buffer = spine::SpineExtension::realloc(_buffer, _capacity, __FILE__, __LINE__); + } + if (oldSize < _size) { + for (size_t i = oldSize; i < _size; i++) { + construct(_buffer + i, defaultValue); + } + } else { + for (size_t i = _size; i < oldSize; i++) { + destroy(_buffer + i); + } + } + } + + inline void ensureCapacity(size_t newCapacity = 0) { + if (_capacity >= newCapacity) return; + _capacity = newCapacity; + _buffer = SpineExtension::realloc(_buffer, newCapacity, __FILE__, __LINE__); + } + + inline void add(const T &inValue) { + if (_size == _capacity) { + // inValue might reference an element in this buffer + // When we reallocate, the reference becomes invalid. + // We thus need to create a defensive copy before + // reallocating. + T valueCopy = inValue; + _capacity = (int) (_size * 1.75f); + if (_capacity < 8) _capacity = 8; + _buffer = spine::SpineExtension::realloc(_buffer, _capacity, __FILE__, __LINE__); + construct(_buffer + _size++, valueCopy); + } else { + construct(_buffer + _size++, inValue); + } + } + + inline void addAll(const Vector &inValue) { + ensureCapacity(this->size() + inValue.size()); + for (size_t i = 0; i < inValue.size(); i++) { + add(inValue[i]); + } + } + + inline void clearAndAddAll(const Vector &inValue) { + this->clear(); + this->addAll(inValue); + } + + inline void removeAt(size_t inIndex) { + assert(inIndex < _size); + + --_size; + + if (inIndex != _size) { + for (size_t i = inIndex; i < _size; ++i) { + T tmp(_buffer[i]); + _buffer[i] = _buffer[i + 1]; + _buffer[i + 1] = tmp; + } + } + + destroy(_buffer + _size); + } + + inline bool contains(const T &inValue) { + for (size_t i = 0; i < _size; ++i) { + if (_buffer[i] == inValue) { + return true; + } + } + + return false; + } + + inline int indexOf(const T &inValue) { + for (size_t i = 0; i < _size; ++i) { + if (_buffer[i] == inValue) { + return (int) i; + } + } + + return -1; + } + + inline T &operator[](size_t inIndex) { + assert(inIndex < _size); + + return _buffer[inIndex]; + } + + inline const T &operator[](size_t inIndex) const { + assert(inIndex < _size); + + return _buffer[inIndex]; + } + + inline friend bool operator==(Vector &lhs, Vector &rhs) { + if (lhs.size() != rhs.size()) { + return false; + } + + for (size_t i = 0, n = lhs.size(); i < n; ++i) { + if (lhs[i] != rhs[i]) { + return false; + } + } + + return true; + } + + inline friend bool operator!=(Vector &lhs, Vector &rhs) { + return !(lhs == rhs); + } + + Vector &operator=(const Vector &inVector) { + if (this != &inVector) { + clearAndAddAll(inVector); + } + return *this; + } + + inline T *buffer() { + return _buffer; + } + + private: + size_t _size; + size_t _capacity; + T *_buffer; + + inline T *allocate(size_t n) { + assert(n > 0); + + T *ptr = SpineExtension::calloc(n, __FILE__, __LINE__); + + assert(ptr); + + return ptr; + } + + inline void deallocate(T *buffer) { + if (_buffer) { + SpineExtension::free(buffer, __FILE__, __LINE__); + } + } + + inline void construct(T *buffer, const T &val) { + new(buffer) T(val); + } + + inline void destroy(T *buffer) { + buffer->~T(); + } + + }; +} + +#endif /* Spine_Vector_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Version.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Version.h new file mode 100644 index 0000000..eaa5655 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Version.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_VERSION_H_ +#define SPINE_VERSION_H_ + +#define SPINE_MAJOR_VERSION 4 +#define SPINE_MINOR_VERSION 2 +#define SPINE_VERSION_STRING "4.2" + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/VertexAttachment.h new file mode 100644 index 0000000..e4957a9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_VertexAttachment_h +#define Spine_VertexAttachment_h + +#include + +#include + +namespace spine { + class Slot; + + /// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices. + class SP_API VertexAttachment : public Attachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class DeformTimeline; + + RTTI_DECL + + public: + explicit VertexAttachment(const String &name); + + virtual ~VertexAttachment(); + + void computeWorldVertices(Slot &slot, float *worldVertices); + + void computeWorldVertices(Slot &slot, Vector &worldVertices); + + /// Transforms local vertices to world coordinates. + /// @param start The index of the first Vertices value to transform. Each vertex has 2 values, x and y. + /// @param count The number of world vertex values to output. Must be less than or equal to WorldVerticesLength - start. + /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + count. + /// @param offset The worldVertices index to begin writing values. + /// @param stride The number of worldVertices entries between the value pairs written. + virtual void computeWorldVertices(Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride = 2); + + virtual void computeWorldVertices(Slot &slot, size_t start, size_t count, Vector &worldVertices, size_t offset, + size_t stride = 2); + + /// Gets a unique ID for this attachment. + int getId(); + + Vector &getBones(); + + Vector &getVertices(); + + size_t getWorldVerticesLength(); + + void setWorldVerticesLength(size_t inValue); + + Attachment * getTimelineAttachment(); + + void setTimelineAttachment(Attachment *attachment); + + void copyTo(VertexAttachment *other); + + protected: + Vector _bones; + Vector _vertices; + size_t _worldVerticesLength; + Attachment *_timelineAttachment; + + private: + const int _id; + + static int getNextID(); + }; +} + +#endif /* Spine_VertexAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Vertices.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Vertices.h new file mode 100644 index 0000000..070d823 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/Vertices.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Vertices_h +#define Spine_Vertices_h + +#include + +namespace spine { + class SP_API Vertices : public SpineObject { + public: + Vector _bones; + Vector _vertices; + }; +} + +#endif /* Spine_Vertices_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/dll.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/dll.h new file mode 100644 index 0000000..2681a53 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/dll.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SHAREDLIB_H +#define SPINE_SHAREDLIB_H + +#ifdef _WIN32 +#define DLLIMPORT __declspec(dllimport) +#define DLLEXPORT __declspec(dllexport) +#else +#ifndef DLLIMPORT +#define DLLIMPORT +#endif +#ifndef DLLEXPORT +#define DLLEXPORT +#endif +#endif + +#ifdef SPINEPLUGIN_API +#define SP_API SPINEPLUGIN_API +#else +#define SP_API +#endif + +#endif /* SPINE_SHAREDLIB_H */ diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/spine.h b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/spine.h new file mode 100644 index 0000000..ab3e541 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/include/spine/spine.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SPINE_H_ +#define SPINE_SPINE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Animation.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Animation.cpp new file mode 100644 index 0000000..21fafac --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Animation.cpp @@ -0,0 +1,107 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include + +#include + +#include + +using namespace spine; + +Animation::Animation(const String &name, Vector &timelines, float duration) : _timelines(timelines), + _timelineIds(), + _duration(duration), + _name(name) { + assert(_name.length() > 0); + for (size_t i = 0; i < timelines.size(); i++) { + Vector propertyIds = timelines[i]->getPropertyIds(); + for (size_t ii = 0; ii < propertyIds.size(); ii++) + _timelineIds.put(propertyIds[ii], true); + } +} + +bool Animation::hasTimeline(Vector &ids) { + for (size_t i = 0; i < ids.size(); i++) { + if (_timelineIds.containsKey(ids[i])) return true; + } + return false; +} + +Animation::~Animation() { + ContainerUtil::cleanUpVectorOfPointers(_timelines); +} + +void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + if (loop && _duration != 0) { + time = MathUtil::fmod(time, _duration); + if (lastTime > 0) { + lastTime = MathUtil::fmod(lastTime, _duration); + } + } + + for (size_t i = 0, n = _timelines.size(); i < n; ++i) { + _timelines[i]->apply(skeleton, lastTime, time, pEvents, alpha, blend, direction); + } +} + +const String &Animation::getName() { + return _name; +} + +Vector &Animation::getTimelines() { + return _timelines; +} + +float Animation::getDuration() { + return _duration; +} + +void Animation::setDuration(float inValue) { + _duration = inValue; +} + +int Animation::search(Vector &frames, float target) { + size_t n = (int) frames.size(); + for (size_t i = 1; i < n; i++) { + if (frames[i] > target) return (int) (i - 1); + } + return (int) (n - 1); +} + +int Animation::search(Vector &frames, float target, int step) { + size_t n = frames.size(); + for (size_t i = step; i < n; i += step) + if (frames[i] > target) return (int) (i - step); + return (int) (n - step); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AnimationState.cpp new file mode 100644 index 0000000..7920e94 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -0,0 +1,1104 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +void dummyOnAnimationEventFunc(AnimationState *state, spine::EventType type, TrackEntry *entry, Event *event = NULL) { + SP_UNUSED(state); + SP_UNUSED(type); + SP_UNUSED(entry); + SP_UNUSED(event); +} + +TrackEntry::TrackEntry() : _animation(NULL), _previous(NULL), _next(NULL), _mixingFrom(NULL), _mixingTo(0), + _trackIndex(0), _loop(false), _holdPrevious(false), _reverse(false), + _shortestRotation(false), + _eventThreshold(0), _mixAttachmentThreshold(0), _alphaAttachmentThreshold(0), _mixDrawOrderThreshold(0), _animationStart(0), + _animationEnd(0), _animationLast(0), _nextAnimationLast(0), _delay(0), _trackTime(0), + _trackLast(0), _nextTrackLast(0), _trackEnd(0), _timeScale(1.0f), _alpha(0), _mixTime(0), + _mixDuration(0), _interruptAlpha(0), _totalAlpha(0), _mixBlend(MixBlend_Replace), + _listener(dummyOnAnimationEventFunc), _listenerObject(NULL) { +} + +TrackEntry::~TrackEntry() {} + +int TrackEntry::getTrackIndex() { return _trackIndex; } + +Animation *TrackEntry::getAnimation() { return _animation; } + +TrackEntry *TrackEntry::getPrevious() { return _previous; } + +bool TrackEntry::getLoop() { return _loop; } + +void TrackEntry::setLoop(bool inValue) { _loop = inValue; } + +bool TrackEntry::getHoldPrevious() { return _holdPrevious; } + +void TrackEntry::setHoldPrevious(bool inValue) { _holdPrevious = inValue; } + +bool TrackEntry::getReverse() { return _reverse; } + +void TrackEntry::setReverse(bool inValue) { _reverse = inValue; } + +bool TrackEntry::getShortestRotation() { return _shortestRotation; } + +void TrackEntry::setShortestRotation(bool inValue) { _shortestRotation = inValue; } + +float TrackEntry::getDelay() { return _delay; } + +void TrackEntry::setDelay(float inValue) { _delay = inValue; } + +float TrackEntry::getTrackTime() { return _trackTime; } + +void TrackEntry::setTrackTime(float inValue) { _trackTime = inValue; } + +float TrackEntry::getTrackEnd() { return _trackEnd; } + +void TrackEntry::setTrackEnd(float inValue) { _trackEnd = inValue; } + +float TrackEntry::getAnimationStart() { return _animationStart; } + +void TrackEntry::setAnimationStart(float inValue) { _animationStart = inValue; } + +float TrackEntry::getAnimationEnd() { return _animationEnd; } + +void TrackEntry::setAnimationEnd(float inValue) { _animationEnd = inValue; } + +float TrackEntry::getAnimationLast() { return _animationLast; } + +void TrackEntry::setAnimationLast(float inValue) { + _animationLast = inValue; + _nextAnimationLast = inValue; +} + +float TrackEntry::getAnimationTime() { + if (_loop) { + float duration = _animationEnd - _animationStart; + if (duration == 0) return _animationStart; + return MathUtil::fmod(_trackTime, duration) + _animationStart; + } + + return MathUtil::min(_trackTime + _animationStart, _animationEnd); +} + +float TrackEntry::getTimeScale() { return _timeScale; } + +void TrackEntry::setTimeScale(float inValue) { _timeScale = inValue; } + +float TrackEntry::getAlpha() { return _alpha; } + +void TrackEntry::setAlpha(float inValue) { _alpha = inValue; } + +float TrackEntry::getEventThreshold() { return _eventThreshold; } + +void TrackEntry::setEventThreshold(float inValue) { _eventThreshold = inValue; } + +float TrackEntry::getMixAttachmentThreshold() { return _mixAttachmentThreshold; } + +void TrackEntry::setMixAttachmentThreshold(float inValue) { _mixAttachmentThreshold = inValue; } + +float TrackEntry::getAlphaAttachmentThreshold() { return _alphaAttachmentThreshold; } + +void TrackEntry::setAlphaAttachmentThreshold(float inValue) { _alphaAttachmentThreshold = inValue; } + +float TrackEntry::getMixDrawOrderThreshold() { return _mixDrawOrderThreshold; } + +void TrackEntry::setMixDrawOrderThreshold(float inValue) { _mixDrawOrderThreshold = inValue; } + +TrackEntry *TrackEntry::getNext() { return _next; } + +bool TrackEntry::isComplete() { + return _trackTime >= _animationEnd - _animationStart; +} + +float TrackEntry::getMixTime() { return _mixTime; } + +void TrackEntry::setMixTime(float inValue) { _mixTime = inValue; } + +float TrackEntry::getMixDuration() { return _mixDuration; } + +void TrackEntry::setMixDuration(float inValue) { _mixDuration = inValue; } + +void TrackEntry::setMixDuration(float mixDuration, float delay) { + _mixDuration = mixDuration; + if (delay <= 0) { + if (_previous != nullptr) + delay = MathUtil::max(delay + _previous->getTrackComplete() - mixDuration, 0.0f); + else + delay = 0; + } + this->_delay = delay; +} + +TrackEntry *TrackEntry::getMixingFrom() { return _mixingFrom; } + +TrackEntry *TrackEntry::getMixingTo() { return _mixingTo; } + +void TrackEntry::setMixBlend(MixBlend blend) { _mixBlend = blend; } + +MixBlend TrackEntry::getMixBlend() { return _mixBlend; } + +void TrackEntry::resetRotationDirections() { + _timelinesRotation.clear(); +} + +void TrackEntry::setListener(AnimationStateListener inValue) { + _listener = inValue; + _listenerObject = NULL; +} + +void TrackEntry::setListener(AnimationStateListenerObject *inValue) { + _listener = dummyOnAnimationEventFunc; + _listenerObject = inValue; +} + +void TrackEntry::reset() { + _animation = NULL; + _previous = NULL; + _next = NULL; + _mixingFrom = NULL; + _mixingTo = NULL; + + setRendererObject(NULL); + + _timelineMode.clear(); + _timelineHoldMix.clear(); + _timelinesRotation.clear(); + + _listener = dummyOnAnimationEventFunc; + _listenerObject = NULL; +} + +float TrackEntry::getTrackComplete() { + float duration = _animationEnd - _animationStart; + if (duration != 0) { + if (_loop) return duration * (1 + (int) (_trackTime / duration));// Completion of next loop. + if (_trackTime < duration) return duration; // Before duration. + } + return _trackTime;// Next update. +} + +bool TrackEntry::wasApplied() { + return _nextTrackLast != -1; +} + +EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry *trackEntry, Event *event) : _type(eventType), + _entry(trackEntry), + _event(event) { +} + +EventQueue *EventQueue::newEventQueue(AnimationState &state) { + return new (__FILE__, __LINE__) EventQueue(state); +} + +EventQueueEntry EventQueue::newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event) { + return EventQueueEntry(eventType, entry, event); +} + +EventQueue::EventQueue(AnimationState &state) : _state(state), + _drainDisabled(false) { +} + +EventQueue::~EventQueue() { +} + +void EventQueue::start(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Start, entry)); + _state._animationsChanged = true; +} + +void EventQueue::interrupt(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Interrupt, entry)); +} + +void EventQueue::end(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_End, entry)); + _state._animationsChanged = true; +} + +void EventQueue::dispose(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Dispose, entry)); +} + +void EventQueue::complete(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Complete, entry)); +} + +void EventQueue::event(TrackEntry *entry, Event *event) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Event, entry, event)); +} + +/// Raises all events in the queue and drains the queue. +void EventQueue::drain() { + if (_drainDisabled) { + return; + } + + _drainDisabled = true; + + AnimationState &state = _state; + + // Don't cache _eventQueueEntries.size() so callbacks can queue their own events (eg, call setAnimation in AnimationState_Complete). + for (size_t i = 0; i < _eventQueueEntries.size(); ++i) { + EventQueueEntry queueEntry = _eventQueueEntries[i]; + TrackEntry *trackEntry = queueEntry._entry; + + switch (queueEntry._type) { + case EventType_Start: + case EventType_Interrupt: + case EventType_Complete: + if (!trackEntry->_listenerObject) trackEntry->_listener(&state, queueEntry._type, trackEntry, NULL); + else + trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + if (!state._listenerObject) state._listener(&state, queueEntry._type, trackEntry, NULL); + else + state._listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + break; + case EventType_End: + if (!trackEntry->_listenerObject) trackEntry->_listener(&state, queueEntry._type, trackEntry, NULL); + else + trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + if (!state._listenerObject) state._listener(&state, queueEntry._type, trackEntry, NULL); + else + state._listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + /* Fall through. */ + case EventType_Dispose: + if (!trackEntry->_listenerObject) trackEntry->_listener(&state, EventType_Dispose, trackEntry, NULL); + else + trackEntry->_listenerObject->callback(&state, EventType_Dispose, trackEntry, NULL); + if (!state._listenerObject) state._listener(&state, EventType_Dispose, trackEntry, NULL); + else + state._listenerObject->callback(&state, EventType_Dispose, trackEntry, NULL); + + if (!_state.getManualTrackEntryDisposal()) _state.disposeTrackEntry(trackEntry); + break; + case EventType_Event: + if (!trackEntry->_listenerObject) + trackEntry->_listener(&state, queueEntry._type, trackEntry, queueEntry._event); + else + trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, queueEntry._event); + if (!state._listenerObject) state._listener(&state, queueEntry._type, trackEntry, queueEntry._event); + else + state._listenerObject->callback(&state, queueEntry._type, trackEntry, queueEntry._event); + break; + } + } + _eventQueueEntries.clear(); + + _drainDisabled = false; +} + +AnimationState::AnimationState(AnimationStateData *data) : _data(data), + _queue(EventQueue::newEventQueue(*this)), + _animationsChanged(false), + _listener(dummyOnAnimationEventFunc), + _listenerObject(NULL), + _unkeyedState(0), + _timeScale(1), + _manualTrackEntryDisposal(false) { +} + +AnimationState::~AnimationState() { + for (size_t i = 0; i < _tracks.size(); i++) { + TrackEntry *entry = _tracks[i]; + if (entry) { + TrackEntry *from = entry->_mixingFrom; + while (from) { + TrackEntry *curr = from; + from = curr->_mixingFrom; + delete curr; + } + TrackEntry *next = entry->_next; + while (next) { + TrackEntry *curr = next; + next = curr->_next; + delete curr; + } + delete entry; + } + } + delete _queue; +} + +void AnimationState::update(float delta) { + delta *= _timeScale; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *currentP = _tracks[i]; + if (currentP == NULL) { + continue; + } + + TrackEntry ¤t = *currentP; + + current._animationLast = current._nextAnimationLast; + current._trackLast = current._nextTrackLast; + + float currentDelta = delta * current._timeScale; + + if (current._delay > 0) { + current._delay -= currentDelta; + if (current._delay > 0) { + continue; + } + currentDelta = -current._delay; + current._delay = 0; + } + + TrackEntry *next = current._next; + if (next != NULL) { + // When the next entry's delay is passed, change to the next entry, preserving leftover time. + float nextTime = current._trackLast - next->_delay; + if (nextTime >= 0) { + next->_delay = 0; + next->_trackTime += + current._timeScale == 0 ? 0 : (nextTime / current._timeScale + delta) * next->_timeScale; + current._trackTime += currentDelta; + setCurrent(i, next, true); + while (next->_mixingFrom != NULL) { + next->_mixTime += delta; + next = next->_mixingFrom; + } + continue; + } + } else if (current._trackLast >= current._trackEnd && current._mixingFrom == NULL) { + // clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. + _tracks[i] = NULL; + + _queue->end(currentP); + clearNext(currentP); + continue; + } + + if (current._mixingFrom != NULL && updateMixingFrom(currentP, delta)) { + // End mixing from entries once all have completed. + TrackEntry *from = current._mixingFrom; + current._mixingFrom = NULL; + if (from != NULL) from->_mixingTo = NULL; + while (from != NULL) { + _queue->end(from); + from = from->_mixingFrom; + } + } + + current._trackTime += currentDelta; + } + + _queue->drain(); +} + +bool AnimationState::apply(Skeleton &skeleton) { + if (_animationsChanged) { + animationsChanged(); + } + + bool applied = false; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *currentP = _tracks[i]; + if (currentP == NULL || currentP->_delay > 0) { + continue; + } + + TrackEntry ¤t = *currentP; + + applied = true; + MixBlend blend = i == 0 ? MixBlend_First : current._mixBlend; + + // apply mixing from entries first. + float alpha = current._alpha; + if (current._mixingFrom != NULL) { + alpha *= applyMixingFrom(currentP, skeleton, blend); + } else if (current._trackTime >= current._trackEnd && current._next == NULL) { + alpha = 0;// Set to setup pose the last time the entry will be applied. + } + bool attachments = alpha >= current._alphaAttachmentThreshold; + + + // apply current entry. + float animationLast = current._animationLast, animationTime = current.getAnimationTime(); + float applyTime = animationTime; + Vector *applyEvents = &_events; + if (current._reverse) { + applyTime = current._animation->getDuration() - applyTime; + applyEvents = NULL; + } + size_t timelineCount = current._animation->_timelines.size(); + Vector &timelines = current._animation->_timelines; + if ((i == 0 && alpha == 1) || blend == MixBlend_Add) { + if (i == 0) attachments = true; + for (size_t ii = 0; ii < timelineCount; ++ii) { + Timeline *timeline = timelines[ii]; + if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) + applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, blend, + attachments); + else + timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, MixDirection_In); + } + } else { + Vector &timelineMode = current._timelineMode; + + bool shortestRotation = current._shortestRotation; + bool firstFrame = !shortestRotation && current._timelinesRotation.size() != timelines.size() << 1; + if (firstFrame) current._timelinesRotation.setSize(timelines.size() << 1, 0); + Vector &timelinesRotation = current._timelinesRotation; + + for (size_t ii = 0; ii < timelineCount; ++ii) { + Timeline *timeline = timelines[ii]; + assert(timeline); + + MixBlend timelineBlend = timelineMode[ii] == Subsequent ? blend : MixBlend_Setup; + + if (!shortestRotation && timeline->getRTTI().isExactly(RotateTimeline::rtti)) + applyRotateTimeline(static_cast(timeline), skeleton, applyTime, alpha, + timelineBlend, timelinesRotation, ii << 1, firstFrame); + else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) + applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, + blend, attachments); + else + timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend, + MixDirection_In); + } + } + + queueEvents(currentP, animationTime); + _events.clear(); + current._nextAnimationLast = animationTime; + current._nextTrackLast = current._trackTime; + } + + int setupState = _unkeyedState + Setup; + Vector &slots = skeleton.getSlots(); + for (int i = 0, n = (int) slots.size(); i < n; i++) { + Slot *slot = slots[i]; + if (slot->getAttachmentState() == setupState) { + const String &attachmentName = slot->getData().getAttachmentName(); + slot->setAttachment(attachmentName.isEmpty() ? NULL : skeleton.getAttachment(slot->getData().getIndex(), attachmentName)); + } + } + _unkeyedState += 2; + + _queue->drain(); + return applied; +} + +void AnimationState::clearTracks() { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) + clearTrack(i); + _tracks.clear(); + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); +} + +void AnimationState::clearTrack(size_t trackIndex) { + if (trackIndex >= _tracks.size()) return; + + TrackEntry *current = _tracks[trackIndex]; + if (current == NULL) return; + + _queue->end(current); + + clearNext(current); + + TrackEntry *entry = current; + while (true) { + TrackEntry *from = entry->_mixingFrom; + if (from == NULL) break; + + _queue->end(from); + entry->_mixingFrom = NULL; + entry->_mixingTo = NULL; + entry = from; + } + + _tracks[current->_trackIndex] = NULL; + + _queue->drain(); +} + +TrackEntry *AnimationState::setAnimation(size_t trackIndex, const String &animationName, bool loop) { + Animation *animation = _data->_skeletonData->findAnimation(animationName); + assert(animation != NULL); + return setAnimation(trackIndex, animation, loop); +} + +TrackEntry *AnimationState::setAnimation(size_t trackIndex, Animation *animation, bool loop) { + assert(animation != NULL); + + bool interrupt = true; + TrackEntry *current = expandToIndex(trackIndex); + if (current != NULL) { + if (current->_nextTrackLast == -1) { + // Don't mix from an entry that was never applied. + _tracks[trackIndex] = current->_mixingFrom; + _queue->interrupt(current); + _queue->end(current); + clearNext(current); + current = current->_mixingFrom; + interrupt = false; + } else { + clearNext(current); + } + } + + TrackEntry *entry = newTrackEntry(trackIndex, animation, loop, current); + setCurrent(trackIndex, entry, interrupt); + _queue->drain(); + + return entry; +} + +TrackEntry *AnimationState::addAnimation(size_t trackIndex, const String &animationName, bool loop, float delay) { + Animation *animation = _data->_skeletonData->findAnimation(animationName); + assert(animation != NULL); + return addAnimation(trackIndex, animation, loop, delay); +} + +TrackEntry *AnimationState::addAnimation(size_t trackIndex, Animation *animation, bool loop, float delay) { + assert(animation != NULL); + + TrackEntry *last = expandToIndex(trackIndex); + if (last != NULL) { + while (last->_next != NULL) + last = last->_next; + } + + TrackEntry *entry = newTrackEntry(trackIndex, animation, loop, last); + + if (last == NULL) { + setCurrent(trackIndex, entry, true); + _queue->drain(); + if (delay < 0) delay = 0; + } else { + last->_next = entry; + entry->_previous = last; + if (delay <= 0) delay = MathUtil::max(delay + last->getTrackComplete() - entry->_mixDuration, 0.0f); + } + + entry->_delay = delay; + return entry; +} + +TrackEntry *AnimationState::setEmptyAnimation(size_t trackIndex, float mixDuration) { + TrackEntry *entry = setAnimation(trackIndex, AnimationState::getEmptyAnimation(), false); + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; +} + +TrackEntry *AnimationState::addEmptyAnimation(size_t trackIndex, float mixDuration, float delay) { + TrackEntry *entry = addAnimation(trackIndex, AnimationState::getEmptyAnimation(), false, delay); + if (delay <= 0) entry->_delay = MathUtil::max(entry->_delay + entry->_mixDuration - mixDuration, 0.0f); + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; +} + +void AnimationState::setEmptyAnimations(float mixDuration) { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *current = _tracks[i]; + if (current != NULL) { + setEmptyAnimation(i, mixDuration); + } + } + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); +} + +TrackEntry *AnimationState::getCurrent(size_t trackIndex) { + return trackIndex >= _tracks.size() ? NULL : _tracks[trackIndex]; +} + +AnimationStateData *AnimationState::getData() { + return _data; +} + +Vector &AnimationState::getTracks() { + return _tracks; +} + +float AnimationState::getTimeScale() { + return _timeScale; +} + +void AnimationState::setTimeScale(float inValue) { + _timeScale = inValue; +} + +void AnimationState::setListener(AnimationStateListener inValue) { + _listener = inValue; + _listenerObject = NULL; +} + +void AnimationState::setListener(AnimationStateListenerObject *inValue) { + _listener = dummyOnAnimationEventFunc; + _listenerObject = inValue; +} + +void AnimationState::disableQueue() { + _queue->_drainDisabled = true; +} + +void AnimationState::enableQueue() { + _queue->_drainDisabled = false; +} + +void AnimationState::setManualTrackEntryDisposal(bool inValue) { + _manualTrackEntryDisposal = inValue; +} + +bool AnimationState::getManualTrackEntryDisposal() { + return _manualTrackEntryDisposal; +} + +void AnimationState::disposeTrackEntry(TrackEntry *entry) { + entry->reset(); + _trackEntryPool.free(entry); +} + +Animation *AnimationState::getEmptyAnimation() { + static Vector timelines; + static Animation ret(String(""), timelines, 0); + return &ret; +} + +void AnimationState::applyAttachmentTimeline(AttachmentTimeline *attachmentTimeline, Skeleton &skeleton, float time, + MixBlend blend, bool attachments) { + Slot *slot = skeleton.getSlots()[attachmentTimeline->getSlotIndex()]; + if (!slot->getBone().isActive()) return; + + Vector &frames = attachmentTimeline->getFrames(); + if (time < frames[0]) { + if (blend == MixBlend_Setup || blend == MixBlend_First) + setAttachment(skeleton, *slot, slot->getData().getAttachmentName(), attachments); + } else { + setAttachment(skeleton, *slot, attachmentTimeline->getAttachmentNames()[Animation::search(frames, time)], + attachments); + } + + /* If an attachment wasn't set (ie before the first frame or attachments is false), set the setup attachment later.*/ + if (slot->getAttachmentState() <= _unkeyedState) slot->setAttachmentState(_unkeyedState + Setup); +} + + +void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, + MixBlend blend, Vector &timelinesRotation, size_t i, bool firstFrame) { + if (firstFrame) timelinesRotation[i] = 0; + + if (alpha == 1) { + rotateTimeline->apply(skeleton, 0, time, NULL, 1, blend, MixDirection_In); + return; + } + + Bone *bone = skeleton._bones[rotateTimeline->_boneIndex]; + if (!bone->isActive()) return; + Vector &frames = rotateTimeline->_frames; + float r1, r2; + if (time < frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_rotation = bone->_data._rotation; + default: + return; + case MixBlend_First: + r1 = bone->_rotation; + r2 = bone->_data._rotation; + } + } else { + r1 = blend == MixBlend_Setup ? bone->_data._rotation : bone->_rotation; + r2 = bone->_data._rotation + rotateTimeline->getCurveValue(time); + } + + // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. + float total, diff = r2 - r1; + diff -= MathUtil::ceil(diff / 360 - 0.5) * 360; + if (diff == 0) { + total = timelinesRotation[i]; + } else { + float lastTotal, lastDiff; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } else { + lastTotal = timelinesRotation[i]; + lastDiff = timelinesRotation[i + 1]; + } + float loops = lastTotal - MathUtil::fmod(lastTotal, 360.f); + total = diff + loops; + bool current = diff >= 0, dir = lastTotal >= 0; + if (MathUtil::abs(lastDiff) <= 90 && MathUtil::sign(lastDiff) != MathUtil::sign(diff)) { + if (MathUtil::abs(lastTotal - loops) > 180) { + total += 360.f * MathUtil::sign(lastTotal); + dir = current; + } else if (loops != 0) + total -= 360.f * MathUtil::sign(lastTotal); + else + dir = current; + } + if (dir != current) { + total += 360 * MathUtil::sign(lastTotal); + } + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + bone->_rotation = r1 + total * alpha; +} + +bool AnimationState::updateMixingFrom(TrackEntry *to, float delta) { + TrackEntry *from = to->_mixingFrom; + if (from == NULL) { + return true; + } + + bool finished = updateMixingFrom(from, delta); + + from->_animationLast = from->_nextAnimationLast; + from->_trackLast = from->_nextTrackLast; + + // The from entry was applied at least once and the mix is complete. + if (to->_nextTrackLast != -1 && to->_mixTime >= to->_mixDuration) { + // Mixing is complete for all entries before the from entry or the mix is instantaneous. + if (from->_totalAlpha == 0 || to->_mixDuration == 0) { + to->_mixingFrom = from->_mixingFrom; + if (from->_mixingFrom) from->_mixingFrom->_mixingTo = to; + to->_interruptAlpha = from->_interruptAlpha; + _queue->end(from); + } + return finished; + } + + from->_trackTime += delta * from->_timeScale; + to->_mixTime += delta; + + return false; +} + +float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBlend blend) { + TrackEntry *from = to->_mixingFrom; + if (from->_mixingFrom != NULL) applyMixingFrom(from, skeleton, blend); + + float mix; + if (to->_mixDuration == 0) { + // Single frame mix to undo mixingFrom changes. + mix = 1; + if (blend == MixBlend_First) blend = MixBlend_Setup; + } else { + mix = to->_mixTime / to->_mixDuration; + if (mix > 1) { + mix = 1; + } + if (blend != MixBlend_First) blend = from->_mixBlend; + } + + bool attachments = mix < from->_mixAttachmentThreshold, drawOrder = mix < from->_mixDrawOrderThreshold; + Vector &timelines = from->_animation->_timelines; + size_t timelineCount = timelines.size(); + float alphaHold = from->_alpha * to->_interruptAlpha, alphaMix = alphaHold * (1 - mix); + float animationLast = from->_animationLast, animationTime = from->getAnimationTime(); + float applyTime = animationTime; + Vector *events = NULL; + if (from->_reverse) { + applyTime = from->_animation->_duration - applyTime; + } else { + if (mix < from->_eventThreshold) events = &_events; + } + + if (blend == MixBlend_Add) { + for (size_t i = 0; i < timelineCount; i++) + timelines[i]->apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection_Out); + } else { + Vector &timelineMode = from->_timelineMode; + Vector &timelineHoldMix = from->_timelineHoldMix; + + bool shortestRotation = from->_shortestRotation; + bool firstFrame = !shortestRotation && from->_timelinesRotation.size() != timelines.size() << 1; + if (firstFrame) from->_timelinesRotation.setSize(timelines.size() << 1, 0); + + Vector &timelinesRotation = from->_timelinesRotation; + + from->_totalAlpha = 0; + for (size_t i = 0; i < timelineCount; i++) { + Timeline *timeline = timelines[i]; + MixDirection direction = MixDirection_Out; + MixBlend timelineBlend; + float alpha; + switch (timelineMode[i]) { + case Subsequent: + if (!drawOrder && (timeline->getRTTI().isExactly(DrawOrderTimeline::rtti))) continue; + timelineBlend = blend; + alpha = alphaMix; + break; + case First: + timelineBlend = MixBlend_Setup; + alpha = alphaMix; + break; + case HoldSubsequent: + timelineBlend = blend; + alpha = alphaHold; + break; + case HoldFirst: + timelineBlend = MixBlend_Setup; + alpha = alphaHold; + break; + default: + timelineBlend = MixBlend_Setup; + TrackEntry *holdMix = timelineHoldMix[i]; + alpha = alphaHold * MathUtil::max(0.0f, 1.0f - holdMix->_mixTime / holdMix->_mixDuration); + break; + } + from->_totalAlpha += alpha; + if (!shortestRotation && (timeline->getRTTI().isExactly(RotateTimeline::rtti))) { + applyRotateTimeline((RotateTimeline *) timeline, skeleton, applyTime, alpha, timelineBlend, + timelinesRotation, i << 1, firstFrame); + } else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) { + applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, timelineBlend, + attachments && alpha >= from->_alphaAttachmentThreshold); + } else { + if (drawOrder && timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) && + timelineBlend == MixBlend_Setup) + direction = MixDirection_In; + timeline->apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction); + } + } + } + + if (to->_mixDuration > 0) { + queueEvents(from, animationTime); + } + + _events.clear(); + from->_nextAnimationLast = animationTime; + from->_nextTrackLast = from->_trackTime; + + return mix; +} + +void AnimationState::setAttachment(Skeleton &skeleton, Slot &slot, const String &attachmentName, bool attachments) { + slot.setAttachment( + attachmentName.isEmpty() ? NULL : skeleton.getAttachment(slot.getData().getIndex(), attachmentName)); + if (attachments) slot.setAttachmentState(_unkeyedState + Current); +} + +void AnimationState::queueEvents(TrackEntry *entry, float animationTime) { + float animationStart = entry->_animationStart, animationEnd = entry->_animationEnd; + float duration = animationEnd - animationStart; + float trackLastWrapped = duration != 0 ? MathUtil::fmod(entry->_trackLast, duration) : MathUtil::quietNan(); + + // Queue events before complete. + size_t i = 0, n = _events.size(); + for (; i < n; ++i) { + Event *e = _events[i]; + if (e->_time < trackLastWrapped) break; + if (e->_time > animationEnd) continue;// Discard events outside animation start/end. + _queue->event(entry, e); + } + + // Queue complete if completed a loop iteration or the animation. + bool complete = false; + if (entry->_loop) { + if (duration == 0) + complete = true; + else { + int cycles = (int) (entry->_trackTime / duration); + complete = cycles > 0 && cycles > (int) (entry->_trackLast / duration); + } + } else { + complete = animationTime >= animationEnd && entry->_animationLast < animationEnd; + } + if (complete) _queue->complete(entry); + + // Queue events after complete. + for (; i < n; ++i) { + Event *e = _events[i]; + if (e->_time < animationStart) continue;// Discard events outside animation start/end. + _queue->event(entry, e); + } +} + +void AnimationState::setCurrent(size_t index, TrackEntry *current, bool interrupt) { + TrackEntry *from = expandToIndex(index); + _tracks[index] = current; + current->_previous = NULL; + + if (from != NULL) { + if (interrupt) _queue->interrupt(from); + + current->_mixingFrom = from; + from->_mixingTo = current; + current->_mixTime = 0; + + // Store interrupted mix percentage. + if (from->_mixingFrom != NULL && from->_mixDuration > 0) { + current->_interruptAlpha *= MathUtil::min(1.0f, from->_mixTime / from->_mixDuration); + } + + from->_timelinesRotation.clear();// Reset rotation for mixing out, in case entry was mixed in. + } + + _queue->start(current);// triggers animationsChanged +} + +TrackEntry *AnimationState::expandToIndex(size_t index) { + if (index < _tracks.size()) return _tracks[index]; + while (index >= _tracks.size()) + _tracks.add(NULL); + return NULL; +} + +TrackEntry *AnimationState::newTrackEntry(size_t trackIndex, Animation *animation, bool loop, TrackEntry *last) { + TrackEntry *entryP = _trackEntryPool.obtain();// Pooling + TrackEntry &entry = *entryP; + + entry._trackIndex = (int) trackIndex; + entry._animation = animation; + entry._loop = loop; + entry._holdPrevious = 0; + + entry._reverse = false; + entry._shortestRotation = false; + + entry._eventThreshold = 0; + entry._alphaAttachmentThreshold = 0; + entry._mixAttachmentThreshold = 0; + entry._mixDrawOrderThreshold = 0; + + entry._animationStart = 0; + entry._animationEnd = animation->getDuration(); + entry._animationLast = -1; + entry._nextAnimationLast = -1; + + entry._delay = 0; + entry._trackTime = 0; + entry._trackLast = -1; + entry._nextTrackLast = -1;// nextTrackLast == -1 signifies a TrackEntry that wasn't applied yet. + entry._trackEnd = FLT_MAX;// loop ? float.MaxValue : animation.Duration; + entry._timeScale = 1; + + entry._alpha = 1; + entry._mixTime = 0; + entry._mixDuration = (last == NULL) ? 0 : _data->getMix(last->_animation, animation); + entry._interruptAlpha = 1; + entry._totalAlpha = 0; + entry._mixBlend = MixBlend_Replace; + + return entryP; +} + +void AnimationState::clearNext(TrackEntry *entry) { + TrackEntry *next = entry->_next; + while (next != NULL) { + _queue->dispose(next); + next = next->_next; + } + entry->_next = NULL; +} + +void AnimationState::animationsChanged() { + _animationsChanged = false; + + _propertyIDs.clear(); + + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *entry = _tracks[i]; + if (!entry) continue; + + while (entry->_mixingFrom != NULL) + entry = entry->_mixingFrom; + + do { + if (entry->_mixingTo == NULL || entry->_mixBlend != MixBlend_Add) computeHold(entry); + entry = entry->_mixingTo; + } while (entry != NULL); + } +} + +void AnimationState::computeHold(TrackEntry *entry) { + TrackEntry *to = entry->_mixingTo; + Vector &timelines = entry->_animation->_timelines; + size_t timelinesCount = timelines.size(); + Vector &timelineMode = entry->_timelineMode; + timelineMode.setSize(timelinesCount, 0); + Vector &timelineHoldMix = entry->_timelineHoldMix; + timelineHoldMix.setSize(timelinesCount, 0); + + if (to != NULL && to->_holdPrevious) { + for (size_t i = 0; i < timelinesCount; i++) { + timelineMode[i] = _propertyIDs.addAll(timelines[i]->getPropertyIds(), true) ? HoldFirst : HoldSubsequent; + } + return; + } + + // outer: + size_t i = 0; +continue_outer: + for (; i < timelinesCount; ++i) { + Timeline *timeline = timelines[i]; + Vector &ids = timeline->getPropertyIds(); + if (!_propertyIDs.addAll(ids, true)) { + timelineMode[i] = Subsequent; + } else { + if (to == NULL || timeline->getRTTI().isExactly(AttachmentTimeline::rtti) || + timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) || + timeline->getRTTI().isExactly(EventTimeline::rtti) || !to->_animation->hasTimeline(ids)) { + timelineMode[i] = First; + } else { + for (TrackEntry *next = to->_mixingTo; next != NULL; next = next->_mixingTo) { + if (next->_animation->hasTimeline(ids)) continue; + if (next->_mixDuration > 0) { + timelineMode[i] = HoldMix; + timelineHoldMix[i] = next; + i++; + goto continue_outer;// continue outer; + } + break; + } + timelineMode[i] = HoldFirst; + } + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp new file mode 100644 index 0000000..9ba25ca --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +using namespace spine; + +AnimationStateData::AnimationStateData(SkeletonData *skeletonData) : _skeletonData(skeletonData), _defaultMix(0) { +} + +void AnimationStateData::setMix(const String &fromName, const String &toName, float duration) { + Animation *from = _skeletonData->findAnimation(fromName); + Animation *to = _skeletonData->findAnimation(toName); + + setMix(from, to, duration); +} + +void AnimationStateData::setMix(Animation *from, Animation *to, float duration) { + assert(from != NULL); + assert(to != NULL); + + AnimationPair key(from, to); + _animationToMixTime.put(key, duration); +} + +float AnimationStateData::getMix(Animation *from, Animation *to) { + assert(from != NULL); + assert(to != NULL); + + AnimationPair key(from, to); + + if (_animationToMixTime.containsKey(key)) return _animationToMixTime[key]; + return _defaultMix; +} + +SkeletonData *AnimationStateData::getSkeletonData() { + return _skeletonData; +} + +float AnimationStateData::getDefaultMix() { + return _defaultMix; +} + +void AnimationStateData::setDefaultMix(float inValue) { + _defaultMix = inValue; +} + +void AnimationStateData::clear() { + _defaultMix = 0; + _animationToMixTime.clear(); +} + +AnimationStateData::AnimationPair::AnimationPair(Animation *a1, Animation *a2) : _a1(a1), _a2(a2) { +} + +bool AnimationStateData::AnimationPair::operator==(const AnimationPair &other) const { + return _a1->_name == other._a1->_name && _a2->_name == other._a2->_name; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Atlas.cpp new file mode 100644 index 0000000..9258fa0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -0,0 +1,350 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +#include + +using namespace spine; + +Atlas::Atlas(const String &path, TextureLoader *textureLoader, bool createTexture) : _textureLoader(textureLoader) { + int dirLength; + char *dir; + int length; + const char *data; + + /* Get directory from atlas path. */ + const char *lastForwardSlash = strrchr(path.buffer(), '/'); + const char *lastBackwardSlash = strrchr(path.buffer(), '\\'); + const char *lastSlash = lastForwardSlash > lastBackwardSlash ? lastForwardSlash : lastBackwardSlash; + if (lastSlash == path) lastSlash++; /* Never drop starting slash. */ + dirLength = (int) (lastSlash ? lastSlash - path.buffer() : 0); + dir = SpineExtension::calloc(dirLength + 1, __FILE__, __LINE__); + memcpy(dir, path.buffer(), dirLength); + dir[dirLength] = '\0'; + + data = SpineExtension::readFile(path, &length); + if (data) { + load(data, length, dir, createTexture); + } + + SpineExtension::free(data, __FILE__, __LINE__); + SpineExtension::free(dir, __FILE__, __LINE__); +} + +Atlas::Atlas(const char *data, int length, const char *dir, TextureLoader *textureLoader, bool createTexture) + : _textureLoader( + textureLoader) { + load(data, length, dir, createTexture); +} + +Atlas::~Atlas() { + if (_textureLoader) { + for (size_t i = 0, n = _pages.size(); i < n; ++i) { + _textureLoader->unload(_pages[i]->texture); + } + } + ContainerUtil::cleanUpVectorOfPointers(_pages); + ContainerUtil::cleanUpVectorOfPointers(_regions); +} + +void Atlas::flipV() { + for (size_t i = 0, n = _regions.size(); i < n; ++i) { + AtlasRegion *regionP = _regions[i]; + AtlasRegion ®ion = *regionP; + region.v = 1 - region.v; + region.v2 = 1 - region.v2; + } +} + +AtlasRegion *Atlas::findRegion(const String &name) { + for (size_t i = 0, n = _regions.size(); i < n; ++i) + if (_regions[i]->name == name) return _regions[i]; + return NULL; +} + +Vector &Atlas::getPages() { + return _pages; +} + +Vector &Atlas::getRegions() { + return _regions; +} + +struct SimpleString { + char *start; + char *end; + int length; + + SimpleString trim() { + while (isspace((unsigned char) *start) && start < end) + start++; + if (start == end) { + length = (int) (end - start); + return *this; + } + end--; + while (((unsigned char) *end == '\r') && end >= start) + end--; + end++; + length = (int) (end - start); + return *this; + } + + int indexOf(char needle) { + char *c = start; + while (c < end) { + if (*c == needle) return (int) (c - start); + c++; + } + return -1; + } + + int indexOf(char needle, int at) { + char *c = start + at; + while (c < end) { + if (*c == needle) return (int) (c - start); + c++; + } + return -1; + } + + SimpleString substr(int s, int e) { + e = s + e; + SimpleString result; + result.start = start + s; + result.end = start + e; + result.length = e - s; + return result; + } + + SimpleString substr(int s) { + SimpleString result; + result.start = start + s; + result.end = end; + result.length = (int) (result.end - result.start); + return result; + } + + bool equals(const char *str) { + int otherLen = (int) strlen(str); + if (length != otherLen) return false; + for (int i = 0; i < length; i++) { + if (start[i] != str[i]) return false; + } + return true; + } + + char *copy() { + char *string = SpineExtension::calloc(length + 1, __FILE__, __LINE__); + memcpy(string, start, length); + string[length] = '\0'; + return string; + } + + int toInt() { + return (int) strtol(start, &end, 10); + } +}; + +struct AtlasInput { + const char *start; + const char *end; + char *index; + int length; + SimpleString line; + + AtlasInput(const char *data, int length) : start(data), end(data + length), index((char *) data), length(length) {} + + SimpleString *readLine() { + if (index >= end) return 0; + line.start = index; + while (index < end && *index != '\n') + index++; + line.end = index; + if (index != end) index++; + line = line.trim(); + line.length = (int) (end - start); + return &line; + } + + static int readEntry(SimpleString entry[5], SimpleString *line) { + if (line == NULL) return 0; + line->trim(); + if (line->length == 0) return 0; + + int colon = line->indexOf(':'); + if (colon == -1) return 0; + entry[0] = line->substr(0, colon).trim(); + for (int i = 1, lastMatch = colon + 1;; i++) { + int comma = line->indexOf(',', lastMatch); + if (comma == -1) { + entry[i] = line->substr(lastMatch).trim(); + return i; + } + entry[i] = line->substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + if (i == 4) return 4; + } + } +}; + +int indexOf(const char **array, int count, SimpleString *str) { + for (int i = 0; i < count; i++) + if (str->equals(array[i])) return i; + return 0; +} + +void Atlas::load(const char *begin, int length, const char *dir, bool createTexture) { + static const char *formatNames[] = {"", "Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888", + "RGBA8888"}; + static const char *textureFilterNames[] = {"", "Nearest", "Linear", "MipMap", "MipMapNearestNearest", + "MipMapLinearNearest", + "MipMapNearestLinear", "MipMapLinearLinear"}; + + int dirLength = (int) strlen(dir); + int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\'; + AtlasInput reader(begin, length); + SimpleString entry[5]; + AtlasPage *page = NULL; + + SimpleString *line = reader.readLine(); + while (line != NULL && line->length == 0) + line = reader.readLine(); + + while (true) { + if (line == NULL || line->length == 0) break; + if (reader.readEntry(entry, line) == 0) break; + line = reader.readLine(); + } + + while (true) { + if (line == NULL) break; + if (line->trim().length == 0) { + page = NULL; + line = reader.readLine(); + } else if (page == NULL) { + char *name = line->copy(); + char *path = SpineExtension::calloc(dirLength + needsSlash + strlen(name) + 1, __FILE__, __LINE__); + memcpy(path, dir, dirLength); + if (needsSlash) path[dirLength] = '/'; + strcpy(path + dirLength + needsSlash, name); + page = new (__FILE__, __LINE__) AtlasPage(String(name, true)); + + while (true) { + line = reader.readLine(); + if (reader.readEntry(entry, line) == 0) break; + if (entry[0].equals("size")) { + page->width = entry[1].toInt(); + page->height = entry[2].toInt(); + } else if (entry[0].equals("format")) { + page->format = (Format) indexOf(formatNames, 8, &entry[1]); + } else if (entry[0].equals("filter")) { + page->minFilter = (TEXTURE_FILTER_ENUM) indexOf(textureFilterNames, 8, &entry[1]); + page->magFilter = (TEXTURE_FILTER_ENUM) indexOf(textureFilterNames, 8, &entry[2]); + } else if (entry[0].equals("repeat")) { + page->uWrap = TextureWrap_ClampToEdge; + page->vWrap = TextureWrap_ClampToEdge; + if (entry[1].indexOf('x') != -1) page->uWrap = TextureWrap_Repeat; + if (entry[1].indexOf('y') != -1) page->vWrap = TextureWrap_Repeat; + } else if (entry[0].equals("pma")) { + page->pma = entry[1].equals("true"); + } + } + + page->index = (int) _pages.size(); + if (createTexture && _textureLoader) _textureLoader->load(*page, String(path)); + page->texturePath = String(path, true); + _pages.add(page); + } else { + AtlasRegion *region = new (__FILE__, __LINE__) AtlasRegion(); + region->page = page; + region->rendererObject = page->texture; + region->name = String(line->copy(), true); + while (true) { + line = reader.readLine(); + int count = reader.readEntry(entry, line); + if (count == 0) break; + if (entry[0].equals("xy")) { + region->x = entry[1].toInt(); + region->y = entry[2].toInt(); + } else if (entry[0].equals("size")) { + region->width = entry[1].toInt(); + region->height = entry[2].toInt(); + } else if (entry[0].equals("bounds")) { + region->x = entry[1].toInt(); + region->y = entry[2].toInt(); + region->width = entry[3].toInt(); + region->height = entry[4].toInt(); + } else if (entry[0].equals("offset")) { + region->offsetX = entry[1].toInt(); + region->offsetY = entry[2].toInt(); + } else if (entry[0].equals("orig")) { + region->originalWidth = entry[1].toInt(); + region->originalHeight = entry[2].toInt(); + } else if (entry[0].equals("offsets")) { + region->offsetX = entry[1].toInt(); + region->offsetY = entry[2].toInt(); + region->originalWidth = entry[3].toInt(); + region->originalHeight = entry[4].toInt(); + } else if (entry[0].equals("rotate")) { + if (entry[1].equals("true")) { + region->degrees = 90; + } else if (!entry[1].equals("false")) { + region->degrees = entry[1].toInt(); + } + } else if (entry[0].equals("index")) { + region->index = entry[1].toInt(); + } else { + region->names.add(String(entry[0].copy())); + for (int i = 0; i < count; i++) { + region->values.add(entry[i + 1].toInt()); + } + } + } + if (region->originalWidth == 0 && region->originalHeight == 0) { + region->originalWidth = region->width; + region->originalHeight = region->height; + } + + region->u = (float) region->x / page->width; + region->v = (float) region->y / page->height; + if (region->degrees == 90) { + region->u2 = (float) (region->x + region->height) / page->width; + region->v2 = (float) (region->y + region->width) / page->height; + } else { + region->u2 = (float) (region->x + region->width) / page->width; + region->v2 = (float) (region->y + region->height) / page->height; + } + _regions.add(region); + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp new file mode 100644 index 0000000..ff3b009 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp @@ -0,0 +1,112 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace spine { + RTTI_IMPL(AtlasAttachmentLoader, AttachmentLoader) + + AtlasAttachmentLoader::AtlasAttachmentLoader(Atlas *atlas) : AttachmentLoader(), _atlas(atlas) { + } + + bool loadSequence(Atlas *atlas, const String &basePath, Sequence *sequence) { + Vector ®ions = sequence->getRegions(); + for (int i = 0, n = (int) regions.size(); i < n; i++) { + String path = sequence->getPath(basePath, i); + regions[i] = atlas->findRegion(path); + if (!regions[i]) return false; + } + return true; + } + + RegionAttachment *AtlasAttachmentLoader::newRegionAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) { + SP_UNUSED(skin); + RegionAttachment *attachment = new (__FILE__, __LINE__) RegionAttachment(name); + if (sequence) { + if (!loadSequence(_atlas, path, sequence)) return NULL; + } else { + AtlasRegion *region = findRegion(path); + if (!region) return NULL; + attachment->setRegion(region); + } + return attachment; + } + + MeshAttachment *AtlasAttachmentLoader::newMeshAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) { + SP_UNUSED(skin); + MeshAttachment *attachment = new (__FILE__, __LINE__) MeshAttachment(name); + + if (sequence) { + if (!loadSequence(_atlas, path, sequence)) return NULL; + } else { + AtlasRegion *region = findRegion(path); + if (!region) return NULL; + attachment->setRegion(region); + } + return attachment; + } + + BoundingBoxAttachment *AtlasAttachmentLoader::newBoundingBoxAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new (__FILE__, __LINE__) BoundingBoxAttachment(name); + } + + PathAttachment *AtlasAttachmentLoader::newPathAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new (__FILE__, __LINE__) PathAttachment(name); + } + + PointAttachment *AtlasAttachmentLoader::newPointAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new (__FILE__, __LINE__) PointAttachment(name); + } + + ClippingAttachment *AtlasAttachmentLoader::newClippingAttachment(Skin &skin, const String &name) { + SP_UNUSED(skin); + return new (__FILE__, __LINE__) ClippingAttachment(name); + } + + void AtlasAttachmentLoader::configureAttachment(Attachment *attachment) { + SP_UNUSED(attachment); + } + + AtlasRegion *AtlasAttachmentLoader::findRegion(const String &name) { + return _atlas->findRegion(name); + } + +}// namespace spine diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Attachment.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Attachment.cpp new file mode 100644 index 0000000..e46122a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Attachment.cpp @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(Attachment) + +Attachment::Attachment(const String &name) : _name(name), _refCount(0) { + assert(_name.length() > 0); +} + +Attachment::~Attachment() { +} + +const String &Attachment::getName() const { + return _name; +} + +int Attachment::getRefCount() { + return _refCount; +} + +void Attachment::reference() { + _refCount++; +} + +void Attachment::dereference() { + _refCount--; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp new file mode 100644 index 0000000..87f1007 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp @@ -0,0 +1,48 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(AttachmentLoader) + +AttachmentLoader::AttachmentLoader() { +} + +AttachmentLoader::~AttachmentLoader() { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp new file mode 100644 index 0000000..f439cd3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(AttachmentTimeline, Timeline) + +AttachmentTimeline::AttachmentTimeline(size_t frameCount, int slotIndex) : Timeline(frameCount, 1), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Attachment << 32) | slotIndex}; + setPropertyIds(ids, 1); + + _attachmentNames.ensureCapacity(frameCount); + for (size_t i = 0; i < frameCount; ++i) { + _attachmentNames.add(String()); + } +} + +AttachmentTimeline::~AttachmentTimeline() {} + +void AttachmentTimeline::setAttachment(Skeleton &skeleton, Slot &slot, String *attachmentName) { + slot.setAttachment(attachmentName == NULL || attachmentName->isEmpty() ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName)); +} + +void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(alpha); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (direction == MixDirection_Out) { + if (blend == MixBlend_Setup) setAttachment(skeleton, *slot, &slot->_data._attachmentName); + return; + } + + if (time < _frames[0]) { + // Time is before first frame. + if (blend == MixBlend_Setup || blend == MixBlend_First) { + setAttachment(skeleton, *slot, &slot->_data._attachmentName); + } + return; + } + + if (time < _frames[0]) { + if (blend == MixBlend_Setup || blend == MixBlend_First) + setAttachment(skeleton, *slot, &slot->_data._attachmentName); + return; + } + + setAttachment(skeleton, *slot, &_attachmentNames[Animation::search(_frames, time)]); +} + +void AttachmentTimeline::setFrame(int frame, float time, const String &attachmentName) { + _frames[frame] = time; + _attachmentNames[frame] = attachmentName; +} + +Vector &AttachmentTimeline::getAttachmentNames() { + return _attachmentNames; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Bone.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Bone.cpp new file mode 100644 index 0000000..9a78078 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -0,0 +1,595 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL(Bone, Updatable) + +bool Bone::yDown = false; + +void Bone::setYDown(bool inValue) { + yDown = inValue; +} + +bool Bone::isYDown() { + return yDown; +} + +Bone::Bone(BoneData &data, Skeleton &skeleton, Bone *parent) : Updatable(), + _data(data), + _skeleton(skeleton), + _parent(parent), + _x(0), + _y(0), + _rotation(0), + _scaleX(0), + _scaleY(0), + _shearX(0), + _shearY(0), + _ax(0), + _ay(0), + _arotation(0), + _ascaleX(0), + _ascaleY(0), + _ashearX(0), + _ashearY(0), + _a(1), + _b(0), + _worldX(0), + _c(0), + _d(1), + _worldY(0), + _sorted(false), + _active(false), + _inherit(Inherit_Normal) { + setToSetupPose(); +} + +void Bone::update(Physics) { + updateWorldTransform(_ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY); +} + +void Bone::updateWorldTransform() { + updateWorldTransform(_x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY); +} + +void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { + float pa, pb, pc, pd; + Bone *parent = _parent; + + _ax = x; + _ay = y; + _arotation = rotation; + _ascaleX = scaleX; + _ascaleY = scaleY; + _ashearX = shearX; + _ashearY = shearY; + + if (!parent) { /* Root bone. */ + Skeleton &skeleton = this->_skeleton; + float sx = skeleton.getScaleX(); + float sy = skeleton.getScaleY(); + float rx = (rotation + shearX) * MathUtil::Deg_Rad; + float ry = (rotation + 90 + shearY) * MathUtil::Deg_Rad; + _a = MathUtil::cos(rx) * scaleX * sx; + _b = MathUtil::cos(ry) * scaleY * sx; + _c = MathUtil::sin(rx) * scaleX * sy; + _d = MathUtil::sin(ry) * scaleY * sy; + _worldX = x * sx + _skeleton.getX(); + _worldY = y * sy + _skeleton.getY(); + return; + } + + pa = parent->_a; + pb = parent->_b; + pc = parent->_c; + pd = parent->_d; + + _worldX = pa * x + pb * y + parent->_worldX; + _worldY = pc * x + pd * y + parent->_worldY; + + switch (_inherit) { + case Inherit_Normal: { + float rx = (rotation + shearX) * MathUtil::Deg_Rad; + float ry = (rotation + 90 + shearY) * MathUtil::Deg_Rad; + float la = MathUtil::cos(rx) * scaleX; + float lb = MathUtil::cos(ry) * scaleY; + float lc = MathUtil::sin(rx) * scaleX; + float ld = MathUtil::sin(ry) * scaleY; + _a = pa * la + pb * lc; + _b = pa * lb + pb * ld; + _c = pc * la + pd * lc; + _d = pc * lb + pd * ld; + return; + } + case Inherit_OnlyTranslation: { + float rx = (rotation + shearX) * MathUtil::Deg_Rad; + float ry = (rotation + 90 + shearY) * MathUtil::Deg_Rad; + _a = MathUtil::cos(rx) * scaleX; + _b = MathUtil::cos(ry) * scaleY; + _c = MathUtil::sin(rx) * scaleX; + _d = MathUtil::sin(ry) * scaleY; + break; + } + case Inherit_NoRotationOrReflection: { + float s = pa * pa + pc * pc; + float prx; + if (s > 0.0001f) { + s = MathUtil::abs(pa * pd - pb * pc) / s; + pa /= _skeleton.getScaleX(); + pc /= _skeleton.getScaleY(); + pb = pc * s; + pd = pa * s; + prx = MathUtil::atan2Deg(pc, pa); + } else { + pa = 0; + pc = 0; + prx = 90 - MathUtil::atan2Deg(pd, pb); + } + float rx = (rotation + shearX - prx) * MathUtil::Deg_Rad; + float ry = (rotation + shearY - prx + 90) * MathUtil::Deg_Rad; + float la = MathUtil::cos(rx) * scaleX; + float lb = MathUtil::cos(ry) * scaleY; + float lc = MathUtil::sin(rx) * scaleX; + float ld = MathUtil::sin(ry) * scaleY; + _a = pa * la - pb * lc; + _b = pa * lb - pb * ld; + _c = pc * la + pd * lc; + _d = pc * lb + pd * ld; + break; + } + case Inherit_NoScale: + case Inherit_NoScaleOrReflection: { + rotation *= MathUtil::Deg_Rad; + float cosine = MathUtil::cos(rotation); + float sine = MathUtil::sin(rotation); + float za = (pa * cosine + pb * sine) / _skeleton.getScaleX(); + float zc = (pc * cosine + pd * sine) / _skeleton.getScaleY(); + float s = MathUtil::sqrt(za * za + zc * zc); + if (s > 0.00001f) s = 1 / s; + za *= s; + zc *= s; + s = MathUtil::sqrt(za * za + zc * zc); + if (_inherit == Inherit_NoScale && + (pa * pd - pb * pc < 0) != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0)) + s = -s; + rotation = MathUtil::Pi / 2 + MathUtil::atan2(zc, za); + float zb = MathUtil::cos(rotation) * s; + float zd = MathUtil::sin(rotation) * s; + shearX *= MathUtil::Deg_Rad; + shearY = (90 + shearY) * MathUtil::Deg_Rad; + float la = MathUtil::cos(shearX) * scaleX; + float lb = MathUtil::cos(shearY) * scaleY; + float lc = MathUtil::sin(shearX) * scaleX; + float ld = MathUtil::sin(shearY) * scaleY; + _a = za * la + zb * lc; + _b = za * lb + zb * ld; + _c = zc * la + zd * lc; + _d = zc * lb + zd * ld; + } + } + _a *= _skeleton.getScaleX(); + _b *= _skeleton.getScaleX(); + _c *= _skeleton.getScaleY(); + _d *= _skeleton.getScaleY(); +} + +void Bone::setToSetupPose() { + BoneData &data = _data; + _x = data.getX(); + _y = data.getY(); + _rotation = data.getRotation(); + _scaleX = data.getScaleX(); + _scaleY = data.getScaleY(); + _shearX = data.getShearX(); + _shearY = data.getShearY(); + _inherit = data.getInherit(); +} + +void Bone::worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY) { + float a = _a; + float b = _b; + float c = _c; + float d = _d; + + float invDet = 1 / (a * d - b * c); + float x = worldX - _worldX; + float y = worldY - _worldY; + + outLocalX = (x * d * invDet - y * b * invDet); + outLocalY = (y * a * invDet - x * c * invDet); +} + +void Bone::worldToParent(float worldX, float worldY, float &outParentX, float &outParentY) { + if (!_parent) { + outParentX = worldX; + outParentY = worldY; + } else { + _parent->worldToLocal(worldX, worldY, outParentX, outParentY); + } +} + +void Bone::localToWorld(float localX, float localY, float &outWorldX, float &outWorldY) { + outWorldX = localX * _a + localY * _b + _worldX; + outWorldY = localX * _c + localY * _d + _worldY; +} + +void Bone::parentToWorld(float worldX, float worldY, float &outX, float &outY) { + if (!_parent) { + outX = worldX; + outY = worldY; + } else { + _parent->localToWorld(worldX, worldY, outX, outY); + } +} + +float Bone::worldToLocalRotation(float worldRotation) { + worldRotation *= MathUtil::Deg_Rad; + float sine = MathUtil::sin(worldRotation), cosine = MathUtil::cos(worldRotation); + return MathUtil::atan2Deg(_a * sine - _c * cosine, _d * cosine - _b * sine) + _rotation - _shearX; +} + +float Bone::localToWorldRotation(float localRotation) { + localRotation = (localRotation - _rotation - _shearX) * MathUtil::Deg_Rad; + float sine = MathUtil::sin(localRotation), cosine = MathUtil::cos(localRotation); + return MathUtil::atan2Deg(cosine * _c + sine * _d, cosine * _a + sine * _b); +} + +void Bone::rotateWorld(float degrees) { + degrees *= MathUtil::Deg_Rad; + float sine = MathUtil::sin(degrees), cosine = MathUtil::cos(degrees); + float ra = _a, rb = _b; + _a = cosine * ra - sine * _c; + _b = cosine * rb - sine * _d; + _c = sine * ra + cosine * _c; + _d = sine * rb + cosine * _d; +} + +float Bone::getWorldToLocalRotationX() { + Bone *parent = _parent; + if (!parent) { + return _arotation; + } + + float pa = parent->_a; + float pb = parent->_b; + float pc = parent->_c; + float pd = parent->_d; + float a = _a; + float c = _c; + + return MathUtil::atan2(pa * c - pc * a, pd * a - pb * c) * MathUtil::Rad_Deg; +} + +float Bone::getWorldToLocalRotationY() { + Bone *parent = _parent; + if (!parent) { + return _arotation; + } + + float pa = parent->_a; + float pb = parent->_b; + float pc = parent->_c; + float pd = parent->_d; + float b = _b; + float d = _d; + + return MathUtil::atan2(pa * d - pc * b, pd * b - pb * d) * MathUtil::Rad_Deg; +} + +BoneData &Bone::getData() { + return _data; +} + +Skeleton &Bone::getSkeleton() { + return _skeleton; +} + +Bone *Bone::getParent() { + return _parent; +} + +Vector &Bone::getChildren() { + return _children; +} + +float Bone::getX() { + return _x; +} + +void Bone::setX(float inValue) { + _x = inValue; +} + +float Bone::getY() { + return _y; +} + +void Bone::setY(float inValue) { + _y = inValue; +} + +float Bone::getRotation() { + return _rotation; +} + +void Bone::setRotation(float inValue) { + _rotation = inValue; +} + +float Bone::getScaleX() { + return _scaleX; +} + +void Bone::setScaleX(float inValue) { + _scaleX = inValue; +} + +float Bone::getScaleY() { + return _scaleY; +} + +void Bone::setScaleY(float inValue) { + _scaleY = inValue; +} + +float Bone::getShearX() { + return _shearX; +} + +void Bone::setShearX(float inValue) { + _shearX = inValue; +} + +float Bone::getShearY() { + return _shearY; +} + +void Bone::setShearY(float inValue) { + _shearY = inValue; +} + +float Bone::getAppliedRotation() { + return _arotation; +} + +void Bone::setAppliedRotation(float inValue) { + _arotation = inValue; +} + +float Bone::getAX() { + return _ax; +} + +void Bone::setAX(float inValue) { + _ax = inValue; +} + +float Bone::getAY() { + return _ay; +} + +void Bone::setAY(float inValue) { + _ay = inValue; +} + +float Bone::getAScaleX() { + return _ascaleX; +} + +void Bone::setAScaleX(float inValue) { + _ascaleX = inValue; +} + +float Bone::getAScaleY() { + return _ascaleY; +} + +void Bone::setAScaleY(float inValue) { + _ascaleY = inValue; +} + +float Bone::getAShearX() { + return _ashearX; +} + +void Bone::setAShearX(float inValue) { + _ashearX = inValue; +} + +float Bone::getAShearY() { + return _ashearY; +} + +void Bone::setAShearY(float inValue) { + _ashearY = inValue; +} + +float Bone::getA() { + return _a; +} + +void Bone::setA(float inValue) { + _a = inValue; +} + +float Bone::getB() { + return _b; +} + +void Bone::setB(float inValue) { + _b = inValue; +} + +float Bone::getC() { + return _c; +} + +void Bone::setC(float inValue) { + _c = inValue; +} + +float Bone::getD() { + return _d; +} + +void Bone::setD(float inValue) { + _d = inValue; +} + +float Bone::getWorldX() { + return _worldX; +} + +void Bone::setWorldX(float inValue) { + _worldX = inValue; +} + +float Bone::getWorldY() { + return _worldY; +} + +void Bone::setWorldY(float inValue) { + _worldY = inValue; +} + +float Bone::getWorldRotationX() { + return MathUtil::atan2Deg(_c, _a); +} + +float Bone::getWorldRotationY() { + return MathUtil::atan2Deg(_d, _b); +} + +float Bone::getWorldScaleX() { + return MathUtil::sqrt(_a * _a + _c * _c); +} + +float Bone::getWorldScaleY() { + return MathUtil::sqrt(_b * _b + _d * _d); +} + +void Bone::updateAppliedTransform() { + Bone *parent = _parent; + if (!parent) { + _ax = _worldX - _skeleton.getX(); + _ay = _worldY - _skeleton.getY(); + _arotation = MathUtil::atan2Deg(_c, _a); + _ascaleX = MathUtil::sqrt(_a * _a + _c * _c); + _ascaleY = MathUtil::sqrt(_b * _b + _d * _d); + _ashearX = 0; + _ashearY = MathUtil::atan2Deg(_a * _b + _c * _d, _a * _d - _b * _c); + } + float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d; + float pid = 1 / (pa * pd - pb * pc); + float ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid; + float dx = _worldX - parent->_worldX, dy = _worldY - parent->_worldY; + _ax = (dx * ia - dy * ib); + _ay = (dy * id - dx * ic); + + float ra, rb, rc, rd; + if (_inherit == Inherit_OnlyTranslation) { + ra = _a; + rb = _b; + rc = _c; + rd = _d; + } else { + switch (_inherit) { + case Inherit_NoRotationOrReflection: { + float s = MathUtil::abs(pa * pd - pb * pc) / (pa * pa + pc * pc); + float sa = pa / _skeleton.getScaleX(); + float sc = pc / _skeleton.getScaleY(); + pb = -sc * s * _skeleton.getScaleX(); + pd = sa * s * _skeleton.getScaleY(); + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + break; + } + case Inherit_NoScale: + case Inherit_NoScaleOrReflection: { + float r = _rotation * MathUtil::Deg_Rad; + float cos = MathUtil::cos(r), sin = MathUtil::sin(r); + pa = (pa * cos + pb * sin) / _skeleton.getScaleX(); + pc = (pc * cos + pd * sin) / _skeleton.getScaleY(); + float s = MathUtil::sqrt(pa * pa + pc * pc); + if (s > 0.00001) s = 1 / s; + pa *= s; + pc *= s; + s = MathUtil::sqrt(pa * pa + pc * pc); + if (_inherit == Inherit_NoScale && + pid < 0 != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0)) + s = -s; + r = MathUtil::Pi / 2 + MathUtil::atan2(pc, pa); + pb = MathUtil::cos(r) * s; + pd = MathUtil::sin(r) * s; + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + ic = pc * pid; + id = pa * pid; + break; + } + case Inherit_Normal: + case Inherit_OnlyTranslation: + break; + } + ra = ia * _a - ib * _c; + rb = ia * _b - ib * _d; + rc = id * _c - ic * _a; + rd = id * _d - ic * _b; + } + + _ashearX = 0; + _ascaleX = MathUtil::sqrt(ra * ra + rc * rc); + if (_ascaleX > 0.0001f) { + float det = ra * rd - rb * rc; + _ascaleY = det / _ascaleX; + _ashearY = -MathUtil::atan2Deg(ra * rb + rc * rd, det); + _arotation = MathUtil::atan2Deg(rc, ra); + } else { + _ascaleX = 0; + _ascaleY = MathUtil::sqrt(rb * rb + rd * rd); + _ashearY = 0; + _arotation = 90 - MathUtil::atan2Deg(rd, rb); + } +} + +bool Bone::isActive() { + return _active; +} + +void Bone::setActive(bool inValue) { + _active = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/BoneData.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/BoneData.cpp new file mode 100644 index 0000000..31ab264 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/BoneData.cpp @@ -0,0 +1,166 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +BoneData::BoneData(int index, const String &name, BoneData *parent) : _index(index), + _name(name), + _parent(parent), + _length(0), + _x(0), + _y(0), + _rotation(0), + _scaleX(1), + _scaleY(1), + _shearX(0), + _shearY(0), + _inherit(Inherit_Normal), + _skinRequired(false), + _color(), + _icon(), + _visible(true) { + assert(index >= 0); + assert(_name.length() > 0); +} + +int BoneData::getIndex() { + return _index; +} + +const String &BoneData::getName() { + return _name; +} + +BoneData *BoneData::getParent() { + return _parent; +} + +float BoneData::getLength() { + return _length; +} + +void BoneData::setLength(float inValue) { + _length = inValue; +} + +float BoneData::getX() { + return _x; +} + +void BoneData::setX(float inValue) { + _x = inValue; +} + +float BoneData::getY() { + return _y; +} + +void BoneData::setY(float inValue) { + _y = inValue; +} + +float BoneData::getRotation() { + return _rotation; +} + +void BoneData::setRotation(float inValue) { + _rotation = inValue; +} + +float BoneData::getScaleX() { + return _scaleX; +} + +void BoneData::setScaleX(float inValue) { + _scaleX = inValue; +} + +float BoneData::getScaleY() { + return _scaleY; +} + +void BoneData::setScaleY(float inValue) { + _scaleY = inValue; +} + +float BoneData::getShearX() { + return _shearX; +} + +void BoneData::setShearX(float inValue) { + _shearX = inValue; +} + +float BoneData::getShearY() { + return _shearY; +} + +void BoneData::setShearY(float inValue) { + _shearY = inValue; +} + +Inherit BoneData::getInherit() { + return _inherit; +} + +void BoneData::setInherit(Inherit inValue) { + _inherit = inValue; +} + +bool BoneData::isSkinRequired() { + return _skinRequired; +} + +void BoneData::setSkinRequired(bool inValue) { + _skinRequired = inValue; +} + +Color &BoneData::getColor() { + return _color; +} + +const String &BoneData::getIcon() { + return _icon; +} + +void BoneData::setIcon(const String &icon) { + this->_icon = icon; +} + +bool BoneData::isVisible() { + return _visible; +} + +void BoneData::setVisible(bool inValue) { + this->_visible = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp new file mode 100644 index 0000000..5ede2c5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp @@ -0,0 +1,47 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL(BoundingBoxAttachment, VertexAttachment) + +BoundingBoxAttachment::BoundingBoxAttachment(const String &name) : VertexAttachment(name), _color() { +} + +Color &BoundingBoxAttachment::getColor() { + return _color; +} + +Attachment *BoundingBoxAttachment::copy() { + BoundingBoxAttachment *copy = new (__FILE__, __LINE__) BoundingBoxAttachment(getName()); + copyTo(copy); + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp new file mode 100644 index 0000000..90f5c14 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp @@ -0,0 +1,58 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +RTTI_IMPL(ClippingAttachment, VertexAttachment) + +ClippingAttachment::ClippingAttachment(const String &name) : VertexAttachment(name), _endSlot(NULL), _color() { +} + +SlotData *ClippingAttachment::getEndSlot() { + return _endSlot; +} + +void ClippingAttachment::setEndSlot(SlotData *inValue) { + _endSlot = inValue; +} + +Color &ClippingAttachment::getColor() { + return _color; +} + +Attachment *ClippingAttachment::copy() { + ClippingAttachment *copy = new (__FILE__, __LINE__) ClippingAttachment(getName()); + copyTo(copy); + copy->_endSlot = _endSlot; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp new file mode 100644 index 0000000..6eacd3e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -0,0 +1,488 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(RGBATimeline, CurveTimeline) + +RGBATimeline::RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount, + RGBATimeline::ENTRIES, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, + ((PropertyId) Property_Alpha << 32) | slotIndex}; + setPropertyIds(ids, 2); +} + +RGBATimeline::~RGBATimeline() { +} + +void RGBATimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) { + Color &color = slot->_color, &setup = slot->_data._color; + switch (blend) { + case MixBlend_Setup: + color.set(setup); + return; + case MixBlend_First: + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, + (setup.a - color.a) * alpha); + default: { + } + } + return; + } + + float r = 0, g = 0, b = 0, a = 0; + int i = Animation::search(_frames, time, RGBATimeline::ENTRIES); + int curveType = (int) _curves[i / RGBATimeline::ENTRIES]; + switch (curveType) { + case RGBATimeline::LINEAR: { + float before = _frames[i]; + r = _frames[i + RGBATimeline::R]; + g = _frames[i + RGBATimeline::G]; + b = _frames[i + RGBATimeline::B]; + a = _frames[i + RGBATimeline::A]; + float t = (time - before) / (_frames[i + RGBATimeline::ENTRIES] - before); + r += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::R] - r) * t; + g += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::G] - g) * t; + b += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::B] - b) * t; + a += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::A] - a) * t; + break; + } + case RGBATimeline::STEPPED: { + r = _frames[i + RGBATimeline::R]; + g = _frames[i + RGBATimeline::G]; + b = _frames[i + RGBATimeline::B]; + a = _frames[i + RGBATimeline::A]; + break; + } + default: { + r = getBezierValue(time, i, RGBATimeline::R, curveType - RGBATimeline::BEZIER); + g = getBezierValue(time, i, RGBATimeline::G, + curveType + RGBATimeline::BEZIER_SIZE - RGBATimeline::BEZIER); + b = getBezierValue(time, i, RGBATimeline::B, + curveType + RGBATimeline::BEZIER_SIZE * 2 - RGBATimeline::BEZIER); + a = getBezierValue(time, i, RGBATimeline::A, + curveType + RGBATimeline::BEZIER_SIZE * 3 - RGBATimeline::BEZIER); + } + } + Color &color = slot->_color; + if (alpha == 1) + color.set(r, g, b, a); + else { + if (blend == MixBlend_Setup) color.set(slot->_data._color); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } +} + +void RGBATimeline::setFrame(int frame, float time, float r, float g, float b, float a) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; + _frames[frame + A] = a; +} + +RTTI_IMPL(RGBTimeline, CurveTimeline) + +RGBTimeline::RGBTimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount, + RGBTimeline::ENTRIES, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex}; + setPropertyIds(ids, 1); +} + +RGBTimeline::~RGBTimeline() { +} + +void RGBTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) { + Color &color = slot->_color, &setup = slot->_data._color; + switch (blend) { + case MixBlend_Setup: + color.set(setup); + return; + case MixBlend_First: + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, + (setup.a - color.a) * alpha); + default: { + } + } + return; + } + + float r = 0, g = 0, b = 0; + int i = Animation::search(_frames, time, RGBTimeline::ENTRIES); + int curveType = (int) _curves[i / RGBTimeline::ENTRIES]; + switch (curveType) { + case RGBTimeline::LINEAR: { + float before = _frames[i]; + r = _frames[i + RGBTimeline::R]; + g = _frames[i + RGBTimeline::G]; + b = _frames[i + RGBTimeline::B]; + float t = (time - before) / (_frames[i + RGBTimeline::ENTRIES] - before); + r += (_frames[i + RGBTimeline::ENTRIES + RGBTimeline::R] - r) * t; + g += (_frames[i + RGBTimeline::ENTRIES + RGBTimeline::G] - g) * t; + b += (_frames[i + RGBTimeline::ENTRIES + RGBTimeline::B] - b) * t; + break; + } + case RGBTimeline::STEPPED: { + r = _frames[i + RGBTimeline::R]; + g = _frames[i + RGBTimeline::G]; + b = _frames[i + RGBTimeline::B]; + break; + } + default: { + r = getBezierValue(time, i, RGBTimeline::R, curveType - RGBTimeline::BEZIER); + g = getBezierValue(time, i, RGBTimeline::G, + curveType + RGBTimeline::BEZIER_SIZE - RGBTimeline::BEZIER); + b = getBezierValue(time, i, RGBTimeline::B, + curveType + RGBTimeline::BEZIER_SIZE * 2 - RGBTimeline::BEZIER); + } + } + Color &color = slot->_color; + if (alpha == 1) + color.set(r, g, b); + else { + Color &setup = slot->_data._color; + if (blend == MixBlend_Setup) color.set(setup.r, setup.g, setup.b); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha); + } +} + +void RGBTimeline::setFrame(int frame, float time, float r, float g, float b) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; +} + +RTTI_IMPL(AlphaTimeline, CurveTimeline1) + +AlphaTimeline::AlphaTimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline1(frameCount, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Alpha << 32) | slotIndex}; + setPropertyIds(ids, 1); +} + +AlphaTimeline::~AlphaTimeline() { +} + +void AlphaTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) {// Time is before first frame. + Color &color = slot->_color, &setup = slot->_data._color; + switch (blend) { + case MixBlend_Setup: + color.a = setup.a; + return; + case MixBlend_First: + color.a += (setup.a - color.a) * alpha; + default: { + } + } + return; + } + + float a = getCurveValue(time); + if (alpha == 1) + slot->_color.a = a; + else { + if (blend == MixBlend_Setup) slot->_color.a = slot->_data._color.a; + slot->_color.a += (a - slot->_color.a) * alpha; + } +} + +RTTI_IMPL(RGBA2Timeline, CurveTimeline) + +RGBA2Timeline::RGBA2Timeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount, + RGBA2Timeline::ENTRIES, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, + ((PropertyId) Property_Alpha << 32) | slotIndex, + ((PropertyId) Property_Rgb2 << 32) | slotIndex}; + setPropertyIds(ids, 3); +} + +RGBA2Timeline::~RGBA2Timeline() { +} + +void RGBA2Timeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) { + Color &light = slot->_color, &dark = slot->_darkColor, &setupLight = slot->_data._color, &setupDark = slot->_data._darkColor; + switch (blend) { + case MixBlend_Setup: + light.set(setupLight); + dark.set(setupDark.r, setupDark.g, setupDark.b); + return; + case MixBlend_First: + light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, + (setupLight.b - light.b) * alpha, + (setupLight.a - light.a) * alpha); + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + default: { + } + } + return; + } + + float r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + int i = Animation::search(_frames, time, RGBA2Timeline::ENTRIES); + int curveType = (int) _curves[i / RGBA2Timeline::ENTRIES]; + switch (curveType) { + case RGBA2Timeline::LINEAR: { + float before = _frames[i]; + r = _frames[i + RGBA2Timeline::R]; + g = _frames[i + RGBA2Timeline::G]; + b = _frames[i + RGBA2Timeline::B]; + a = _frames[i + RGBA2Timeline::A]; + r2 = _frames[i + RGBA2Timeline::R2]; + g2 = _frames[i + RGBA2Timeline::G2]; + b2 = _frames[i + RGBA2Timeline::B2]; + float t = (time - before) / (_frames[i + RGBA2Timeline::ENTRIES] - before); + r += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::R] - r) * t; + g += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::G] - g) * t; + b += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::B] - b) * t; + a += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::A] - a) * t; + r2 += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::R2] - r2) * t; + g2 += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::G2] - g2) * t; + b2 += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::B2] - b2) * t; + break; + } + case RGBA2Timeline::STEPPED: { + r = _frames[i + RGBA2Timeline::R]; + g = _frames[i + RGBA2Timeline::G]; + b = _frames[i + RGBA2Timeline::B]; + a = _frames[i + RGBA2Timeline::A]; + r2 = _frames[i + RGBA2Timeline::R2]; + g2 = _frames[i + RGBA2Timeline::G2]; + b2 = _frames[i + RGBA2Timeline::B2]; + break; + } + default: { + r = getBezierValue(time, i, RGBA2Timeline::R, curveType - RGBA2Timeline::BEZIER); + g = getBezierValue(time, i, RGBA2Timeline::G, + curveType + RGBA2Timeline::BEZIER_SIZE - RGBA2Timeline::BEZIER); + b = getBezierValue(time, i, RGBA2Timeline::B, + curveType + RGBA2Timeline::BEZIER_SIZE * 2 - RGBA2Timeline::BEZIER); + a = getBezierValue(time, i, RGBA2Timeline::A, + curveType + RGBA2Timeline::BEZIER_SIZE * 3 - RGBA2Timeline::BEZIER); + r2 = getBezierValue(time, i, RGBA2Timeline::R2, + curveType + RGBA2Timeline::BEZIER_SIZE * 4 - RGBA2Timeline::BEZIER); + g2 = getBezierValue(time, i, RGBA2Timeline::G2, + curveType + RGBA2Timeline::BEZIER_SIZE * 5 - RGBA2Timeline::BEZIER); + b2 = getBezierValue(time, i, RGBA2Timeline::B2, + curveType + RGBA2Timeline::BEZIER_SIZE * 6 - RGBA2Timeline::BEZIER); + } + } + Color &light = slot->_color, &dark = slot->_darkColor; + if (alpha == 1) { + light.set(r, g, b, a); + dark.set(r2, g2, b2); + } else { + if (blend == MixBlend_Setup) { + light.set(slot->_data._color); + dark.set(slot->_data._darkColor); + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } +} + +void RGBA2Timeline::setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; + _frames[frame + A] = a; + _frames[frame + R2] = r2; + _frames[frame + G2] = g2; + _frames[frame + B2] = b2; +} + +RTTI_IMPL(RGB2Timeline, CurveTimeline) + +RGB2Timeline::RGB2Timeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount, + RGB2Timeline::ENTRIES, + bezierCount), + _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, + ((PropertyId) Property_Rgb2 << 32) | slotIndex}; + setPropertyIds(ids, 2); +} + +RGB2Timeline::~RGB2Timeline() { +} + +void RGB2Timeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + if (time < _frames[0]) { + Color &light = slot->_color, &dark = slot->_darkColor, &setupLight = slot->_data._color, &setupDark = slot->_data._darkColor; + switch (blend) { + case MixBlend_Setup: + light.set(setupLight.r, setupLight.g, setupLight.b); + dark.set(setupDark.r, setupDark.g, setupDark.b); + return; + case MixBlend_First: + light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, + (setupLight.b - light.b) * alpha); + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + default: { + } + } + return; + } + + float r = 0, g = 0, b = 0, r2 = 0, g2 = 0, b2 = 0; + int i = Animation::search(_frames, time, RGB2Timeline::ENTRIES); + int curveType = (int) _curves[i / RGB2Timeline::ENTRIES]; + switch (curveType) { + case RGB2Timeline::LINEAR: { + float before = _frames[i]; + r = _frames[i + RGB2Timeline::R]; + g = _frames[i + RGB2Timeline::G]; + b = _frames[i + RGB2Timeline::B]; + r2 = _frames[i + RGB2Timeline::R2]; + g2 = _frames[i + RGB2Timeline::G2]; + b2 = _frames[i + RGB2Timeline::B2]; + float t = (time - before) / (_frames[i + RGB2Timeline::ENTRIES] - before); + r += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::R] - r) * t; + g += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::G] - g) * t; + b += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::B] - b) * t; + r2 += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::R2] - r2) * t; + g2 += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::G2] - g2) * t; + b2 += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::B2] - b2) * t; + break; + } + case RGB2Timeline::STEPPED: { + r = _frames[i + RGB2Timeline::R]; + g = _frames[i + RGB2Timeline::G]; + b = _frames[i + RGB2Timeline::B]; + r2 = _frames[i + RGB2Timeline::R2]; + g2 = _frames[i + RGB2Timeline::G2]; + b2 = _frames[i + RGB2Timeline::B2]; + break; + } + default: { + r = getBezierValue(time, i, RGB2Timeline::R, curveType - RGB2Timeline::BEZIER); + g = getBezierValue(time, i, RGB2Timeline::G, curveType + RGB2Timeline::BEZIER_SIZE - RGB2Timeline::BEZIER); + b = getBezierValue(time, i, RGB2Timeline::B, curveType + RGB2Timeline::BEZIER_SIZE * 2 - RGB2Timeline::BEZIER); + r2 = getBezierValue(time, i, RGB2Timeline::R2, curveType + RGB2Timeline::BEZIER_SIZE * 3 - RGB2Timeline::BEZIER); + g2 = getBezierValue(time, i, RGB2Timeline::G2, curveType + RGB2Timeline::BEZIER_SIZE * 4 - RGB2Timeline::BEZIER); + b2 = getBezierValue(time, i, RGB2Timeline::B2, curveType + RGB2Timeline::BEZIER_SIZE * 5 - RGB2Timeline::BEZIER); + } + } + Color &light = slot->_color, &dark = slot->_darkColor; + if (alpha == 1) { + light.set(r, g, b); + dark.set(r2, g2, b2); + } else { + if (blend == MixBlend_Setup) { + light.set(slot->_data._color.r, slot->_data._color.g, slot->_data._color.b); + dark.set(slot->_data._darkColor); + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha); + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } +} + +void RGB2Timeline::setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; + _frames[frame + R2] = r2; + _frames[frame + G2] = g2; + _frames[frame + B2] = b2; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp new file mode 100644 index 0000000..1be0b2d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp @@ -0,0 +1,60 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(ConstraintData) + +ConstraintData::ConstraintData(const String &name) : _name(name), _order(0), _skinRequired(false) { +} + +ConstraintData::~ConstraintData() { +} + +const String &ConstraintData::getName() { + return _name; +} + +size_t ConstraintData::getOrder() { + return _order; +} + +void ConstraintData::setOrder(size_t inValue) { + _order = inValue; +} + +bool ConstraintData::isSkinRequired() { + return _skinRequired; +} + +void ConstraintData::setSkinRequired(bool inValue) { + _skinRequired = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp new file mode 100644 index 0000000..530dabd --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp @@ -0,0 +1,252 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +RTTI_IMPL(CurveTimeline, Timeline) + +CurveTimeline::CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount) : Timeline(frameCount, + frameEntries) { + _curves.setSize(frameCount + bezierCount * BEZIER_SIZE, 0); + _curves[frameCount - 1] = STEPPED; +} + +CurveTimeline::~CurveTimeline() { +} + +void CurveTimeline::setLinear(size_t frame) { + _curves[frame] = LINEAR; +} + +void CurveTimeline::setStepped(size_t frame) { + _curves[frame] = STEPPED; +} + +void CurveTimeline::setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, + float cx2, float cy2, float time2, float value2) { + size_t i = getFrameCount() + bezier * BEZIER_SIZE; + if (value == 0) _curves[frame] = BEZIER + i; + float tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03; + float dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 0.006; + float ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + float dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667; + float x = time1 + dx, y = value1 + dy; + for (size_t n = i + BEZIER_SIZE; i < n; i += 2) { + _curves[i] = x; + _curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } +} + +float CurveTimeline::getBezierValue(float time, size_t frameIndex, size_t valueOffset, size_t i) { + if (_curves[i] > time) { + float x = _frames[frameIndex], y = _frames[frameIndex + valueOffset]; + return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y); + } + size_t n = i + BEZIER_SIZE; + for (i += 2; i < n; i += 2) { + if (_curves[i] >= time) { + float x = _curves[i - 2], y = _curves[i - 1]; + return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y); + } + } + frameIndex += getFrameEntries(); + float x = _curves[n - 2], y = _curves[n - 1]; + return y + (time - x) / (_frames[frameIndex] - x) * (_frames[frameIndex + valueOffset] - y); +} + +Vector &CurveTimeline::getCurves() { + return _curves; +} + +RTTI_IMPL(CurveTimeline1, CurveTimeline) + +CurveTimeline1::CurveTimeline1(size_t frameCount, size_t bezierCount) : CurveTimeline(frameCount, + CurveTimeline1::ENTRIES, + bezierCount) { +} + +CurveTimeline1::~CurveTimeline1() { +} + +void CurveTimeline1::setFrame(size_t frame, float time, float value) { + frame <<= 1; + _frames[frame] = time; + _frames[frame + CurveTimeline1::VALUE] = value; +} + +float CurveTimeline1::getCurveValue(float time) { + int i = (int) _frames.size() - 2; + for (int ii = 2; ii <= i; ii += 2) { + if (_frames[ii] > time) { + i = ii - 2; + break; + } + } + + int curveType = (int) _curves[i >> 1]; + switch (curveType) { + case CurveTimeline::LINEAR: { + float before = _frames[i], value = _frames[i + CurveTimeline1::VALUE]; + return value + (time - before) / (_frames[i + CurveTimeline1::ENTRIES] - before) * + (_frames[i + CurveTimeline1::ENTRIES + CurveTimeline1::VALUE] - value); + } + case CurveTimeline::STEPPED: + return _frames[i + CurveTimeline1::VALUE]; + } + return getBezierValue(time, i, CurveTimeline1::VALUE, curveType - CurveTimeline1::BEZIER); +} + +float CurveTimeline1::getRelativeValue(float time, float alpha, MixBlend blend, float current, float setup) { + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + return setup; + case MixBlend_First: + return current + (setup - current) * alpha; + default: + return current; + } + } + float value = getCurveValue(time); + switch (blend) { + case MixBlend_Setup: + return setup + value * alpha; + case MixBlend_First: + case MixBlend_Replace: + value += setup - current; + break; + case MixBlend_Add: + break; + } + return current + value * alpha; +} + +float CurveTimeline1::getAbsoluteValue(float time, float alpha, MixBlend blend, float current, float setup) { + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + return setup; + case MixBlend_First: + return current + (setup - current) * alpha; + default: + return current; + } + } + float value = getCurveValue(time); + if (blend == MixBlend_Setup) return setup + (value - setup) * alpha; + return current + (value - current) * alpha; +} + +float CurveTimeline1::getAbsoluteValue(float time, float alpha, MixBlend blend, float current, float setup, float value) { + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + return setup; + case MixBlend_First: + return current + (setup - current) * alpha; + default: + return current; + } + } + if (blend == MixBlend_Setup) return setup + (value - setup) * alpha; + return current + (value - current) * alpha; +} + +float CurveTimeline1::getScaleValue(float time, float alpha, MixBlend blend, MixDirection direction, float current, + float setup) { + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + return setup; + case MixBlend_First: + return current + (setup - current) * alpha; + default: + return current; + } + } + float value = getCurveValue(time) * setup; + if (alpha == 1) { + if (blend == MixBlend_Add) return current + value - setup; + return value; + } + // Mixing out uses sign of setup or current pose, else use sign of key. + if (direction == MixDirection_Out) { + switch (blend) { + case MixBlend_Setup: + return setup + (MathUtil::abs(value) * MathUtil::sign(setup) - setup) * alpha; + case MixBlend_First: + case MixBlend_Replace: + return current + (MathUtil::abs(value) * MathUtil::sign(current) - current) * alpha; + default: + break; + } + } else { + float s; + switch (blend) { + case MixBlend_Setup: + s = MathUtil::abs(setup) * MathUtil::sign(value); + return s + (value - s) * alpha; + case MixBlend_First: + case MixBlend_Replace: + s = MathUtil::abs(current) * MathUtil::sign(value); + return s + (value - s) * alpha; + default: + break; + } + } + return current + (value - setup) * alpha; +} + + +RTTI_IMPL(CurveTimeline2, CurveTimeline) + +CurveTimeline2::CurveTimeline2(size_t frameCount, size_t bezierCount) : CurveTimeline(frameCount, + CurveTimeline2::ENTRIES, + bezierCount) { +} + +CurveTimeline2::~CurveTimeline2() { +} + +void CurveTimeline2::setFrame(size_t frame, float time, float value1, float value2) { + frame *= CurveTimeline2::ENTRIES; + _frames[frame] = time; + _frames[frame + CurveTimeline2::VALUE1] = value1; + _frames[frame + CurveTimeline2::VALUE2] = value2; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp new file mode 100644 index 0000000..d7d5aa1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -0,0 +1,328 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(DeformTimeline, CurveTimeline) + +DeformTimeline::DeformTimeline(size_t frameCount, size_t bezierCount, int slotIndex, VertexAttachment *attachment) + : CurveTimeline(frameCount, 1, bezierCount), _slotIndex(slotIndex), _attachment(attachment) { + PropertyId ids[] = {((PropertyId) Property_Deform << 32) | ((slotIndex << 16 | attachment->_id) & 0xffffffff)}; + setPropertyIds(ids, 1); + + _vertices.ensureCapacity(frameCount); + for (size_t i = 0; i < frameCount; ++i) { + Vector vec; + _vertices.add(vec); + } +} + +void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slotP = skeleton._slots[_slotIndex]; + Slot &slot = *slotP; + if (!slot._bone.isActive()) return; + + Attachment *slotAttachment = slot.getAttachment(); + if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) { + return; + } + + VertexAttachment *attachment = static_cast(slotAttachment); + if (attachment->_timelineAttachment != _attachment) { + return; + } + + Vector &deformArray = slot._deform; + if (deformArray.size() == 0) { + blend = MixBlend_Setup; + } + + Vector> &vertices = _vertices; + size_t vertexCount = vertices[0].size(); + + Vector &frames = _frames; + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + deformArray.clear(); + return; + case MixBlend_First: { + if (alpha == 1) { + deformArray.clear(); + return; + } + deformArray.setSize(vertexCount, 0); + Vector &deform = deformArray; + if (attachment->getBones().size() == 0) { + // Unweighted vertex positions. + Vector &setupVertices = attachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) + deform[i] += (setupVertices[i] - deform[i]) * alpha; + } else { + // Weighted deform offsets. + alpha = 1 - alpha; + for (size_t i = 0; i < vertexCount; i++) + deform[i] *= alpha; + } + } + case MixBlend_Replace: + case MixBlend_Add: { + } + } + return; + } + + deformArray.setSize(vertexCount, 0); + Vector &deform = deformArray; + + if (time >= frames[frames.size() - 1]) {// Time is after last frame. + Vector &lastVertices = vertices[frames.size() - 1]; + if (alpha == 1) { + if (blend == MixBlend_Add) { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, no alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) + deform[i] += lastVertices[i] - setupVertices[i]; + } else { + // Weighted deform offsets, no alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] += lastVertices[i]; + } + } else { + // Vertex positions or deform offsets, no alpha. + memcpy(deform.buffer(), lastVertices.buffer(), vertexCount * sizeof(float)); + } + } else { + switch (blend) { + case MixBlend_Setup: { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, with alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float setup = setupVertices[i]; + deform[i] = setup + (lastVertices[i] - setup) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] = lastVertices[i] * alpha; + } + break; + } + case MixBlend_First: + case MixBlend_Replace: + // Vertex positions or deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] += (lastVertices[i] - deform[i]) * alpha; + break; + case MixBlend_Add: + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, no alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) + deform[i] += (lastVertices[i] - setupVertices[i]) * alpha; + } else { + // Weighted deform offsets, alpha. + for (size_t i = 0; i < vertexCount; i++) + deform[i] += lastVertices[i] * alpha; + } + } + } + return; + } + + // Interpolate between the previous frame and the current frame. + int frame = Animation::search(frames, time); + float percent = getCurvePercent(time, frame); + Vector &prevVertices = vertices[frame]; + Vector &nextVertices = vertices[frame + 1]; + + if (alpha == 1) { + if (blend == MixBlend_Add) { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, no alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i]; + } + } else { + // Weighted deform offsets, no alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += prev + (nextVertices[i] - prev) * percent; + } + } + } else { + // Vertex positions or deform offsets, no alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] = prev + (nextVertices[i] - prev) * percent; + } + } + } else { + switch (blend) { + case MixBlend_Setup: { + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, with alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i], setup = setupVertices[i]; + deform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } + break; + } + case MixBlend_First: + case MixBlend_Replace: + // Vertex positions or deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha; + } + break; + case MixBlend_Add: + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getBones().size() == 0) { + // Unweighted vertex positions, with alpha. + Vector &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (size_t i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + deform[i] += (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } + } + } +} + +void DeformTimeline::setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, + float cx2, float cy2, float time2, float value2) { + SP_UNUSED(value1); + SP_UNUSED(value2); + size_t i = getFrameCount() + bezier * DeformTimeline::BEZIER_SIZE; + if (value == 0) _curves[frame] = DeformTimeline::BEZIER + i; + float tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06; + float dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = (cy1 - cy2 + 0.33333333) * 0.018; + float ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + float dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667; + float x = time1 + dx, y = dy; + for (size_t n = i + DeformTimeline::BEZIER_SIZE; i < n; i += 2) { + _curves[i] = x; + _curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } +} + +float DeformTimeline::getCurvePercent(float time, int frame) { + int i = (int) _curves[frame]; + switch (i) { + case DeformTimeline::LINEAR: { + float x = _frames[frame]; + return (time - x) / (_frames[frame + getFrameEntries()] - x); + } + case DeformTimeline::STEPPED: { + return 0; + } + default: { + } + } + i -= DeformTimeline::BEZIER; + if (_curves[i] > time) { + float x = _frames[frame]; + return _curves[i + 1] * (time - x) / (_curves[i] - x); + } + int n = i + DeformTimeline::BEZIER_SIZE; + for (i += 2; i < n; i += 2) { + if (_curves[i] >= time) { + float x = _curves[i - 2], y = _curves[i - 1]; + return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y); + } + } + float x = _curves[n - 2], y = _curves[n - 1]; + return y + (1 - y) * (time - x) / (_frames[frame + getFrameEntries()] - x); +} + +void DeformTimeline::setFrame(int frame, float time, Vector &vertices) { + _frames[frame] = time; + _vertices[frame].clear(); + _vertices[frame].addAll(vertices); +} + +Vector> &DeformTimeline::getVertices() { + return _vertices; +} + +VertexAttachment *DeformTimeline::getAttachment() { + return _attachment; +} + +void DeformTimeline::setAttachment(VertexAttachment *inValue) { + _attachment = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp new file mode 100644 index 0000000..2708d25 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -0,0 +1,102 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(DrawOrderTimeline, Timeline) + +DrawOrderTimeline::DrawOrderTimeline(size_t frameCount) : Timeline(frameCount, 1) { + PropertyId ids[] = {((PropertyId) Property_DrawOrder << 32)}; + setPropertyIds(ids, 1); + + _drawOrders.ensureCapacity(frameCount); + for (size_t i = 0; i < frameCount; ++i) { + Vector vec; + _drawOrders.add(vec); + } +} + +void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(alpha); + + Vector &drawOrder = skeleton._drawOrder; + Vector &slots = skeleton._slots; + if (direction == MixDirection_Out) { + if (blend == MixBlend_Setup) { + drawOrder.clear(); + drawOrder.ensureCapacity(slots.size()); + for (size_t i = 0, n = slots.size(); i < n; ++i) + drawOrder.add(slots[i]); + } + return; + } + + if (time < _frames[0]) { + if (blend == MixBlend_Setup || blend == MixBlend_First) { + drawOrder.clear(); + drawOrder.ensureCapacity(slots.size()); + for (size_t i = 0, n = slots.size(); i < n; ++i) + drawOrder.add(slots[i]); + } + return; + } + + Vector &drawOrderToSetupIndex = _drawOrders[Animation::search(_frames, time)]; + if (drawOrderToSetupIndex.size() == 0) { + drawOrder.clear(); + for (size_t i = 0, n = slots.size(); i < n; ++i) + drawOrder.add(slots[i]); + } else { + for (size_t i = 0, n = drawOrderToSetupIndex.size(); i < n; ++i) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } +} + +void DrawOrderTimeline::setFrame(size_t frame, float time, Vector &drawOrder) { + _frames[frame] = time; + _drawOrders[frame].clear(); + _drawOrders[frame].addAll(drawOrder); +} + +Vector> &DrawOrderTimeline::getDrawOrders() { + return _drawOrders; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Event.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Event.cpp new file mode 100644 index 0000000..3086184 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Event.cpp @@ -0,0 +1,90 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +spine::Event::Event(float time, const spine::EventData &data) : _data(data), + _time(time), + _intValue(0), + _floatValue(0), + _stringValue(), + _volume(1), + _balance(0) { +} + +const spine::EventData &spine::Event::getData() { + return _data; +} + +float spine::Event::getTime() { + return _time; +} + +int spine::Event::getIntValue() { + return _intValue; +} + +void spine::Event::setIntValue(int inValue) { + _intValue = inValue; +} + +float spine::Event::getFloatValue() { + return _floatValue; +} + +void spine::Event::setFloatValue(float inValue) { + _floatValue = inValue; +} + +const spine::String &spine::Event::getStringValue() { + return _stringValue; +} + +void spine::Event::setStringValue(const spine::String &inValue) { + _stringValue = inValue; +} + + +float spine::Event::getVolume() { + return _volume; +} + +void spine::Event::setVolume(float inValue) { + _volume = inValue; +} + +float spine::Event::getBalance() { + return _balance; +} + +void spine::Event::setBalance(float inValue) { + _balance = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/EventData.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/EventData.cpp new file mode 100644 index 0000000..df72041 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/EventData.cpp @@ -0,0 +1,96 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +spine::EventData::EventData(const spine::String &name) : _name(name), + _intValue(0), + _floatValue(0), + _stringValue(), + _audioPath(), + _volume(1), + _balance(0) { + assert(_name.length() > 0); +} + +/// The name of the event, which is unique within the skeleton. +const spine::String &spine::EventData::getName() const { + return _name; +} + +int spine::EventData::getIntValue() const { + return _intValue; +} + +void spine::EventData::setIntValue(int inValue) { + _intValue = inValue; +} + +float spine::EventData::getFloatValue() const { + return _floatValue; +} + +void spine::EventData::setFloatValue(float inValue) { + _floatValue = inValue; +} + +const spine::String &spine::EventData::getStringValue() const { + return _stringValue; +} + +void spine::EventData::setStringValue(const spine::String &inValue) { + this->_stringValue = inValue; +} + +const spine::String &spine::EventData::getAudioPath() const { + return _audioPath; +} + +void spine::EventData::setAudioPath(const spine::String &inValue) { + _audioPath = inValue; +} + + +float spine::EventData::getVolume() const { + return _volume; +} + +void spine::EventData::setVolume(float inValue) { + _volume = inValue; +} + +float spine::EventData::getBalance() const { + return _balance; +} + +void spine::EventData::setBalance(float inValue) { + _balance = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp new file mode 100644 index 0000000..aa5986f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -0,0 +1,99 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(EventTimeline, Timeline) + +EventTimeline::EventTimeline(size_t frameCount) : Timeline(frameCount, 1) { + PropertyId ids[] = {((PropertyId) Property_Event << 32)}; + setPropertyIds(ids, 1); + _events.setSize(frameCount, NULL); +} + +EventTimeline::~EventTimeline() { + ContainerUtil::cleanUpVectorOfPointers(_events); +} + +void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + if (pEvents == NULL) return; + + Vector &events = *pEvents; + + size_t frameCount = _frames.size(); + + if (lastTime > time) { + // Fire events after last time for looped animations. + apply(skeleton, lastTime, FLT_MAX, pEvents, alpha, blend, direction); + lastTime = -1.0f; + } else if (lastTime >= _frames[frameCount - 1]) { + // Last time is after last i. + return; + } + + if (time < _frames[0]) return;// Time is before first i. + + int i; + if (lastTime < _frames[0]) { + i = 0; + } else { + i = Animation::search(_frames, lastTime) + 1; + float frameTime = _frames[i]; + while (i > 0) { + // Fire multiple events with the same i. + if (_frames[i - 1] != frameTime) break; + i--; + } + } + + for (; (size_t) i < frameCount && time >= _frames[i]; i++) + events.add(_events[i]); +} + +void EventTimeline::setFrame(size_t frame, Event *event) { + _frames[frame] = event->getTime(); + _events[frame] = event; +} + +Vector &EventTimeline::getEvents() { return _events; } diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Extension.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Extension.cpp new file mode 100644 index 0000000..4f47e06 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Extension.cpp @@ -0,0 +1,127 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +#include + +using namespace spine; + +SpineExtension *SpineExtension::_instance = NULL; + +void SpineExtension::setInstance(SpineExtension *inValue) { + assert(inValue); + + _instance = inValue; +} + +SpineExtension *SpineExtension::getInstance() { + if (!_instance) _instance = spine::getDefaultExtension(); + assert(_instance); + + return _instance; +} + +SpineExtension::~SpineExtension() { +} + +SpineExtension::SpineExtension() { +} + +DefaultSpineExtension::~DefaultSpineExtension() { +} + +void *DefaultSpineExtension::_alloc(size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + if (size == 0) + return 0; + void *ptr = ::malloc(size); + return ptr; +} + +void *DefaultSpineExtension::_calloc(size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + if (size == 0) + return 0; + + void *ptr = ::malloc(size); + if (ptr) { + memset(ptr, 0, size); + } + return ptr; +} + +void *DefaultSpineExtension::_realloc(void *ptr, size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + void *mem = NULL; + if (size == 0) + return 0; + if (ptr == NULL) + mem = ::malloc(size); + else + mem = ::realloc(ptr, size); + return mem; +} + +void DefaultSpineExtension::_free(void *mem, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + ::free(mem); +} + +char *DefaultSpineExtension::_readFile(const String &path, int *length) { +#ifndef __EMSCRIPTEN__ + char *data; + FILE *file = fopen(path.buffer(), "rb"); + if (!file) return 0; + + fseek(file, 0, SEEK_END); + *length = (int) ftell(file); + fseek(file, 0, SEEK_SET); + + data = SpineExtension::alloc(*length, __FILE__, __LINE__); + fread(data, 1, *length, file); + fclose(file); + + return data; +#else + return nullptr; +#endif +} + +DefaultSpineExtension::DefaultSpineExtension() : SpineExtension() { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp new file mode 100644 index 0000000..8460901 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -0,0 +1,379 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(IkConstraint, Updatable) + +void IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha) { + Bone *p = bone.getParent(); + float pa = p->_a, pb = p->_b, pc = p->_c, pd = p->_d; + float rotationIK = -bone._ashearX - bone._arotation; + float tx = 0, ty = 0; + + switch (bone._inherit) { + case Inherit_OnlyTranslation: + tx = (targetX - bone._worldX) * MathUtil::sign(bone.getSkeleton().getScaleX()); + ty = (targetY - bone._worldY) * MathUtil::sign(bone.getSkeleton().getScaleY()); + break; + case Inherit_NoRotationOrReflection: { + float s = MathUtil::abs(pa * pd - pb * pc) / MathUtil::max(0.0001f, pa * pa + pc * pc); + float sa = pa / bone._skeleton.getScaleX(); + float sc = pc / bone._skeleton.getScaleY(); + pb = -sc * s * bone._skeleton.getScaleX(); + pd = sa * s * bone._skeleton.getScaleY(); + rotationIK += MathUtil::atan2Deg(sc, sa); + } + default: + float x = targetX - p->_worldX, y = targetY - p->_worldY; + float d = pa * pd - pb * pc; + if (MathUtil::abs(d) <= 0.0001f) { + tx = 0; + ty = 0; + } else { + tx = (x * pd - y * pb) / d - bone._ax; + ty = (y * pa - x * pc) / d - bone._ay; + } + } + rotationIK += MathUtil::atan2Deg(ty, tx); + if (bone._ascaleX < 0) rotationIK += 180; + if (rotationIK > 180) rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + float sx = bone._ascaleX; + float sy = bone._ascaleY; + if (compress || stretch) { + switch (bone._inherit) { + case Inherit_NoScale: + case Inherit_NoScaleOrReflection: + tx = targetX - bone._worldX; + ty = targetY - bone._worldY; + default:; + } + + float b = bone._data.getLength() * sx; + if (b > 0.0001) { + float dd = tx * tx + ty * ty; + if ((compress && dd < b * b) || (stretch && dd > b * b)) { + float s = (MathUtil::sqrt(dd) / b - 1) * alpha + 1; + sx *= s; + if (uniform) sy *= s; + } + } + } + bone.updateWorldTransform(bone._ax, bone._ay, bone._arotation + rotationIK * alpha, sx, sy, bone._ashearX, + bone._ashearY); +} + +void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, bool uniform, + float softness, + float alpha) { + float a, b, c, d; + float px, py, psx, psy, sx, sy; + float cx, cy, csx, cwx, cwy; + int o1, o2, s2, u; + Bone *pp = parent.getParent(); + float tx, ty, dx, dy, dd, l1, l2, a1, a2, r, td, sd, p; + float id, x, y; + if (parent._inherit != Inherit_Normal || child._inherit != Inherit_Normal) return; + px = parent._ax; + py = parent._ay; + psx = parent._ascaleX; + psy = parent._ascaleY; + sx = psx; + sy = psy; + csx = child._ascaleX; + if (psx < 0) { + psx = -psx; + o1 = 180; + s2 = -1; + } else { + o1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + o2 = 180; + } else + o2 = 0; + r = psx - psy; + cx = child._ax; + u = (r < 0 ? -r : r) <= 0.0001f; + if (!u || stretch) { + cy = 0; + cwx = parent._a * cx + parent._worldX; + cwy = parent._c * cx + parent._worldY; + } else { + cy = child._ay; + cwx = parent._a * cx + parent._b * cy + parent._worldX; + cwy = parent._c * cx + parent._d * cy + parent._worldY; + } + a = pp->_a; + b = pp->_b; + c = pp->_c; + d = pp->_d; + id = a * d - b * c; + id = MathUtil::abs(id) <= 0.0001f ? 0 : 1 / id; + x = cwx - pp->_worldX; + y = cwy - pp->_worldY; + dx = (x * d - y * b) * id - px; + dy = (y * a - x * c) * id - py; + l1 = MathUtil::sqrt(dx * dx + dy * dy); + l2 = child._data.getLength() * csx; + if (l1 < 0.0001) { + apply(parent, targetX, targetY, false, stretch, false, alpha); + child.updateWorldTransform(cx, cy, 0, child._ascaleX, child._ascaleY, child._ashearX, child._ashearY); + return; + } + x = targetX - pp->_worldX; + y = targetY - pp->_worldY; + tx = (x * d - y * b) * id - px; + ty = (y * a - x * c) * id - py; + dd = tx * tx + ty * ty; + if (softness != 0) { + softness *= psx * (csx + 1) * 0.5f; + td = MathUtil::sqrt(dd); + sd = td - l1 - l2 * psx + softness; + if (sd > 0) { + p = MathUtil::min(1.0f, sd / (softness * 2)) - 1; + p = (sd - softness * (1 - p * p)) / td; + tx -= p * tx; + ty -= p * ty; + dd = tx * tx + ty * ty; + } + } + if (u) { + float cosine; + l2 *= psx; + cosine = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cosine < -1) { + cosine = -1; + a2 = MathUtil::Pi * bendDir; + } else if (cosine > 1) { + cosine = 1; + a2 = 0; + if (stretch) { + a = (MathUtil::sqrt(dd) / (l1 + l2) - 1) * alpha + 1; + sx *= a; + if (uniform) sy *= a; + } + } else + a2 = MathUtil::acos(cosine) * bendDir; + a = l1 + l2 * cosine; + b = l2 * MathUtil::sin(a2); + a1 = MathUtil::atan2(ty * a - tx * b, tx * a + ty * b); + } else { + a = psx * l2; + b = psy * l2; + float aa = a * a, bb = b * b, ll = l1 * l1, ta = MathUtil::atan2(ty, tx); + float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c0; + if (d >= 0) { + float q = MathUtil::sqrt(d), r0, r1; + if (c1 < 0) q = -q; + q = -(c1 + q) * 0.5f; + r0 = q / c2; + r1 = c0 / q; + r = MathUtil::abs(r0) < MathUtil::abs(r1) ? r0 : r1; + if (dd - r * r >= 0) { + y = MathUtil::sqrt(dd - r * r) * bendDir; + a1 = ta - MathUtil::atan2(y, r); + a2 = MathUtil::atan2(y / psy, (r - l1) / psx); + goto break_outer; + } + } + { + float minAngle = MathUtil::Pi, minX = l1 - a, minDist = minX * minX, minY = 0; + float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c0 = -a * l1 / (aa - bb); + if (c0 >= -1 && c0 <= 1) { + c0 = MathUtil::acos(c0); + x = a * MathUtil::cos(c0) + l1; + y = b * MathUtil::sin(c0); + d = x * x + y * y; + if (d < minDist) { + minAngle = c0; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c0; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) * 0.5f) { + a1 = ta - MathUtil::atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } else { + a1 = ta - MathUtil::atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + } +break_outer : { + float os = MathUtil::atan2(cy, cx) * s2; + a1 = (a1 - os) * MathUtil::Rad_Deg + o1 - parent._arotation; + if (a1 > 180) a1 -= 360; + else if (a1 < -180) + a1 += 360; + parent.updateWorldTransform(px, py, parent._arotation + a1 * alpha, sx, sy, 0, 0); + a2 = ((a2 + os) * MathUtil::Rad_Deg - child._ashearX) * s2 + o2 - child._arotation; + if (a2 > 180) a2 -= 360; + else if (a2 < -180) + a2 += 360; + child.updateWorldTransform(cx, cy, child._arotation + a2 * alpha, child._ascaleX, child._ascaleY, + child._ashearX, child._ashearY); +} +} + +IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Updatable(), + _data(data), + _bendDirection(data.getBendDirection()), + _compress(data.getCompress()), + _stretch(data.getStretch()), + _mix(data.getMix()), + _softness(data.getSoftness()), + _target(skeleton.findBone( + data.getTarget()->getName())), + _active(false) { + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); i++) { + BoneData *boneData = _data.getBones()[i]; + _bones.add(skeleton.findBone(boneData->getName())); + } +} + +void IkConstraint::update(Physics) { + if (_mix == 0) return; + switch (_bones.size()) { + case 1: { + Bone *bone0 = _bones[0]; + apply(*bone0, _target->getWorldX(), _target->getWorldY(), _compress, _stretch, _data._uniform, _mix); + } break; + case 2: { + Bone *bone0 = _bones[0]; + Bone *bone1 = _bones[1]; + apply(*bone0, *bone1, _target->getWorldX(), _target->getWorldY(), _bendDirection, _stretch, _data._uniform, + _softness, + _mix); + } break; + } +} + +int IkConstraint::getOrder() { + return (int) _data.getOrder(); +} + +IkConstraintData &IkConstraint::getData() { + return _data; +} + +Vector &IkConstraint::getBones() { + return _bones; +} + +Bone *IkConstraint::getTarget() { + return _target; +} + +void IkConstraint::setTarget(Bone *inValue) { + _target = inValue; +} + +int IkConstraint::getBendDirection() { + return _bendDirection; +} + +void IkConstraint::setBendDirection(int inValue) { + _bendDirection = inValue; +} + +float IkConstraint::getMix() { + return _mix; +} + +void IkConstraint::setMix(float inValue) { + _mix = inValue; +} + +bool IkConstraint::getStretch() { + return _stretch; +} + +void IkConstraint::setStretch(bool inValue) { + _stretch = inValue; +} + +bool IkConstraint::getCompress() { + return _compress; +} + +void IkConstraint::setCompress(bool inValue) { + _compress = inValue; +} + +bool IkConstraint::isActive() { + return _active; +} + +void IkConstraint::setActive(bool inValue) { + _active = inValue; +} + +float IkConstraint::getSoftness() { + return _softness; +} + +void IkConstraint::setSoftness(float inValue) { + _softness = inValue; +} + +void IkConstraint::setToSetupPose() { + IkConstraintData &data = this->_data; + this->_mix = data._mix; + this->_softness = data._softness; + this->_bendDirection = data._bendDirection; + this->_compress = data._compress; + this->_stretch = data._stretch; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp new file mode 100644 index 0000000..5f232ac --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -0,0 +1,107 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +RTTI_IMPL(IkConstraintData, ConstraintData) + +IkConstraintData::IkConstraintData(const String &name) : ConstraintData(name), + _target(NULL), + _bendDirection(0), + _compress(false), + _stretch(false), + _uniform(false), + _mix(0), + _softness(0) { +} + +Vector &IkConstraintData::getBones() { + return _bones; +} + +BoneData *IkConstraintData::getTarget() { + return _target; +} + +void IkConstraintData::setTarget(BoneData *inValue) { + _target = inValue; +} + +int IkConstraintData::getBendDirection() { + return _bendDirection; +} + +void IkConstraintData::setBendDirection(int inValue) { + _bendDirection = inValue; +} + +float IkConstraintData::getMix() { + return _mix; +} + +void IkConstraintData::setMix(float inValue) { + _mix = inValue; +} + +bool IkConstraintData::getStretch() { + return _stretch; +} + +void IkConstraintData::setStretch(bool inValue) { + _stretch = inValue; +} + +bool IkConstraintData::getCompress() { + return _compress; +} + +void IkConstraintData::setCompress(bool inValue) { + _compress = inValue; +} + + +bool IkConstraintData::getUniform() { + return _uniform; +} + +void IkConstraintData::setUniform(bool inValue) { + _uniform = inValue; +} + +float IkConstraintData::getSoftness() { + return _softness; +} + +void IkConstraintData::setSoftness(float inValue) { + _softness = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp new file mode 100644 index 0000000..8e757f7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -0,0 +1,141 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(IkConstraintTimeline, CurveTimeline) + +IkConstraintTimeline::IkConstraintTimeline(size_t frameCount, size_t bezierCount, int ikConstraintIndex) + : CurveTimeline(frameCount, IkConstraintTimeline::ENTRIES, bezierCount), _constraintIndex(ikConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_IkConstraint << 32) | ikConstraintIndex}; + setPropertyIds(ids, 1); +} + +void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + IkConstraint *constraintP = skeleton._ikConstraints[_constraintIndex]; + IkConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._mix = constraint._data._mix; + constraint._softness = constraint._data._softness; + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + return; + case MixBlend_First: + constraint._mix += (constraint._data._mix - constraint._mix) * alpha; + constraint._softness += (constraint._data._softness - constraint._softness) * alpha; + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + return; + default: + return; + } + } + + float mix = 0, softness = 0; + int i = Animation::search(_frames, time, IkConstraintTimeline::ENTRIES); + int curveType = (int) _curves[i / IkConstraintTimeline::ENTRIES]; + switch (curveType) { + case IkConstraintTimeline::LINEAR: { + float before = _frames[i]; + mix = _frames[i + IkConstraintTimeline::MIX]; + softness = _frames[i + IkConstraintTimeline::SOFTNESS]; + float t = (time - before) / (_frames[i + IkConstraintTimeline::ENTRIES] - before); + mix += (_frames[i + IkConstraintTimeline::ENTRIES + IkConstraintTimeline::MIX] - mix) * t; + softness += (_frames[i + IkConstraintTimeline::ENTRIES + IkConstraintTimeline::SOFTNESS] - softness) * t; + break; + } + case IkConstraintTimeline::STEPPED: { + mix = _frames[i + IkConstraintTimeline::MIX]; + softness = _frames[i + IkConstraintTimeline::SOFTNESS]; + break; + } + default: { + mix = getBezierValue(time, i, IkConstraintTimeline::MIX, curveType - IkConstraintTimeline::BEZIER); + softness = getBezierValue(time, i, IkConstraintTimeline::SOFTNESS, + curveType + IkConstraintTimeline::BEZIER_SIZE - + IkConstraintTimeline::BEZIER); + } + } + + if (blend == MixBlend_Setup) { + constraint._mix = constraint._data._mix + (mix - constraint._data._mix) * alpha; + constraint._softness = constraint._data._softness + (softness - constraint._data._softness) * alpha; + + if (direction == MixDirection_Out) { + constraint._bendDirection = constraint._data._bendDirection; + constraint._compress = constraint._data._compress; + constraint._stretch = constraint._data._stretch; + } else { + constraint._bendDirection = _frames[i + IkConstraintTimeline::BEND_DIRECTION]; + constraint._compress = _frames[i + IkConstraintTimeline::COMPRESS] != 0; + constraint._stretch = _frames[i + IkConstraintTimeline::STRETCH] != 0; + } + } else { + constraint._mix += (mix - constraint._mix) * alpha; + constraint._softness += (softness - constraint._softness) * alpha; + if (direction == MixDirection_In) { + constraint._bendDirection = _frames[i + IkConstraintTimeline::BEND_DIRECTION]; + constraint._compress = _frames[i + IkConstraintTimeline::COMPRESS] != 0; + constraint._stretch = _frames[i + IkConstraintTimeline::STRETCH] != 0; + } + } +} + +void IkConstraintTimeline::setFrame(int frame, float time, float mix, float softness, int bendDirection, bool compress, + bool stretch) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + MIX] = mix; + _frames[frame + SOFTNESS] = softness; + _frames[frame + BEND_DIRECTION] = (float) bendDirection; + _frames[frame + COMPRESS] = compress ? 1 : 0; + _frames[frame + STRETCH] = stretch ? 1 : 0; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/InheritTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/InheritTimeline.cpp new file mode 100644 index 0000000..d8da9e8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/InheritTimeline.cpp @@ -0,0 +1,81 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(InheritTimeline, Timeline) + +InheritTimeline::InheritTimeline(size_t frameCount, int boneIndex) : Timeline(frameCount, ENTRIES), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_Inherit << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +InheritTimeline::~InheritTimeline() { +} + +void InheritTimeline::setFrame(int frame, float time, Inherit inherit) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + INHERIT] = inherit; +} + + +void InheritTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + SP_UNUSED(alpha); + + Bone *bone = skeleton.getBones()[_boneIndex]; + if (!bone->isActive()) return; + + if (direction == MixDirection_Out) { + if (blend == MixBlend_Setup) bone->setInherit(bone->_data.getInherit()); + return; + } + + if (time < _frames[0]) { + if (blend == MixBlend_Setup || blend == MixBlend_First) bone->_inherit = bone->_data.getInherit(); + return; + } + int idx = Animation::search(_frames, time, ENTRIES) + INHERIT; + bone->_inherit = static_cast(_frames[idx]); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Json.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Json.cpp new file mode 100644 index 0000000..89d1cc9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Json.cpp @@ -0,0 +1,559 @@ +/* +Copyright (c) 2009, Dave Gamble +Copyright (c) 2013, Esoteric Software + +Permission is hereby granted, dispose of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* Json */ +/* JSON parser in CPP, from json.c in the spine-c runtime */ + +#ifndef _DEFAULT_SOURCE +/* Bring strings.h definitions into string.h, where appropriate */ +#define _DEFAULT_SOURCE +#endif + +#ifndef _BSD_SOURCE +/* Bring strings.h definitions into string.h, where appropriate */ +#define _BSD_SOURCE +#endif + +#include +#include +#include + +#include +#include + +using namespace spine; + +const int Json::JSON_FALSE = 0; +const int Json::JSON_TRUE = 1; +const int Json::JSON_NULL = 2; +const int Json::JSON_NUMBER = 3; +const int Json::JSON_STRING = 4; +const int Json::JSON_ARRAY = 5; +const int Json::JSON_OBJECT = 6; + +const char *Json::_error = NULL; + +Json *Json::getItem(Json *object, const char *string) { + Json *c = object->_child; + while (c && json_strcasecmp(c->_name, string)) { + c = c->_next; + } + return c; +} + +Json *Json::getItem(Json *object, int childIndex) { + Json *current = object->_child; + while (current != NULL && childIndex > 0) { + childIndex--; + current = current->_next; + } + return current; +} + +const char *Json::getString(Json *object, const char *name, const char *defaultValue) { + object = getItem(object, name); + if (object) { + return object->_valueString; + } + + return defaultValue; +} + +float Json::getFloat(Json *value, const char *name, float defaultValue) { + value = getItem(value, name); + return value ? value->_valueFloat : defaultValue; +} + +int Json::getInt(Json *value, const char *name, int defaultValue) { + value = getItem(value, name); + return value ? value->_valueInt : defaultValue; +} + +bool Json::getBoolean(spine::Json *value, const char *name, bool defaultValue) { + value = getItem(value, name); + if (value) { + if (value->_valueString) return strcmp(value->_valueString, "true") == 0; + if (value->_type == JSON_NULL) return false; + if (value->_type == JSON_NUMBER) return value->_valueFloat != 0; + if (value->_type == JSON_FALSE) return false; + if (value->_type == JSON_TRUE) return true; + return defaultValue; + } else { + return defaultValue; + } +} + +const char *Json::getError() { + return _error; +} + +Json::Json(const char *value) : _next(NULL), +#if SPINE_JSON_HAVE_PREV + _prev(NULL), +#endif + _child(NULL), + _type(0), + _size(0), + _valueString(NULL), + _valueInt(0), + _valueFloat(0), + _name(NULL) { + if (value) { + value = parseValue(this, skip(value)); + + assert(value); + } +} + +Json::~Json() { + spine::Json *curr = NULL; + spine::Json *next = _child; + do { + curr = next; + if (curr) { + next = curr->_next; + } + delete curr; + } while (next); + + if (_valueString) { + SpineExtension::free(_valueString, __FILE__, __LINE__); + } + + if (_name) { + SpineExtension::free(_name, __FILE__, __LINE__); + } +} + +const char *Json::skip(const char *inValue) { + if (!inValue) { + /* must propagate NULL since it's often called in skip(f(...)) form */ + return NULL; + } + + while (*inValue && (unsigned char) *inValue <= 32) { + inValue++; + } + + return inValue; +} + +const char *Json::parseValue(Json *item, const char *value) { + /* Referenced by constructor, parseArray(), and parseObject(). */ + /* Always called with the result of skip(). */ +#ifdef SPINE_JSON_DEBUG /* Checked at entry to graph, constructor, and after every parse call. */ + if (!value) { + /* Fail on null. */ + return NULL; + } +#endif + + switch (*value) { + case 'n': { + if (!strncmp(value + 1, "ull", 3)) { + item->_type = JSON_NULL; + return value + 4; + } + break; + } + case 'f': { + if (!strncmp(value + 1, "alse", 4)) { + item->_type = JSON_FALSE; + /* calloc prevents us needing item->_type = JSON_FALSE or valueInt = 0 here */ + return value + 5; + } + break; + } + case 't': { + if (!strncmp(value + 1, "rue", 3)) { + item->_type = JSON_TRUE; + item->_valueInt = 1; + return value + 4; + } + break; + } + case '\"': + return parseString(item, value); + case '[': + return parseArray(item, value); + case '{': + return parseObject(item, value); + case '-': /* fallthrough */ + case '0': /* fallthrough */ + case '1': /* fallthrough */ + case '2': /* fallthrough */ + case '3': /* fallthrough */ + case '4': /* fallthrough */ + case '5': /* fallthrough */ + case '6': /* fallthrough */ + case '7': /* fallthrough */ + case '8': /* fallthrough */ + case '9': + return parseNumber(item, value); + default: + break; + } + + _error = value; + return NULL; /* failure. */ +} + +static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC}; + +const char *Json::parseString(Json *item, const char *str) { + const char *ptr = str + 1; + char *ptr2; + char *out; + int len = 0; + unsigned uc, uc2; + if (*str != '\"') { + /* TODO: don't need this check when called from parseValue, but do need from parseObject */ + _error = str; + return 0; + } /* not a string! */ + + while (*ptr != '\"' && *ptr && ++len) { + if (*ptr++ == '\\') { + ptr++; /* Skip escaped quotes. */ + } + } + + out = SpineExtension::alloc(len + 1, __FILE__, __LINE__); /* The length needed for the string, roughly. */ + if (!out) { + return 0; + } + + ptr = str + 1; + ptr2 = out; + while (*ptr != '\"' && *ptr) { + if (*ptr != '\\') { + *ptr2++ = *ptr++; + } else { + ptr++; + switch (*ptr) { + case 'b': + *ptr2++ = '\b'; + break; + case 'f': + *ptr2++ = '\f'; + break; + case 'n': + *ptr2++ = '\n'; + break; + case 'r': + *ptr2++ = '\r'; + break; + case 't': + *ptr2++ = '\t'; + break; + case 'u': { + /* transcode utf16 to utf8. */ + sscanf(ptr + 1, "%4x", &uc); + ptr += 4; /* get the unicode char. */ + + if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) { + break; /* check for invalid. */ + } + + /* TODO provide an option to ignore surrogates, use unicode replacement character? */ + if (uc >= 0xD800 && uc <= 0xDBFF) /* UTF16 surrogate pairs. */ { + if (ptr[1] != '\\' || ptr[2] != 'u') { + break; /* missing second-half of surrogate. */ + } + sscanf(ptr + 3, "%4x", &uc2); + ptr += 6; + if (uc2 < 0xDC00 || uc2 > 0xDFFF) { + break; /* invalid second-half of surrogate. */ + } + uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF)); + } + + len = 4; + if (uc < 0x80) { + len = 1; + } else if (uc < 0x800) { + len = 2; + } else if (uc < 0x10000) { + len = 3; + } + ptr2 += len; + + switch (len) { + case 4: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 3: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 2: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 1: + *--ptr2 = (uc | firstByteMark[len]); + } + ptr2 += len; + break; + } + default: + *ptr2++ = *ptr; + break; + } + ptr++; + } + } + + *ptr2 = 0; + + if (*ptr == '\"') { + ptr++; /* TODO error handling if not \" or \0 ? */ + } + + item->_valueString = out; + item->_type = JSON_STRING; + + return ptr; +} + +const char *Json::parseNumber(Json *item, const char *num) { + double result = 0.0; + int negative = 0; + char *ptr = (char *) num; + + if (*ptr == '-') { + negative = -1; + ++ptr; + } + + while (*ptr >= '0' && *ptr <= '9') { + result = result * 10.0 + (*ptr - '0'); + ++ptr; + } + + if (*ptr == '.') { + double fraction = 0.0; + int n = 0; + ++ptr; + + while (*ptr >= '0' && *ptr <= '9') { + fraction = (fraction * 10.0) + (*ptr - '0'); + ++ptr; + ++n; + } + result += fraction / pow(10.0, n); + } + + if (negative) { + result = -result; + } + + if (*ptr == 'e' || *ptr == 'E') { + double exponent = 0; + int expNegative = 0; + ++ptr; + + if (*ptr == '-') { + expNegative = -1; + ++ptr; + } else if (*ptr == '+') { + ++ptr; + } + + while (*ptr >= '0' && *ptr <= '9') { + exponent = (exponent * 10.0) + (*ptr - '0'); + ++ptr; + } + + if (expNegative) { + result = result / pow(10, exponent); + } else { + result = result * pow(10, exponent); + } + } + + if (ptr != num) { + /* Parse success, number found. */ + item->_valueFloat = (float) result; + item->_valueInt = (int) result; + item->_type = JSON_NUMBER; + return ptr; + } else { + /* Parse failure, _error is set. */ + _error = num; + return NULL; + } +} + +const char *Json::parseArray(Json *item, const char *value) { + Json *child; + +#ifdef SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */ + if (*value != '[') { + ep = value; + return 0; + } /* not an array! */ +#endif + + item->_type = JSON_ARRAY; + value = skip(value + 1); + if (*value == ']') { + return value + 1; /* empty array. */ + } + + item->_child = child = new (__FILE__, __LINE__) Json(NULL); + if (!item->_child) { + return NULL; /* memory fail */ + } + + value = skip(parseValue(child, skip(value))); /* skip any spacing, get the value. */ + + if (!value) { + return NULL; + } + + item->_size = 1; + + while (*value == ',') { + Json *new_item = new (__FILE__, __LINE__) Json(NULL); + if (!new_item) { + return NULL; /* memory fail */ + } + child->_next = new_item; +#if SPINE_JSON_HAVE_PREV + new_item->prev = child; +#endif + child = new_item; + value = skip(parseValue(child, skip(value + 1))); + if (!value) { + return NULL; /* parse fail */ + } + item->_size++; + } + + if (*value == ']') { + return value + 1; /* end of array */ + } + + _error = value; + + return NULL; /* malformed. */ +} + +/* Build an object from the text. */ +const char *Json::parseObject(Json *item, const char *value) { + Json *child; + +#ifdef SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */ + if (*value != '{') { + ep = value; + return 0; + } /* not an object! */ +#endif + + item->_type = JSON_OBJECT; + value = skip(value + 1); + if (*value == '}') { + return value + 1; /* empty array. */ + } + + item->_child = child = new (__FILE__, __LINE__) Json(NULL); + if (!item->_child) { + return NULL; + } + value = skip(parseString(child, skip(value))); + if (!value) { + return NULL; + } + child->_name = child->_valueString; + child->_valueString = 0; + if (*value != ':') { + _error = value; + return NULL; + } /* fail! */ + + value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return NULL; + } + + item->_size = 1; + + while (*value == ',') { + Json *new_item = new (__FILE__, __LINE__) Json(NULL); + if (!new_item) { + return NULL; /* memory fail */ + } + child->_next = new_item; +#if SPINE_JSON_HAVE_PREV + new_item->prev = child; +#endif + child = new_item; + value = skip(parseString(child, skip(value + 1))); + if (!value) { + return NULL; + } + child->_name = child->_valueString; + child->_valueString = 0; + if (*value != ':') { + _error = value; + return NULL; + } /* fail! */ + + value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return NULL; + } + item->_size++; + } + + if (*value == '}') { + return value + 1; /* end of array */ + } + + _error = value; + + return NULL; /* malformed. */ +} + +int Json::json_strcasecmp(const char *s1, const char *s2) { + /* TODO we may be able to elide these NULL checks if we can prove + * the graph and input (only callsite is Json_getItem) should not have NULLs + */ + if (s1 && s2) { +#if defined(_WIN32) + return _stricmp(s1, s2); +#else + return strcasecmp(s1, s2); +#endif + } else { + if (s1 < s2) { + return -1; /* s1 is null, s2 is not */ + } else if (s1 == s2) { + return 0; /* both are null */ + } else { + return 1; /* s2 is nul s1 is not */ + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp new file mode 100644 index 0000000..db10ced --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp @@ -0,0 +1,52 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +LinkedMesh::LinkedMesh(MeshAttachment *mesh, const int skinIndex, size_t slotIndex, const String &parent, + bool inheritTimeline) : _mesh(mesh), + _skinIndex(skinIndex), + _skin(""), + _slotIndex(slotIndex), + _parent(parent), + _inheritTimeline(inheritTimeline) { +} + +LinkedMesh::LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, + bool inheritTimeline) : _mesh(mesh), + _skinIndex(-1), + _skin(skin), + _slotIndex(slotIndex), + _parent(parent), + _inheritTimeline(inheritTimeline) { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Log.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Log.cpp new file mode 100644 index 0000000..063141e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Log.cpp @@ -0,0 +1,123 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +void spine::spDebug_printSkeletonData(SkeletonData *skeletonData) { + int i, n; + spDebug_printBoneDatas(skeletonData->getBones()); + + for (i = 0, n = (int) skeletonData->getAnimations().size(); i < n; i++) { + spDebug_printAnimation(skeletonData->getAnimations()[i]); + } +} + +void _spDebug_printTimelineBase(Timeline *timeline) { + printf(" Timeline %s:\n", timeline->getRTTI().getClassName()); + printf(" frame count: %zu\n", timeline->getFrameCount()); + printf(" frame entries: %zu\n", timeline->getFrameEntries()); + printf(" frames: "); + spDebug_printFloats(timeline->getFrames()); + printf("\n"); +} + +void _spDebug_printCurveTimeline(CurveTimeline *timeline) { + _spDebug_printTimelineBase(timeline); + printf(" curves: "); + spDebug_printFloats(timeline->getCurves()); + printf("\n"); +} + +void spine::spDebug_printTimeline(Timeline *timeline) { + if (timeline->getRTTI().instanceOf(CurveTimeline::rtti)) + _spDebug_printCurveTimeline(static_cast(timeline)); + else + _spDebug_printTimelineBase(timeline); +} + +void spine::spDebug_printAnimation(Animation *animation) { + int i, n; + printf("Animation %s: %zu timelines\n", animation->getName().buffer(), animation->getTimelines().size()); + + for (i = 0, n = (int) animation->getTimelines().size(); i < n; i++) { + Timeline *timeline = animation->getTimelines()[i]; + spDebug_printTimeline(timeline); + } +} + +void spine::spDebug_printBoneDatas(Vector &boneDatas) { + int i, n; + for (i = 0, n = (int) boneDatas.size(); i < n; i++) { + spDebug_printBoneData(boneDatas[i]); + } +} + +void spine::spDebug_printBoneData(BoneData *boneData) { + printf("Bone data %s: %f, %f, %f, %f, %f, %f %f\n", boneData->getName().buffer(), boneData->getRotation(), + boneData->getScaleX(), boneData->getScaleY(), boneData->getX(), boneData->getY(), boneData->getShearX(), + boneData->getShearY()); +} + +void spine::spDebug_printSkeleton(Skeleton *skeleton) { + spDebug_printBones(skeleton->getBones()); +} + +void spine::spDebug_printBones(Vector &bones) { + int i, n; + for (i = 0, n = (int) bones.size(); i < n; i++) { + spDebug_printBone(bones[i]); + } +} + +void spine::spDebug_printBone(Bone *bone) { + printf("Bone %s: %f, %f, %f, %f, %f, %f\n", bone->getData().getName().buffer(), bone->getA(), bone->getB(), + bone->getC(), bone->getD(), bone->getWorldX(), bone->getWorldY()); +} + +void spine::spDebug_printFloats(float *values, int numFloats) { + int i; + printf("(%i) [", numFloats); + for (i = 0; i < numFloats; i++) { + printf("%f, ", values[i]); + } + printf("]"); +} + +void spine::spDebug_printFloats(Vector &values) { + int i, n; + printf("(%zu) [", values.size()); + for (i = 0, n = (int) values.size(); i < n; i++) { + printf("%f, ", values[i]); + } + printf("]"); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/MathUtil.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/MathUtil.cpp new file mode 100644 index 0000000..44f48fa --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/MathUtil.cpp @@ -0,0 +1,132 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include + +// Required for division by 0 in _isNaN on MSVC +#ifdef _MSC_VER +#pragma warning(disable : 4723) +#endif + +using namespace spine; + +const float MathUtil::Pi = 3.1415926535897932385f; +const float MathUtil::Pi_2 = 3.1415926535897932385f * 2; +const float MathUtil::InvPi_2 = 1 / MathUtil::Pi_2; +const float MathUtil::Deg_Rad = (3.1415926535897932385f / 180.0f); +const float MathUtil::Rad_Deg = (180.0f / 3.1415926535897932385f); + +float MathUtil::abs(float v) { + return ((v) < 0 ? -(v) : (v)); +} + +float MathUtil::sign(float v) { + return ((v) < 0 ? -1.0f : (v) > 0 ? 1.0f + : 0.0f); +} + +float MathUtil::clamp(float x, float min, float max) { + return ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))); +} + +float MathUtil::fmod(float a, float b) { + return (float) ::fmod(a, b); +} + +/// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 +/// degrees), largest error of 0.00488 radians (0.2796 degrees). +float MathUtil::atan2(float y, float x) { + return (float) ::atan2(y, x); +} + +float MathUtil::atan2Deg(float y, float x) { + return MathUtil::atan2(y, x) * MathUtil::Rad_Deg; +} + +/// Returns the cosine in radians from a lookup table. +float MathUtil::cos(float radians) { + return (float) ::cos(radians); +} + +/// Returns the sine in radians from a lookup table. +float MathUtil::sin(float radians) { + return (float) ::sin(radians); +} + +float MathUtil::sqrt(float v) { + return (float) ::sqrt(v); +} + +float MathUtil::acos(float v) { + return (float) ::acos(v); +} + +/// Returns the sine in radians from a lookup table. +float MathUtil::sinDeg(float degrees) { + return (float) ::sin(degrees * MathUtil::Deg_Rad); +} + +/// Returns the cosine in radians from a lookup table. +float MathUtil::cosDeg(float degrees) { + return (float) ::cos(degrees * MathUtil::Deg_Rad); +} + +bool MathUtil::isNan(float v) { + return std::isnan(v); +} + +float MathUtil::quietNan() { + return std::nan(""); +} + +float MathUtil::random() { + return ::rand() / (float) RAND_MAX; +} + +float MathUtil::randomTriangular(float min, float max) { + return randomTriangular(min, max, (min + max) * 0.5f); +} + +float MathUtil::randomTriangular(float min, float max, float mode) { + float u = random(); + float d = max - min; + if (u <= (mode - min) / d) return min + sqrt(u * d * (mode - min)); + return max - sqrt((1 - u) * d * (max - mode)); +} + +float MathUtil::pow(float a, float b) { + return (float) ::pow(a, b); +} + +float MathUtil::ceil(float v) { + return ::ceil(v); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp new file mode 100644 index 0000000..e40bc6e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp @@ -0,0 +1,241 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL(MeshAttachment, VertexAttachment) + +MeshAttachment::MeshAttachment(const String &name) : VertexAttachment(name), + _parentMesh(NULL), + _path(), + _color(1, 1, 1, 1), + _hullLength(0), + _width(0), + _height(0), + _region(NULL), + _sequence(NULL) {} + +MeshAttachment::~MeshAttachment() { + if (_sequence) delete _sequence; +} + +void MeshAttachment::updateRegion() { + if (_uvs.size() != _regionUVs.size()) { + _uvs.setSize(_regionUVs.size(), 0); + } + + if (_region == nullptr) { + return; + } + + int i = 0, n = (int) _regionUVs.size(); + float u = _region->u, v = _region->v; + float width = 0, height = 0; + switch (_region->degrees) { + case 90: { + float textureWidth = _region->height / (_region->u2 - _region->u); + float textureHeight = _region->width / (_region->v2 - _region->v); + u -= (_region->originalHeight - _region->offsetY - _region->height) / textureWidth; + v -= (_region->originalWidth - _region->offsetX - _region->width) / textureHeight; + width = _region->originalHeight / textureWidth; + height = _region->originalWidth / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + _regionUVs[i + 1] * width; + _uvs[i + 1] = v + (1 - _regionUVs[i]) * height; + } + return; + } + case 180: { + float textureWidth = _region->width / (_region->u2 - _region->u); + float textureHeight = _region->height / (_region->v2 - _region->v); + u -= (_region->originalWidth - _region->offsetX - _region->width) / textureWidth; + v -= _region->offsetY / textureHeight; + width = _region->originalWidth / textureWidth; + height = _region->originalHeight / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + (1 - _regionUVs[i]) * width; + _uvs[i + 1] = v + (1 - _regionUVs[i + 1]) * height; + } + return; + } + case 270: { + float textureHeight = _region->height / (_region->v2 - _region->v); + float textureWidth = _region->width / (_region->u2 - _region->u); + u -= _region->offsetY / textureWidth; + v -= _region->offsetX / textureHeight; + width = _region->originalHeight / textureWidth; + height = _region->originalWidth / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + (1 - _regionUVs[i + 1]) * width; + _uvs[i + 1] = v + _regionUVs[i] * height; + } + return; + } + default: { + float textureWidth = _region->width / (_region->u2 - _region->u); + float textureHeight = _region->height / (_region->v2 - _region->v); + u -= _region->offsetX / textureWidth; + v -= (_region->originalHeight - _region->offsetY - _region->height) / textureHeight; + width = _region->originalWidth / textureWidth; + height = _region->originalHeight / textureHeight; + for (i = 0; i < n; i += 2) { + _uvs[i] = u + _regionUVs[i] * width; + _uvs[i + 1] = v + _regionUVs[i + 1] * height; + } + } + } +} + +int MeshAttachment::getHullLength() { + return _hullLength; +} + +void MeshAttachment::setHullLength(int inValue) { + _hullLength = inValue; +} + +Vector &MeshAttachment::getRegionUVs() { + return _regionUVs; +} + +Vector &MeshAttachment::getUVs() { + return _uvs; +} + +Vector &MeshAttachment::getTriangles() { + return _triangles; +} + +const String &MeshAttachment::getPath() { + return _path; +} + +void MeshAttachment::setPath(const String &inValue) { + _path = inValue; +} + +TextureRegion *MeshAttachment::getRegion() { + return _region; +} + +void MeshAttachment::setRegion(TextureRegion *region) { + _region = region; +} + +Sequence *MeshAttachment::getSequence() { + return _sequence; +} + +void MeshAttachment::setSequence(Sequence *sequence) { + _sequence = sequence; +} + +MeshAttachment *MeshAttachment::getParentMesh() { + return _parentMesh; +} + +void MeshAttachment::setParentMesh(MeshAttachment *inValue) { + _parentMesh = inValue; + if (inValue != NULL) { + _bones.clearAndAddAll(inValue->_bones); + _vertices.clearAndAddAll(inValue->_vertices); + _worldVerticesLength = inValue->_worldVerticesLength; + _regionUVs.clearAndAddAll(inValue->_regionUVs); + _triangles.clearAndAddAll(inValue->_triangles); + _hullLength = inValue->_hullLength; + _edges.clearAndAddAll(inValue->_edges); + _width = inValue->_width; + _height = inValue->_height; + } +} + +Vector &MeshAttachment::getEdges() { + return _edges; +} + +float MeshAttachment::getWidth() { + return _width; +} + +void MeshAttachment::setWidth(float inValue) { + _width = inValue; +} + +float MeshAttachment::getHeight() { + return _height; +} + +void MeshAttachment::setHeight(float inValue) { + _height = inValue; +} + +spine::Color &MeshAttachment::getColor() { + return _color; +} + +Attachment *MeshAttachment::copy() { + if (_parentMesh) return newLinkedMesh(); + + MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName()); + copy->setRegion(_region); + copy->setSequence(_sequence != NULL ? _sequence->copy() : NULL); + copy->_path = _path; + copy->_color.set(_color); + + copyTo(copy); + copy->_regionUVs.clearAndAddAll(_regionUVs); + copy->_uvs.clearAndAddAll(_uvs); + copy->_triangles.clearAndAddAll(_triangles); + copy->_hullLength = _hullLength; + + // Nonessential. + copy->_edges.clearAndAddAll(copy->_edges); + copy->_width = _width; + copy->_height = _height; + return copy; +} + +MeshAttachment *MeshAttachment::newLinkedMesh() { + MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName()); + copy->setRegion(_region); + copy->_path = _path; + copy->_color.set(_color); + copy->_timelineAttachment = this->_timelineAttachment; + copy->setParentMesh(_parentMesh ? _parentMesh : this); + if (copy->_region) copy->updateRegion(); + return copy; +} + +void MeshAttachment::computeWorldVertices(Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride) { + if (_sequence) _sequence->apply(&slot, this); + VertexAttachment::computeWorldVertices(slot, start, count, worldVertices, offset, stride); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp new file mode 100644 index 0000000..5a5670f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp @@ -0,0 +1,71 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL(PathAttachment, VertexAttachment) + +PathAttachment::PathAttachment(const String &name) : VertexAttachment(name), _closed(false), _constantSpeed(false), + _color() { +} + +Vector &PathAttachment::getLengths() { + return _lengths; +} + +bool PathAttachment::isClosed() { + return _closed; +} + +void PathAttachment::setClosed(bool inValue) { + _closed = inValue; +} + +bool PathAttachment::isConstantSpeed() { + return _constantSpeed; +} + +void PathAttachment::setConstantSpeed(bool inValue) { + _constantSpeed = inValue; +} + +Color &PathAttachment::getColor() { + return _color; +} + +Attachment *PathAttachment::copy() { + PathAttachment *copy = new (__FILE__, __LINE__) PathAttachment(getName()); + copyTo(copy); + copy->_lengths.clearAndAddAll(_lengths); + copy->_closed = _closed; + copy->_constantSpeed = _constantSpeed; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp new file mode 100644 index 0000000..fb8683e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -0,0 +1,588 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraint, Updatable) + +const float PathConstraint::EPSILON = 0.00001f; +const int PathConstraint::NONE = -1; +const int PathConstraint::BEFORE = -2; +const int PathConstraint::AFTER = -3; + +PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : Updatable(), + _data(data), + _target(skeleton.findSlot( + data.getTarget()->getName())), + _position(data.getPosition()), + _spacing(data.getSpacing()), + _mixRotate(data.getMixRotate()), + _mixX(data.getMixX()), + _mixY(data.getMixY()), + _active(false) { + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); i++) { + BoneData *boneData = _data.getBones()[i]; + _bones.add(skeleton.findBone(boneData->getName())); + } + + _segments.setSize(10, 0); +} + +void PathConstraint::update(Physics) { + Attachment *baseAttachment = _target->getAttachment(); + if (baseAttachment == NULL || !baseAttachment->getRTTI().instanceOf(PathAttachment::rtti)) { + return; + } + PathAttachment *attachment = static_cast(baseAttachment); + + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY; + if (mixRotate == 0 && mixX == 0 && mixY == 0) return; + + PathConstraintData &data = _data; + bool tangents = data._rotateMode == RotateMode_Tangent, scale = data._rotateMode == RotateMode_ChainScale; + size_t boneCount = _bones.size(); + size_t spacesCount = tangents ? boneCount : boneCount + 1; + _spaces.setSize(spacesCount, 0); + if (scale) _lengths.setSize(boneCount, 0); + float spacing = _spacing; + + switch (data._spacingMode) { + case SpacingMode_Percent: { + if (scale) { + for (size_t i = 0, n = spacesCount - 1; i < n; i++) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + float setupLength = bone._data.getLength(); + float x = setupLength * bone._a; + float y = setupLength * bone._c; + _lengths[i] = MathUtil::sqrt(x * x + y * y); + } + } + for (size_t i = 1; i < spacesCount; ++i) { + _spaces[i] = spacing; + } + break; + } + case SpacingMode_Proportional: { + float sum = 0; + for (size_t i = 0, n = spacesCount - 1; i < n;) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + float setupLength = bone._data.getLength(); + if (setupLength < PathConstraint::EPSILON) { + if (scale) _lengths[i] = 0; + _spaces[++i] = spacing; + } else { + float x = setupLength * bone._a, y = setupLength * bone._c; + float length = MathUtil::sqrt(x * x + y * y); + if (scale) _lengths[i] = length; + _spaces[++i] = length; + sum += length; + } + } + if (sum > 0) { + sum = spacesCount / sum * spacing; + for (size_t i = 1; i < spacesCount; i++) { + _spaces[i] *= sum; + } + } + break; + } + default: { + bool lengthSpacing = data._spacingMode == SpacingMode_Length; + for (size_t i = 0, n = spacesCount - 1; i < n;) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + float setupLength = bone._data.getLength(); + if (setupLength < PathConstraint::EPSILON) { + if (scale) _lengths[i] = 0; + _spaces[++i] = spacing; + } else { + float x = setupLength * bone._a, y = setupLength * bone._c; + float length = MathUtil::sqrt(x * x + y * y); + if (scale) _lengths[i] = length; + _spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; + } + } + } + } + + Vector &positions = computeWorldPositions(*attachment, (int) spacesCount, tangents); + float boneX = positions[0]; + float boneY = positions[1]; + float offsetRotation = data.getOffsetRotation(); + bool tip; + if (offsetRotation == 0) { + tip = data._rotateMode == RotateMode_Chain; + } else { + tip = false; + Bone &p = _target->getBone(); + offsetRotation *= p.getA() * p.getD() - p.getB() * p.getC() > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; + } + + for (size_t i = 0, p = 3; i < boneCount; i++, p += 3) { + Bone *boneP = _bones[i]; + Bone &bone = *boneP; + bone._worldX += (boneX - bone._worldX) * mixX; + bone._worldY += (boneY - bone._worldY) * mixY; + float x = positions[p]; + float y = positions[p + 1]; + float dx = x - boneX; + float dy = y - boneY; + if (scale) { + float length = _lengths[i]; + if (length >= PathConstraint::EPSILON) { + float s = (MathUtil::sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1; + bone._a *= s; + bone._c *= s; + } + } + + boneX = x; + boneY = y; + + if (mixRotate > 0) { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d, r, cos, sin; + if (tangents) + r = positions[p - 1]; + else if (_spaces[i + 1] < PathConstraint::EPSILON) + r = positions[p + 2]; + else + r = MathUtil::atan2(dy, dx); + + r -= MathUtil::atan2(c, a); + + if (tip) { + cos = MathUtil::cos(r); + sin = MathUtil::sin(r); + float length = bone._data.getLength(); + boneX += (length * (cos * a - sin * c) - dx) * mixRotate; + boneY += (length * (sin * a + cos * c) - dy) * mixRotate; + } else + r += offsetRotation; + + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r *= mixRotate; + cos = MathUtil::cos(r); + sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + } + + bone.updateAppliedTransform(); + } +} + +int PathConstraint::getOrder() { + return (int) _data.getOrder(); +} + +float PathConstraint::getPosition() { + return _position; +} + +void PathConstraint::setPosition(float inValue) { + _position = inValue; +} + +float PathConstraint::getSpacing() { + return _spacing; +} + +void PathConstraint::setSpacing(float inValue) { + _spacing = inValue; +} + +float PathConstraint::getMixRotate() { + return _mixRotate; +} + +void PathConstraint::setMixRotate(float inValue) { + _mixRotate = inValue; +} + +float PathConstraint::getMixX() { + return _mixX; +} + +void PathConstraint::setMixX(float inValue) { + _mixX = inValue; +} + +float PathConstraint::getMixY() { + return _mixY; +} + +void PathConstraint::setMixY(float inValue) { + _mixY = inValue; +} + +Vector &PathConstraint::getBones() { + return _bones; +} + +Slot *PathConstraint::getTarget() { + return _target; +} + +void PathConstraint::setTarget(Slot *inValue) { + _target = inValue; +} + +PathConstraintData &PathConstraint::getData() { + return _data; +} + +Vector & +PathConstraint::computeWorldPositions(PathAttachment &path, int spacesCount, bool tangents) { + Slot &target = *_target; + float position = _position; + _positions.setSize(spacesCount * 3 + 2, 0); + Vector &out = _positions; + Vector &world = _world; + bool closed = path.isClosed(); + int verticesLength = (int) path.getWorldVerticesLength(); + int curveCount = verticesLength / 6; + int prevCurve = NONE; + + float pathLength; + if (!path.isConstantSpeed()) { + Vector &lengths = path.getLengths(); + curveCount -= closed ? 1 : 2; + pathLength = lengths[curveCount]; + if (_data._positionMode == PositionMode_Percent) position *= pathLength; + + float multiplier = 0; + switch (_data._spacingMode) { + case SpacingMode_Percent: + multiplier = pathLength; + break; + case SpacingMode_Proportional: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + + world.setSize(8, 0); + for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + float space = _spaces[i] * multiplier; + position += space; + float p = position; + + if (closed) { + p = MathUtil::fmod(p, pathLength); + if (p < 0) p += pathLength; + curve = 0; + } else if (p < 0) { + if (prevCurve != BEFORE) { + prevCurve = BEFORE; + path.computeWorldVertices(target, 2, 4, world, 0); + } + + addBeforePosition(p, world, 0, out, o); + + continue; + } else if (p > pathLength) { + if (prevCurve != AFTER) { + prevCurve = AFTER; + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0); + } + + addAfterPosition(p - pathLength, world, 0, out, o); + + continue; + } + + // Determine curve containing position. + for (;; curve++) { + float length = lengths[curve]; + if (p > length) continue; + + if (curve == 0) + p /= length; + else { + float prev = lengths[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + + if (curve != prevCurve) { + prevCurve = curve; + if (closed && curve == curveCount) { + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0); + path.computeWorldVertices(target, 0, 4, world, 4); + } else + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0); + } + + addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], + out, o, tangents || (i > 0 && space < EPSILON)); + } + return out; + } + + // World vertices. + if (closed) { + verticesLength += 2; + world.setSize(verticesLength, 0); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } else { + curveCount--; + verticesLength -= 4; + world.setSize(verticesLength, 0); + path.computeWorldVertices(target, 2, verticesLength, world, 0); + } + + // Curve lengths. + _curves.setSize(curveCount, 0); + pathLength = 0; + float x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy; + for (int i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875f; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875f; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375f; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375f; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f; + dfy = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + + if (_data._positionMode == PositionMode_Percent) position *= pathLength; + + float multiplier = 0; + switch (_data._spacingMode) { + case SpacingMode_Percent: + multiplier = pathLength; + break; + case SpacingMode_Proportional: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + + float curveLength = 0; + for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + float space = _spaces[i] * multiplier; + position += space; + float p = position; + + if (closed) { + p = MathUtil::fmod(p, pathLength); + if (p < 0) p += pathLength; + curve = 0; + } else if (p < 0) { + addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength) { + addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + + // Determine curve containing position. + for (;; curve++) { + float length = _curves[curve]; + if (p > length) continue; + if (curve == 0) + p /= length; + else { + float prev = _curves[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + + // Curve segment lengths. + if (curve != prevCurve) { + prevCurve = curve; + int ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03f; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03f; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006f; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006f; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f; + dfy = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f; + curveLength = MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[9] = curveLength; + segment = 0; + } + + // Weight by segment length. + p *= curveLength; + for (;; segment++) { + float length = _segments[segment]; + if (p > length) continue; + if (segment == 0) + p /= length; + else { + float prev = _segments[segment - 1]; + p = segment + (p - prev) / (length - prev); + } + break; + } + addCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, + tangents || (i > 0 && space < EPSILON)); + } + + return out; +} + +void PathConstraint::addBeforePosition(float p, Vector &temp, int i, Vector &output, int o) { + float x1 = temp[i]; + float y1 = temp[i + 1]; + float dx = temp[i + 2] - x1; + float dy = temp[i + 3] - y1; + float r = MathUtil::atan2(dy, dx); + output[o] = x1 + p * MathUtil::cos(r); + output[o + 1] = y1 + p * MathUtil::sin(r); + output[o + 2] = r; +} + +void PathConstraint::addAfterPosition(float p, Vector &temp, int i, Vector &output, int o) { + float x1 = temp[i + 2]; + float y1 = temp[i + 3]; + float dx = x1 - temp[i]; + float dy = y1 - temp[i + 1]; + float r = MathUtil::atan2(dy, dx); + output[o] = x1 + p * MathUtil::cos(r); + output[o + 1] = y1 + p * MathUtil::sin(r); + output[o + 2] = r; +} + +void PathConstraint::addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, + float y2, Vector &output, int o, bool tangents) { + if (p < EPSILON || MathUtil::isNan(p)) { + output[o] = x1; + output[o + 1] = y1; + output[o + 2] = MathUtil::atan2(cy1 - y1, cx1 - x1); + return; + } + + float tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + float ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + float x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + output[o] = x; + output[o + 1] = y; + if (tangents) { + if (p < 0.001) + output[o + 2] = MathUtil::atan2(cy1 - y1, cx1 - x1); + else + output[o + 2] = MathUtil::atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), + x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } +} + +bool PathConstraint::isActive() { + return _active; +} + +void PathConstraint::setActive(bool inValue) { + _active = inValue; +} + +void PathConstraint::setToSetupPose() { + PathConstraintData &data = this->_data; + this->_position = data._position; + this->_spacing = data._spacing; + this->_mixRotate = data._mixRotate; + this->_mixX = data._mixX; + this->_mixY = data._mixY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp new file mode 100644 index 0000000..6d13223 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -0,0 +1,136 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintData, ConstraintData) + +PathConstraintData::PathConstraintData(const String &name) : ConstraintData(name), + _target(NULL), + _positionMode(PositionMode_Fixed), + _spacingMode(SpacingMode_Length), + _rotateMode(RotateMode_Tangent), + _offsetRotation(0), + _position(0), + _spacing(0), + _mixRotate(0), + _mixX(0), + _mixY(0) { +} + +Vector &PathConstraintData::getBones() { + return _bones; +} + +SlotData *PathConstraintData::getTarget() { + return _target; +} + +void PathConstraintData::setTarget(SlotData *inValue) { + _target = inValue; +} + +PositionMode PathConstraintData::getPositionMode() { + return _positionMode; +} + +void PathConstraintData::setPositionMode(PositionMode inValue) { + _positionMode = inValue; +} + +SpacingMode PathConstraintData::getSpacingMode() { + return _spacingMode; +} + +void PathConstraintData::setSpacingMode(SpacingMode inValue) { + _spacingMode = inValue; +} + +RotateMode PathConstraintData::getRotateMode() { + return _rotateMode; +} + +void PathConstraintData::setRotateMode(RotateMode inValue) { + _rotateMode = inValue; +} + +float PathConstraintData::getOffsetRotation() { + return _offsetRotation; +} + +void PathConstraintData::setOffsetRotation(float inValue) { + _offsetRotation = inValue; +} + +float PathConstraintData::getPosition() { + return _position; +} + +void PathConstraintData::setPosition(float inValue) { + _position = inValue; +} + +float PathConstraintData::getSpacing() { + return _spacing; +} + +void PathConstraintData::setSpacing(float inValue) { + _spacing = inValue; +} + +float PathConstraintData::getMixRotate() { + return _mixRotate; +} + +void PathConstraintData::setMixRotate(float inValue) { + _mixRotate = inValue; +} + +float PathConstraintData::getMixX() { + return _mixX; +} + +void PathConstraintData::setMixX(float inValue) { + _mixX = inValue; +} + +float PathConstraintData::getMixY() { + return _mixY; +} + +void PathConstraintData::setMixY(float inValue) { + _mixY = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp new file mode 100644 index 0000000..9d4969c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -0,0 +1,126 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline) + +PathConstraintMixTimeline::PathConstraintMixTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex) + : CurveTimeline(frameCount, PathConstraintMixTimeline::ENTRIES, bezierCount), + _constraintIndex(pathConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_PathConstraintMix << 32) | pathConstraintIndex}; + setPropertyIds(ids, 1); +} + +void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + PathConstraint *constraintP = skeleton._pathConstraints[_constraintIndex]; + PathConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._mixRotate = constraint._data._mixRotate; + constraint._mixX = constraint._data._mixX; + constraint._mixY = constraint._data._mixY; + return; + case MixBlend_First: + constraint._mixRotate += (constraint._data._mixRotate - constraint._mixRotate) * alpha; + constraint._mixX += (constraint._data._mixX - constraint._mixX) * alpha; + constraint._mixY += (constraint._data._mixY - constraint._mixY) * alpha; + default: { + } + } + return; + } + + float rotate, x, y; + int i = Animation::search(_frames, time, PathConstraintMixTimeline::ENTRIES); + int curveType = (int) _curves[i >> 2]; + switch (curveType) { + case LINEAR: { + float before = _frames[i]; + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + float t = (time - before) / (_frames[i + ENTRIES] - before); + rotate += (_frames[i + ENTRIES + ROTATE] - rotate) * t; + x += (_frames[i + ENTRIES + X] - x) * t; + y += (_frames[i + ENTRIES + Y] - y) * t; + break; + } + case STEPPED: { + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + break; + } + default: { + rotate = getBezierValue(time, i, ROTATE, curveType - BEZIER); + x = getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER); + y = getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER); + } + } + + if (blend == MixBlend_Setup) { + PathConstraintData data = constraint._data; + constraint._mixRotate = data._mixRotate + (rotate - data._mixRotate) * alpha; + constraint._mixX = data._mixX + (x - data._mixX) * alpha; + constraint._mixY = data._mixY + (y - data._mixY) * alpha; + } else { + constraint._mixRotate += (rotate - constraint._mixRotate) * alpha; + constraint._mixX += (x - constraint._mixX) * alpha; + constraint._mixY += (y - constraint._mixY) * alpha; + } +} + +void PathConstraintMixTimeline::setFrame(int frame, float time, float mixRotate, float mixX, float mixY) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + ROTATE] = mixRotate; + _frames[frame + X] = mixX; + _frames[frame + Y] = mixY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp new file mode 100644 index 0000000..25ab8d4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -0,0 +1,66 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline1) + +PathConstraintPositionTimeline::PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, + int pathConstraintIndex) : CurveTimeline1(frameCount, + bezierCount), + _constraintIndex( + pathConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_PathConstraintPosition << 32) | pathConstraintIndex}; + setPropertyIds(ids, 1); +} + +PathConstraintPositionTimeline::~PathConstraintPositionTimeline() { +} + +void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + PathConstraint *constraint = skeleton._pathConstraints[_constraintIndex]; + if (constraint->_active) constraint->_position = getAbsoluteValue(time, alpha, blend, constraint->_position, constraint->_data._position); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp new file mode 100644 index 0000000..e1921dd --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -0,0 +1,64 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline) + +PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(size_t frameCount, size_t bezierCount, + int pathConstraintIndex) : CurveTimeline1(frameCount, + bezierCount), + _pathConstraintIndex( + pathConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_PathConstraintSpacing << 32) | pathConstraintIndex}; + setPropertyIds(ids, 1); +} + +void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + PathConstraint *constraint = skeleton._pathConstraints[_pathConstraintIndex]; + if (constraint->_active) + constraint->_spacing = getAbsoluteValue(time, alpha, blend, constraint->_spacing, constraint->_data._spacing); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PhysicsConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PhysicsConstraint.cpp new file mode 100644 index 0000000..adf9d8f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PhysicsConstraint.cpp @@ -0,0 +1,493 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PhysicsConstraint, Updatable) + +PhysicsConstraint::PhysicsConstraint(PhysicsConstraintData &data, Skeleton &skeleton) + : _data(data), _skeleton(skeleton) { + _bone = skeleton.getBones()[data.getBone()->getIndex()]; + _inertia = data.getInertia(); + _strength = data.getStrength(); + _damping = data.getDamping(); + _massInverse = data.getMassInverse(); + _wind = data.getWind(); + _gravity = data.getGravity(); + _mix = data.getMix(); + + _reset = true; + _ux = 0; + _uy = 0; + _cx = 0; + _cy = 0; + _tx = 0; + _ty = 0; + _xOffset = 0; + _xVelocity = 0; + _yOffset = 0; + _yVelocity = 0; + _rotateOffset = 0; + _rotateVelocity = 0; + _scaleOffset = 0; + _scaleVelocity = 0; + _active = false; + _remaining = 0; + _lastTime = 0; +} + +PhysicsConstraintData &PhysicsConstraint::getData() { + return _data; +} + +void PhysicsConstraint::setBone(Bone *bone) { + _bone = bone; +} + +Bone *PhysicsConstraint::getBone() { + return _bone; +} + +void PhysicsConstraint::setInertia(float value) { + _inertia = value; +} + +float PhysicsConstraint::getInertia() { + return _inertia; +} + +void PhysicsConstraint::setStrength(float value) { + _strength = value; +} + +float PhysicsConstraint::getStrength() { + return _strength; +} + +void PhysicsConstraint::setDamping(float value) { + _damping = value; +} + +float PhysicsConstraint::getDamping() { + return _damping; +} + +void PhysicsConstraint::setMassInverse(float value) { + _massInverse = value; +} + +float PhysicsConstraint::getMassInverse() { + return _massInverse; +} + +void PhysicsConstraint::setWind(float value) { + _wind = value; +} + +float PhysicsConstraint::getWind() { + return _wind; +} + +void PhysicsConstraint::setGravity(float value) { + _gravity = value; +} + +float PhysicsConstraint::getGravity() { + return _gravity; +} + +void PhysicsConstraint::setMix(float value) { + _mix = value; +} + +float PhysicsConstraint::getMix() { + return _mix; +} + +void PhysicsConstraint::setReset(bool value) { + _reset = value; +} + +bool PhysicsConstraint::getReset() { + return _reset; +} + +void PhysicsConstraint::setUx(float value) { + _ux = value; +} + +float PhysicsConstraint::getUx() { + return _ux; +} + +void PhysicsConstraint::setUy(float value) { + _uy = value; +} + +float PhysicsConstraint::getUy() { + return _uy; +} + +void PhysicsConstraint::setCx(float value) { + _cx = value; +} + +float PhysicsConstraint::getCx() { + return _cx; +} + +void PhysicsConstraint::setCy(float value) { + _cy = value; +} + +float PhysicsConstraint::getCy() { + return _cy; +} + +void PhysicsConstraint::setTx(float value) { + _tx = value; +} + +float PhysicsConstraint::getTx() { + return _tx; +} + +void PhysicsConstraint::setTy(float value) { + _ty = value; +} + +float PhysicsConstraint::getTy() { + return _ty; +} + +void PhysicsConstraint::setXOffset(float value) { + _xOffset = value; +} + +float PhysicsConstraint::getXOffset() { + return _xOffset; +} + +void PhysicsConstraint::setXVelocity(float value) { + _xVelocity = value; +} + +float PhysicsConstraint::getXVelocity() { + return _xVelocity; +} + +void PhysicsConstraint::setYOffset(float value) { + _yOffset = value; +} + +float PhysicsConstraint::getYOffset() { + return _yOffset; +} + +void PhysicsConstraint::setYVelocity(float value) { + _yVelocity = value; +} + +float PhysicsConstraint::getYVelocity() { + return _yVelocity; +} + +void PhysicsConstraint::setRotateOffset(float value) { + _rotateOffset = value; +} + +float PhysicsConstraint::getRotateOffset() { + return _rotateOffset; +} + +void PhysicsConstraint::setRotateVelocity(float value) { + _rotateVelocity = value; +} + +float PhysicsConstraint::getRotateVelocity() { + return _rotateVelocity; +} + +void PhysicsConstraint::setScaleOffset(float value) { + _scaleOffset = value; +} + +float PhysicsConstraint::getScaleOffset() { + return _scaleOffset; +} + +void PhysicsConstraint::setScaleVelocity(float value) { + _scaleVelocity = value; +} + +float PhysicsConstraint::getScaleVelocity() { + return _scaleVelocity; +} + +void PhysicsConstraint::setActive(bool value) { + _active = value; +} + +bool PhysicsConstraint::isActive() { + return _active; +} + +void PhysicsConstraint::setRemaining(float value) { + _remaining = value; +} + +float PhysicsConstraint::getRemaining() { + return _remaining; +} + +void PhysicsConstraint::setLastTime(float value) { + _lastTime = value; +} + +float PhysicsConstraint::getLastTime() { + return _lastTime; +} + +void PhysicsConstraint::reset() { + _remaining = 0; + _lastTime = _skeleton.getTime(); + _reset = true; + _xOffset = 0; + _xVelocity = 0; + _yOffset = 0; + _yVelocity = 0; + _rotateOffset = 0; + _rotateVelocity = 0; + _scaleOffset = 0; + _scaleVelocity = 0; +} + +void PhysicsConstraint::setToSetupPose() { + _inertia = _data.getInertia(); + _strength = _data.getStrength(); + _damping = _data.getDamping(); + _massInverse = _data.getMassInverse(); + _wind = _data.getWind(); + _gravity = _data.getGravity(); + _mix = _data.getMix(); +} +void PhysicsConstraint::update(Physics physics) { + float mix = _mix; + if (mix == 0) return; + + bool x = _data._x > 0; + bool y = _data._y > 0; + bool rotateOrShearX = _data._rotate > 0 || _data._shearX > 0; + bool scaleX = _data._scaleX > 0; + + Bone *bone = _bone; + float l = bone->_data.getLength(); + + switch (physics) { + case Physics::Physics_None: + return; + case Physics::Physics_Reset: + reset(); + // Fall through. + case Physics::Physics_Update: { + float delta = MathUtil::max(_skeleton.getTime() - _lastTime, 0.0f); + _remaining += delta; + _lastTime = _skeleton.getTime(); + + float bx = bone->_worldX, by = bone->_worldY; + if (_reset) { + _reset = false; + _ux = bx; + _uy = by; + } else { + float a = _remaining, i = _inertia, t = _data._step, f = _skeleton.getData()->getReferenceScale(); + float qx = _data._limit * delta, qy = qx * MathUtil::abs(_skeleton.getScaleX()); + qx *= MathUtil::abs(_skeleton.getScaleY()); + if (x || y) { + if (x) { + float u = (_ux - bx) * i; + _xOffset += u > qx ? qx : u < -qx ? -qx + : u; + _ux = bx; + } + if (y) { + float u = (_uy - by) * i; + _yOffset += u > qy ? qy : u < -qy ? -qy + : u; + _uy = by; + } + if (a >= t) { + float d = MathUtil::pow(_damping, 60 * t); + float m = _massInverse * t, e = _strength, w = _wind * f * _skeleton.getScaleX(), g = _gravity * f * _skeleton.getScaleY(); + do { + if (x) { + _xVelocity += (w - _xOffset * e) * m; + _xOffset += _xVelocity * t; + _xVelocity *= d; + } + if (y) { + _yVelocity -= (g + _yOffset * e) * m; + _yOffset += _yVelocity * t; + _yVelocity *= d; + } + a -= t; + } while (a >= t); + } + if (x) bone->_worldX += _xOffset * mix * _data._x; + if (y) bone->_worldY += _yOffset * mix * _data._y; + } + + if (rotateOrShearX || scaleX) { + float ca = MathUtil::atan2(bone->_c, bone->_a), c, s, mr = 0; + float dx = _cx - bone->_worldX, dy = _cy - bone->_worldY; + if (dx > qx) + dx = qx; + else if (dx < -qx)// + dx = -qx; + if (dy > qy) + dy = qy; + else if (dy < -qy)// + dy = -qy; + if (rotateOrShearX) { + mr = (_data._rotate + _data._shearX) * mix; + float r = MathUtil::atan2(dy + _ty, dx + _tx) - ca - _rotateOffset * mr; + _rotateOffset += (r - MathUtil::ceil(r * MathUtil::InvPi_2 - 0.5f) * MathUtil::Pi_2) * i; + r = _rotateOffset * mr + ca; + c = MathUtil::cos(r); + s = MathUtil::sin(r); + if (scaleX) { + r = l * bone->getWorldScaleX(); + if (r > 0) _scaleOffset += (dx * c + dy * s) * i / r; + } + } else { + c = MathUtil::cos(ca); + s = MathUtil::sin(ca); + float r = l * bone->getWorldScaleX(); + if (r > 0) _scaleOffset += (dx * c + dy * s) * i / r; + } + a = _remaining; + if (a >= t) { + float m = _massInverse * t, e = _strength, w = _wind, g = _gravity * (Bone::yDown ? -1 : 1), h = l / f; + float d = MathUtil::pow(_damping, 60 * t); + while (true) { + a -= t; + if (scaleX) { + _scaleVelocity += (w * c - g * s - _scaleOffset * e) * m; + _scaleOffset += _scaleVelocity * t; + _scaleVelocity *= d; + } + if (rotateOrShearX) { + _rotateVelocity -= ((w * s + g * c) * h + _rotateOffset * e) * m; + _rotateOffset += _rotateVelocity * t; + _rotateVelocity *= d; + if (a < t) break; + float r = _rotateOffset * mr + ca; + c = MathUtil::cos(r); + s = MathUtil::sin(r); + } else if (a < t)// + break; + } + } + } + _remaining = a; + } + + _cx = bone->_worldX; + _cy = bone->_worldY; + break; + } + case Physics::Physics_Pose: { + if (x) bone->_worldX += _xOffset * mix * _data._x; + if (y) bone->_worldY += _yOffset * mix * _data._y; + break; + } + } + + if (rotateOrShearX) { + float o = _rotateOffset * mix, s = 0, c = 0, a = 0; + if (_data._shearX > 0) { + float r = 0; + if (_data._rotate > 0) { + r = o * _data._rotate; + s = MathUtil::sin(r); + c = MathUtil::cos(r); + a = bone->_b; + bone->_b = c * a - s * bone->_d; + bone->_d = s * a + c * bone->_d; + } + r += o * _data._shearX; + s = MathUtil::sin(r); + c = MathUtil::cos(r); + a = bone->_a; + bone->_a = c * a - s * bone->_c; + bone->_c = s * a + c * bone->_c; + } else { + o *= _data._rotate; + s = MathUtil::sin(o); + c = MathUtil::cos(o); + a = bone->_a; + bone->_a = c * a - s * bone->_c; + bone->_c = s * a + c * bone->_c; + a = bone->_b; + bone->_b = c * a - s * bone->_d; + bone->_d = s * a + c * bone->_d; + } + } + if (scaleX) { + float s = 1 + _scaleOffset * mix * _data._scaleX; + bone->_a *= s; + bone->_c *= s; + } + if (physics != Physics::Physics_Pose) { + _tx = l * bone->_a; + _ty = l * bone->_c; + } + bone->updateAppliedTransform(); +} + +void PhysicsConstraint::rotate(float x, float y, float degrees) { + float r = degrees * MathUtil::Deg_Rad, cos = MathUtil::cos(r), sin = MathUtil::sin(r); + float dx = _cx - x, dy = _cy - y; + translate(dx * cos - dy * sin - dx, dx * sin + dy * cos - dy); +} + +void PhysicsConstraint::translate(float x, float y) { + _ux -= x; + _uy -= y; + _cx -= x; + _cy -= y; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp new file mode 100644 index 0000000..2c88a8d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp @@ -0,0 +1,223 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +#include + +using namespace spine; + +RTTI_IMPL(PhysicsConstraintData, ConstraintData) + +PhysicsConstraintData::PhysicsConstraintData(const String &name) : ConstraintData(name), + _bone(nullptr), + _x(0), _y(0), _rotate(0), _scaleX(0), _shearX(0), _limit(0), + _step(0), _inertia(0), _strength(0), _damping(0), _massInverse(0), _wind(0), _gravity(0), _mix(0), + _inertiaGlobal(false), _strengthGlobal(false), _dampingGlobal(false), _massGlobal(false), + _windGlobal(false), _gravityGlobal(false), _mixGlobal(false) { +} + + +void PhysicsConstraintData::setBone(BoneData *bone) { + _bone = bone; +} + +BoneData *PhysicsConstraintData::getBone() const { + return _bone; +} + +void PhysicsConstraintData::setX(float x) { + _x = x; +} + +float PhysicsConstraintData::getX() const { + return _x; +} + +void PhysicsConstraintData::setY(float y) { + _y = y; +} + +float PhysicsConstraintData::getY() const { + return _y; +} + +void PhysicsConstraintData::setRotate(float rotate) { + _rotate = rotate; +} + +float PhysicsConstraintData::getRotate() const { + return _rotate; +} + +void PhysicsConstraintData::setScaleX(float scaleX) { + _scaleX = scaleX; +} + +float PhysicsConstraintData::getScaleX() const { + return _scaleX; +} + +void PhysicsConstraintData::setShearX(float shearX) { + _shearX = shearX; +} + +float PhysicsConstraintData::getShearX() const { + return _shearX; +} + +void PhysicsConstraintData::setLimit(float limit) { + _limit = limit; +} + +float PhysicsConstraintData::getLimit() const { + return _limit; +} + +void PhysicsConstraintData::setStep(float step) { + _step = step; +} + +float PhysicsConstraintData::getStep() const { + return _step; +} + +void PhysicsConstraintData::setInertia(float inertia) { + _inertia = inertia; +} + +float PhysicsConstraintData::getInertia() const { + return _inertia; +} + +void PhysicsConstraintData::setStrength(float strength) { + _strength = strength; +} + +float PhysicsConstraintData::getStrength() const { + return _strength; +} + +void PhysicsConstraintData::setDamping(float damping) { + _damping = damping; +} + +float PhysicsConstraintData::getDamping() const { + return _damping; +} + +void PhysicsConstraintData::setMassInverse(float massInverse) { + _massInverse = massInverse; +} + +float PhysicsConstraintData::getMassInverse() const { + return _massInverse; +} + +void PhysicsConstraintData::setWind(float wind) { + _wind = wind; +} + +float PhysicsConstraintData::getWind() const { + return _wind; +} + +void PhysicsConstraintData::setGravity(float gravity) { + _gravity = gravity; +} + +float PhysicsConstraintData::getGravity() const { + return _gravity; +} + +void PhysicsConstraintData::setMix(float mix) { + _mix = mix; +} + +float PhysicsConstraintData::getMix() const { + return _mix; +} + +void PhysicsConstraintData::setInertiaGlobal(bool inertiaGlobal) { + _inertiaGlobal = inertiaGlobal; +} + +bool PhysicsConstraintData::isInertiaGlobal() const { + return _inertiaGlobal; +} + +void PhysicsConstraintData::setStrengthGlobal(bool strengthGlobal) { + _strengthGlobal = strengthGlobal; +} + +bool PhysicsConstraintData::isStrengthGlobal() const { + return _strengthGlobal; +} + +void PhysicsConstraintData::setDampingGlobal(bool dampingGlobal) { + _dampingGlobal = dampingGlobal; +} + +bool PhysicsConstraintData::isDampingGlobal() const { + return _dampingGlobal; +} + +void PhysicsConstraintData::setMassGlobal(bool massGlobal) { + _massGlobal = massGlobal; +} + +bool PhysicsConstraintData::isMassGlobal() const { + return _massGlobal; +} + +void PhysicsConstraintData::setWindGlobal(bool windGlobal) { + _windGlobal = windGlobal; +} + +bool PhysicsConstraintData::isWindGlobal() const { + return _windGlobal; +} + +void PhysicsConstraintData::setGravityGlobal(bool gravityGlobal) { + _gravityGlobal = gravityGlobal; +} + +bool PhysicsConstraintData::isGravityGlobal() const { + return _gravityGlobal; +} + +void PhysicsConstraintData::setMixGlobal(bool mixGlobal) { + _mixGlobal = mixGlobal; +} + +bool PhysicsConstraintData::isMixGlobal() const { + return _mixGlobal; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PhysicsConstraintTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PhysicsConstraintTimeline.cpp new file mode 100644 index 0000000..4671e3f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PhysicsConstraintTimeline.cpp @@ -0,0 +1,103 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PhysicsConstraintTimeline, CurveTimeline) +RTTI_IMPL(PhysicsConstraintInertiaTimeline, PhysicsConstraintTimeline) +RTTI_IMPL(PhysicsConstraintStrengthTimeline, PhysicsConstraintTimeline) +RTTI_IMPL(PhysicsConstraintDampingTimeline, PhysicsConstraintTimeline) +RTTI_IMPL(PhysicsConstraintMassTimeline, PhysicsConstraintTimeline) +RTTI_IMPL(PhysicsConstraintWindTimeline, PhysicsConstraintTimeline) +RTTI_IMPL(PhysicsConstraintGravityTimeline, PhysicsConstraintTimeline) +RTTI_IMPL(PhysicsConstraintMixTimeline, PhysicsConstraintTimeline) +RTTI_IMPL(PhysicsConstraintResetTimeline, Timeline) + +PhysicsConstraintTimeline::PhysicsConstraintTimeline(size_t frameCount, size_t bezierCount, + int constraintIndex, Property property) : CurveTimeline1(frameCount, bezierCount), + _constraintIndex(constraintIndex) { + PropertyId ids[] = {((PropertyId) property << 32) | constraintIndex}; + setPropertyIds(ids, 1); +} + +void PhysicsConstraintTimeline::apply(Skeleton &skeleton, float, float time, Vector *, + float alpha, MixBlend blend, MixDirection) { + if (_constraintIndex == -1) { + float value = time >= _frames[0] ? getCurveValue(time) : 0; + + Vector &physicsConstraints = skeleton.getPhysicsConstraints(); + for (size_t i = 0; i < physicsConstraints.size(); i++) { + PhysicsConstraint *constraint = physicsConstraints[i]; + if (constraint->_active && global(constraint->_data)) + set(constraint, getAbsoluteValue(time, alpha, blend, get(constraint), setup(constraint), value)); + } + } else { + PhysicsConstraint *constraint = skeleton.getPhysicsConstraints()[_constraintIndex]; + if (constraint->_active) set(constraint, getAbsoluteValue(time, alpha, blend, get(constraint), setup(constraint))); + } +} + +void PhysicsConstraintResetTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *, float alpha, MixBlend blend, MixDirection direction) { + PhysicsConstraint *constraint = nullptr; + if (_constraintIndex != -1) { + constraint = skeleton.getPhysicsConstraints()[_constraintIndex]; + if (!constraint->_active) return; + } + + if (lastTime > time) {// Apply after lastTime for looped animations. + apply(skeleton, lastTime, FLT_MAX, nullptr, alpha, blend, direction); + lastTime = -1; + } else if (lastTime >= _frames[_frames.size() - 1])// Last time is after last frame. + return; + if (time < _frames[0]) return; + + if (lastTime < _frames[0] || time >= _frames[Animation::search(_frames, lastTime) + 1]) { + if (constraint != nullptr) + constraint->reset(); + else { + Vector &physicsConstraints = skeleton.getPhysicsConstraints(); + for (size_t i = 0; i < physicsConstraints.size(); i++) { + constraint = physicsConstraints[i]; + if (constraint->_active) constraint->reset(); + } + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp new file mode 100644 index 0000000..611f3af --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp @@ -0,0 +1,88 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +#include + +using namespace spine; + +RTTI_IMPL(PointAttachment, Attachment) + +PointAttachment::PointAttachment(const String &name) : Attachment(name), _x(0), _y(0), _rotation(0), _color() { +} + +void PointAttachment::computeWorldPosition(Bone &bone, float &ox, float &oy) { + bone.localToWorld(_x, _y, ox, oy); +} + +float PointAttachment::computeWorldRotation(Bone &bone) { + float r = _rotation * MathUtil::Deg_Rad, cosine = MathUtil::cos(r), sine = MathUtil::sin(r); + float x = cosine * bone._a + sine * bone._b; + float y = cosine * bone._c + sine * bone._d; + return MathUtil::atan2Deg(y, x); +} + +float PointAttachment::getX() { + return _x; +} + +void PointAttachment::setX(float inValue) { + _x = inValue; +} + +float PointAttachment::getY() { + return _y; +} + +void PointAttachment::setY(float inValue) { + _y = inValue; +} + +float PointAttachment::getRotation() { + return _rotation; +} + +void PointAttachment::setRotation(float inValue) { + _rotation = inValue; +} + +Color &PointAttachment::getColor() { + return _color; +} + +Attachment *PointAttachment::copy() { + PointAttachment *copy = new (__FILE__, __LINE__) PointAttachment(getName()); + copy->_x = _x; + copy->_y = _y; + copy->_rotation = _rotation; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/RTTI.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/RTTI.cpp new file mode 100644 index 0000000..04c3160 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/RTTI.cpp @@ -0,0 +1,56 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +using namespace spine; + +RTTI::RTTI(const char *className) : _className(className), _pBaseRTTI(NULL) { +} + +RTTI::RTTI(const char *className, const RTTI &baseRTTI) : _className(className), _pBaseRTTI(&baseRTTI) { +} + +const char *RTTI::getClassName() const { + return _className; +} + +bool RTTI::isExactly(const RTTI &rtti) const { + return !strcmp(this->_className, rtti._className); +} + +bool RTTI::instanceOf(const RTTI &rtti) const { + const RTTI *pCompare = this; + while (pCompare) { + if (!strcmp(pCompare->_className, rtti._className)) return true; + pCompare = pCompare->_pBaseRTTI; + } + return false; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp new file mode 100644 index 0000000..65e1423 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -0,0 +1,275 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(RegionAttachment, Attachment) + +const int RegionAttachment::BLX = 0; +const int RegionAttachment::BLY = 1; +const int RegionAttachment::ULX = 2; +const int RegionAttachment::ULY = 3; +const int RegionAttachment::URX = 4; +const int RegionAttachment::URY = 5; +const int RegionAttachment::BRX = 6; +const int RegionAttachment::BRY = 7; + +RegionAttachment::RegionAttachment(const String &name) : Attachment(name), + _x(0), + _y(0), + _rotation(0), + _scaleX(1), + _scaleY(1), + _width(0), + _height(0), + _path(), + _color(1, 1, 1, 1), + _region(NULL), + _sequence(NULL) { + _vertexOffset.setSize(NUM_UVS, 0); + _uvs.setSize(NUM_UVS, 0); +} + +RegionAttachment::~RegionAttachment() { + if (_sequence) delete _sequence; +} + +void RegionAttachment::updateRegion() { + if (_region == NULL) { + _uvs[BLX] = 0; + _uvs[BLY] = 0; + _uvs[ULX] = 0; + _uvs[ULY] = 1; + _uvs[URX] = 1; + _uvs[URY] = 1; + _uvs[BRX] = 1; + _uvs[BRY] = 0; + return; + } + + float regionScaleX = _width / _region->originalWidth * _scaleX; + float regionScaleY = _height / _region->originalHeight * _scaleY; + float localX = -_width / 2 * _scaleX + _region->offsetX * regionScaleX; + float localY = -_height / 2 * _scaleY + _region->offsetY * regionScaleY; + float localX2 = localX + _region->width * regionScaleX; + float localY2 = localY + _region->height * regionScaleY; + float cos = MathUtil::cosDeg(_rotation); + float sin = MathUtil::sinDeg(_rotation); + float localXCos = localX * cos + _x; + float localXSin = localX * sin; + float localYCos = localY * cos + _y; + float localYSin = localY * sin; + float localX2Cos = localX2 * cos + _x; + float localX2Sin = localX2 * sin; + float localY2Cos = localY2 * cos + _y; + float localY2Sin = localY2 * sin; + + _vertexOffset[BLX] = localXCos - localYSin; + _vertexOffset[BLY] = localYCos + localXSin; + _vertexOffset[ULX] = localXCos - localY2Sin; + _vertexOffset[ULY] = localY2Cos + localXSin; + _vertexOffset[URX] = localX2Cos - localY2Sin; + _vertexOffset[URY] = localY2Cos + localX2Sin; + _vertexOffset[BRX] = localX2Cos - localYSin; + _vertexOffset[BRY] = localYCos + localX2Sin; + + if (_region->degrees == 90) { + _uvs[URX] = _region->u; + _uvs[URY] = _region->v2; + _uvs[BRX] = _region->u; + _uvs[BRY] = _region->v; + _uvs[BLX] = _region->u2; + _uvs[BLY] = _region->v; + _uvs[ULX] = _region->u2; + _uvs[ULY] = _region->v2; + } else { + _uvs[ULX] = _region->u; + _uvs[ULY] = _region->v2; + _uvs[URX] = _region->u; + _uvs[URY] = _region->v; + _uvs[BRX] = _region->u2; + _uvs[BRY] = _region->v; + _uvs[BLX] = _region->u2; + _uvs[BLY] = _region->v2; + } +} + +void RegionAttachment::computeWorldVertices(Slot &slot, Vector &worldVertices, size_t offset, size_t stride) { + assert(worldVertices.size() >= (offset + 8)); + computeWorldVertices(slot, worldVertices.buffer(), offset, stride); +} + +void RegionAttachment::computeWorldVertices(Slot &slot, float *worldVertices, size_t offset, size_t stride) { + if (_sequence) _sequence->apply(&slot, this); + + Bone &bone = slot.getBone(); + float x = bone.getWorldX(), y = bone.getWorldY(); + float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD(); + float offsetX, offsetY; + + offsetX = _vertexOffset[BRX]; + offsetY = _vertexOffset[BRY]; + worldVertices[offset] = offsetX * a + offsetY * b + x;// br + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = _vertexOffset[BLX]; + offsetY = _vertexOffset[BLY]; + worldVertices[offset] = offsetX * a + offsetY * b + x;// bl + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = _vertexOffset[ULX]; + offsetY = _vertexOffset[ULY]; + worldVertices[offset] = offsetX * a + offsetY * b + x;// ul + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = _vertexOffset[URX]; + offsetY = _vertexOffset[URY]; + worldVertices[offset] = offsetX * a + offsetY * b + x;// ur + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; +} + +float RegionAttachment::getX() { + return _x; +} + +void RegionAttachment::setX(float inValue) { + _x = inValue; +} + +float RegionAttachment::getY() { + return _y; +} + +void RegionAttachment::setY(float inValue) { + _y = inValue; +} + +float RegionAttachment::getRotation() { + return _rotation; +} + +void RegionAttachment::setRotation(float inValue) { + _rotation = inValue; +} + +float RegionAttachment::getScaleX() { + return _scaleX; +} + +void RegionAttachment::setScaleX(float inValue) { + _scaleX = inValue; +} + +float RegionAttachment::getScaleY() { + return _scaleY; +} + +void RegionAttachment::setScaleY(float inValue) { + _scaleY = inValue; +} + +float RegionAttachment::getWidth() { + return _width; +} + +void RegionAttachment::setWidth(float inValue) { + _width = inValue; +} + +float RegionAttachment::getHeight() { + return _height; +} + +void RegionAttachment::setHeight(float inValue) { + _height = inValue; +} + +const String &RegionAttachment::getPath() { + return _path; +} + +void RegionAttachment::setPath(const String &inValue) { + _path = inValue; +} + +TextureRegion *RegionAttachment::getRegion() { + return _region; +} + +void RegionAttachment::setRegion(TextureRegion *region) { + _region = region; +} + +Sequence *RegionAttachment::getSequence() { + return _sequence; +} + +void RegionAttachment::setSequence(Sequence *sequence) { + _sequence = sequence; +} + +Vector &RegionAttachment::getOffset() { + return _vertexOffset; +} + +Vector &RegionAttachment::getUVs() { + return _uvs; +} + +spine::Color &RegionAttachment::getColor() { + return _color; +} + +Attachment *RegionAttachment::copy() { + RegionAttachment *copy = new (__FILE__, __LINE__) RegionAttachment(getName()); + copy->_region = _region; + copy->_path = _path; + copy->_x = _x; + copy->_y = _y; + copy->_scaleX = _scaleX; + copy->_scaleY = _scaleY; + copy->_rotation = _rotation; + copy->_width = _width; + copy->_height = _height; + copy->_uvs.clearAndAddAll(_uvs); + copy->_vertexOffset.clearAndAddAll(_vertexOffset); + copy->_color.set(_color); + copy->_sequence = _sequence != NULL ? _sequence->copy() : NULL; + return copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp new file mode 100644 index 0000000..4c53f30 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(RotateTimeline, CurveTimeline1) + +RotateTimeline::RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_Rotate << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (bone->isActive()) bone->_rotation = getRelativeValue(time, alpha, blend, bone->_rotation, bone->getData()._rotation); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp new file mode 100644 index 0000000..f2fe50c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -0,0 +1,194 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(ScaleTimeline, CurveTimeline2) + +ScaleTimeline::ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ScaleX << 32) | boneIndex, + ((PropertyId) Property_ScaleY << 32) | boneIndex}; + setPropertyIds(ids, 2); +} + +ScaleTimeline::~ScaleTimeline() {} + +void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_scaleX = bone->_data._scaleX; + bone->_scaleY = bone->_data._scaleY; + return; + case MixBlend_First: + bone->_scaleX += (bone->_data._scaleX - bone->_scaleX) * alpha; + bone->_scaleY += (bone->_data._scaleY - bone->_scaleY) * alpha; + default: { + } + } + return; + } + + float x, y; + int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES); + int curveType = (int) _curves[i / CurveTimeline2::ENTRIES]; + switch (curveType) { + case CurveTimeline::LINEAR: { + float before = _frames[i]; + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before); + x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t; + y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t; + break; + } + case CurveTimeline::STEPPED: { + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + break; + } + default: { + x = getBezierValue(time, i, CurveTimeline2::VALUE1, curveType - CurveTimeline2::BEZIER); + y = getBezierValue(time, i, CurveTimeline2::VALUE2, + curveType + CurveTimeline2::BEZIER_SIZE - CurveTimeline2::BEZIER); + } + } + x *= bone->_data._scaleX; + y *= bone->_data._scaleY; + + if (alpha == 1) { + if (blend == MixBlend_Add) { + bone->_scaleX += x - bone->_data._scaleX; + bone->_scaleY += y - bone->_data._scaleY; + } else { + bone->_scaleX = x; + bone->_scaleY = y; + } + } else { + float bx, by; + if (direction == MixDirection_Out) { + switch (blend) { + case MixBlend_Setup: + bx = bone->_data._scaleX; + by = bone->_data._scaleY; + bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; + bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bx = bone->_scaleX; + by = bone->_scaleY; + bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; + bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; + break; + case MixBlend_Add: + bone->_scaleX += (x - bone->_data._scaleX) * alpha; + bone->_scaleY += (y - bone->_data._scaleY) * alpha; + } + } else { + switch (blend) { + case MixBlend_Setup: + bx = MathUtil::abs(bone->_data._scaleX) * MathUtil::sign(x); + by = MathUtil::abs(bone->_data._scaleY) * MathUtil::sign(y); + bone->_scaleX = bx + (x - bx) * alpha; + bone->_scaleY = by + (y - by) * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bx = MathUtil::abs(bone->_scaleX) * MathUtil::sign(x); + by = MathUtil::abs(bone->_scaleY) * MathUtil::sign(y); + bone->_scaleX = bx + (x - bx) * alpha; + bone->_scaleY = by + (y - by) * alpha; + break; + case MixBlend_Add: + bone->_scaleX += (x - bone->_data._scaleX) * alpha; + bone->_scaleY += (y - bone->_data._scaleY) * alpha; + } + } + } +} + +RTTI_IMPL(ScaleXTimeline, CurveTimeline1) + +ScaleXTimeline::ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ScaleX << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +ScaleXTimeline::~ScaleXTimeline() {} + +void ScaleXTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + Bone *bone = skeleton._bones[_boneIndex]; + if (bone->_active) bone->_scaleX = getScaleValue(time, alpha, blend, direction, bone->_scaleX, bone->_data._scaleX); +} + +RTTI_IMPL(ScaleYTimeline, CurveTimeline1) + +ScaleYTimeline::ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ScaleY << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +ScaleYTimeline::~ScaleYTimeline() {} + +void ScaleYTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + + Bone *bone = skeleton._bones[_boneIndex]; + if (bone->_active) bone->_scaleY = getScaleValue(time, alpha, blend, direction, bone->_scaleX, bone->_data._scaleY); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Sequence.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Sequence.cpp new file mode 100644 index 0000000..f690dce --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Sequence.cpp @@ -0,0 +1,96 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include + +using namespace spine; + +Sequence::Sequence(int count) : _id(Sequence::getNextID()), + _regions(), + _start(0), + _digits(0), + _setupIndex(0) { + _regions.setSize(count, NULL); +} + +Sequence::~Sequence() { +} + +Sequence *Sequence::copy() { + Sequence *copy = new (__FILE__, __LINE__) Sequence((int) _regions.size()); + for (size_t i = 0; i < _regions.size(); i++) { + copy->_regions[i] = _regions[i]; + } + copy->_start = _start; + copy->_digits = _digits; + copy->_setupIndex = _setupIndex; + return copy; +} + +void Sequence::apply(Slot *slot, Attachment *attachment) { + int index = slot->getSequenceIndex(); + if (index == -1) index = _setupIndex; + if (index >= (int) _regions.size()) index = (int) _regions.size() - 1; + TextureRegion *region = _regions[index]; + + if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) { + RegionAttachment *regionAttachment = static_cast(attachment); + if (regionAttachment->getRegion() != region) { + regionAttachment->setRegion(region); + regionAttachment->updateRegion(); + } + } + + if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) { + MeshAttachment *meshAttachment = static_cast(attachment); + if (meshAttachment->getRegion() != region) { + meshAttachment->setRegion(region); + meshAttachment->updateRegion(); + } + } +} + +String Sequence::getPath(const String &basePath, int index) { + String result(basePath); + String frame; + frame.append(_start + index); + for (int i = _digits - (int) frame.length(); i > 0; i--) + result.append("0"); + result.append(frame); + return result; +} + +int Sequence::getNextID() { + static int _nextID = 0; + return _nextID; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp new file mode 100644 index 0000000..f00bd82 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp @@ -0,0 +1,129 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(SequenceTimeline, Timeline) + +SequenceTimeline::SequenceTimeline(size_t frameCount, int slotIndex, Attachment *attachment) : Timeline(frameCount, ENTRIES), _slotIndex(slotIndex), _attachment(attachment) { + int sequenceId = 0; + if (attachment->getRTTI().instanceOf(RegionAttachment::rtti)) sequenceId = ((RegionAttachment *) attachment)->getSequence()->getId(); + if (attachment->getRTTI().instanceOf(MeshAttachment::rtti)) sequenceId = ((MeshAttachment *) attachment)->getSequence()->getId(); + PropertyId ids[] = {((PropertyId) Property_Sequence << 32) | ((slotIndex << 16 | sequenceId) & 0xffffffff)}; + setPropertyIds(ids, 1); +} + +SequenceTimeline::~SequenceTimeline() { +} + +void SequenceTimeline::setFrame(int frame, float time, SequenceMode mode, int index, float delay) { + Vector &frames = this->_frames; + frame *= ENTRIES; + frames[frame] = time; + frames[frame + MODE] = mode | (index << 4); + frames[frame + DELAY] = delay; +} + +void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction) { + SP_UNUSED(alpha); + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Slot *slot = skeleton.getSlots()[_slotIndex]; + if (!slot->getBone().isActive()) return; + Attachment *slotAttachment = slot->getAttachment(); + if (slotAttachment != _attachment) { + if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti) || ((VertexAttachment *) slotAttachment)->getTimelineAttachment() != _attachment) return; + } + Sequence *sequence = NULL; + if (_attachment->getRTTI().instanceOf(RegionAttachment::rtti)) sequence = ((RegionAttachment *) _attachment)->getSequence(); + if (_attachment->getRTTI().instanceOf(MeshAttachment::rtti)) sequence = ((MeshAttachment *) _attachment)->getSequence(); + if (!sequence) return; + + if (direction == MixDirection_Out) { + if (blend == MixBlend_Setup) slot->setSequenceIndex(-1); + return; + } + + Vector &frames = this->_frames; + if (time < frames[0]) {// Time is before first frame. + if (blend == MixBlend_Setup || blend == MixBlend_First) slot->setSequenceIndex(-1); + return; + } + + int i = Animation::search(frames, time, ENTRIES); + float before = frames[i]; + int modeAndIndex = (int) frames[i + MODE]; + float delay = frames[i + DELAY]; + + int index = modeAndIndex >> 4, count = (int) sequence->getRegions().size(); + int mode = modeAndIndex & 0xf; + if (mode != SequenceMode::hold) { + index += (int) (((time - before) / delay + 0.0001)); + switch (mode) { + case SequenceMode::once: + index = MathUtil::min(count - 1, index); + break; + case SequenceMode::loop: + index %= count; + break; + case SequenceMode::pingpong: { + int n = (count << 1) - 2; + index = n == 0 ? 0 : index % n; + if (index >= count) index = n - index; + break; + } + case SequenceMode::onceReverse: + index = MathUtil::max(count - 1 - index, 0); + break; + case SequenceMode::loopReverse: + index = count - 1 - (index % count); + break; + case SequenceMode::pingpongReverse: { + int n = (count << 1) - 2; + index = n == 0 ? 0 : (index + count - 1) % n; + if (index >= count) index = n - index; + } + } + } + slot->setSequenceIndex(index); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp new file mode 100644 index 0000000..027f70c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -0,0 +1,162 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(ShearTimeline, CurveTimeline2) + +ShearTimeline::ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ShearX << 32) | boneIndex, + ((PropertyId) Property_ShearY << 32) | boneIndex}; + setPropertyIds(ids, 2); +} + +ShearTimeline::~ShearTimeline() { +} + +void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_shearX = bone->_data._shearX; + bone->_shearY = bone->_data._shearY; + return; + case MixBlend_First: + bone->_shearX += (bone->_data._shearX - bone->_shearX) * alpha; + bone->_shearY += (bone->_data._shearY - bone->_shearY) * alpha; + default: { + } + } + return; + } + + float x, y; + int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES); + int curveType = (int) _curves[i / CurveTimeline2::ENTRIES]; + switch (curveType) { + case CurveTimeline2::LINEAR: { + float before = _frames[i]; + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before); + x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t; + y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t; + break; + } + case CurveTimeline2::STEPPED: { + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + break; + } + default: { + x = getBezierValue(time, i, CurveTimeline2::VALUE1, curveType - CurveTimeline2::BEZIER); + y = getBezierValue(time, i, CurveTimeline2::VALUE2, + curveType + CurveTimeline2::BEZIER_SIZE - CurveTimeline2::BEZIER); + } + } + + switch (blend) { + case MixBlend_Setup: + bone->_shearX = bone->_data._shearX + x * alpha; + bone->_shearY = bone->_data._shearY + y * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_shearX += (bone->_data._shearX + x - bone->_shearX) * alpha; + bone->_shearY += (bone->_data._shearY + y - bone->_shearY) * alpha; + break; + case MixBlend_Add: + bone->_shearX += x * alpha; + bone->_shearY += y * alpha; + } +} + +RTTI_IMPL(ShearXTimeline, CurveTimeline1) + +ShearXTimeline::ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ShearX << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +ShearXTimeline::~ShearXTimeline() { +} + +void ShearXTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (bone->_active) bone->_shearX = getRelativeValue(time, alpha, blend, bone->_shearX, bone->_data._shearX); +} + +RTTI_IMPL(ShearYTimeline, CurveTimeline1) + +ShearYTimeline::ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_ShearX << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +ShearYTimeline::~ShearYTimeline() { +} + +void ShearYTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (bone->_active) bone->_shearY = getRelativeValue(time, alpha, blend, bone->_shearY, bone->_data._shearY); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Skeleton.cpp new file mode 100644 index 0000000..84292a9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -0,0 +1,774 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace spine; + +Skeleton::Skeleton(SkeletonData *skeletonData) + : _data(skeletonData), _skin(NULL), _color(1, 1, 1, 1), _scaleX(1), + _scaleY(1), _x(0), _y(0), _time(0) { + _bones.ensureCapacity(_data->getBones().size()); + for (size_t i = 0; i < _data->getBones().size(); ++i) { + BoneData *data = _data->getBones()[i]; + + Bone *bone; + if (data->getParent() == NULL) { + bone = new (__FILE__, __LINE__) Bone(*data, *this, NULL); + } else { + Bone *parent = _bones[data->getParent()->getIndex()]; + bone = new (__FILE__, __LINE__) Bone(*data, *this, parent); + parent->getChildren().add(bone); + } + + _bones.add(bone); + } + + _slots.ensureCapacity(_data->getSlots().size()); + _drawOrder.ensureCapacity(_data->getSlots().size()); + for (size_t i = 0; i < _data->getSlots().size(); ++i) { + SlotData *data = _data->getSlots()[i]; + + Bone *bone = _bones[data->getBoneData().getIndex()]; + Slot *slot = new (__FILE__, __LINE__) Slot(*data, *bone); + + _slots.add(slot); + _drawOrder.add(slot); + } + + _ikConstraints.ensureCapacity(_data->getIkConstraints().size()); + for (size_t i = 0; i < _data->getIkConstraints().size(); ++i) { + IkConstraintData *data = _data->getIkConstraints()[i]; + + IkConstraint *constraint = + new (__FILE__, __LINE__) IkConstraint(*data, *this); + + _ikConstraints.add(constraint); + } + + _transformConstraints.ensureCapacity(_data->getTransformConstraints().size()); + for (size_t i = 0; i < _data->getTransformConstraints().size(); ++i) { + TransformConstraintData *data = _data->getTransformConstraints()[i]; + + TransformConstraint *constraint = + new (__FILE__, __LINE__) TransformConstraint(*data, *this); + + _transformConstraints.add(constraint); + } + + _pathConstraints.ensureCapacity(_data->getPathConstraints().size()); + for (size_t i = 0; i < _data->getPathConstraints().size(); ++i) { + PathConstraintData *data = _data->getPathConstraints()[i]; + + PathConstraint *constraint = + new (__FILE__, __LINE__) PathConstraint(*data, *this); + + _pathConstraints.add(constraint); + } + + _physicsConstraints.ensureCapacity(_data->getPhysicsConstraints().size()); + for (size_t i = 0; i < _data->getPhysicsConstraints().size(); ++i) { + PhysicsConstraintData *data = _data->getPhysicsConstraints()[i]; + + PhysicsConstraint *constraint = + new (__FILE__, __LINE__) PhysicsConstraint(*data, *this); + + _physicsConstraints.add(constraint); + } + + updateCache(); +} + +Skeleton::~Skeleton() { + ContainerUtil::cleanUpVectorOfPointers(_bones); + ContainerUtil::cleanUpVectorOfPointers(_slots); + ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); + ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); + ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); + ContainerUtil::cleanUpVectorOfPointers(_physicsConstraints); +} + +void Skeleton::updateCache() { + _updateCache.clear(); + + for (size_t i = 0, n = _bones.size(); i < n; ++i) { + Bone *bone = _bones[i]; + bone->_sorted = bone->_data.isSkinRequired(); + bone->_active = !bone->_sorted; + } + + if (_skin) { + Vector &skinBones = _skin->getBones(); + for (size_t i = 0, n = skinBones.size(); i < n; i++) { + Bone *bone = _bones[skinBones[i]->getIndex()]; + do { + bone->_sorted = false; + bone->_active = true; + bone = bone->_parent; + } while (bone); + } + } + + size_t ikCount = _ikConstraints.size(); + size_t transformCount = _transformConstraints.size(); + size_t pathCount = _pathConstraints.size(); + size_t physicsCount = _physicsConstraints.size(); + size_t constraintCount = ikCount + transformCount + pathCount + physicsCount; + + size_t i = 0; +continue_outer: + for (; i < constraintCount; ++i) { + for (size_t ii = 0; ii < ikCount; ++ii) { + IkConstraint *constraint = _ikConstraints[ii]; + if (constraint->getData().getOrder() == i) { + sortIkConstraint(constraint); + i++; + goto continue_outer; + } + } + + for (size_t ii = 0; ii < transformCount; ++ii) { + TransformConstraint *constraint = _transformConstraints[ii]; + if (constraint->getData().getOrder() == i) { + sortTransformConstraint(constraint); + i++; + goto continue_outer; + } + } + + for (size_t ii = 0; ii < pathCount; ++ii) { + PathConstraint *constraint = _pathConstraints[ii]; + if (constraint->getData().getOrder() == i) { + sortPathConstraint(constraint); + i++; + goto continue_outer; + } + } + + for (size_t ii = 0; ii < physicsCount; ++ii) { + PhysicsConstraint *constraint = _physicsConstraints[ii]; + if (constraint->getData().getOrder() == i) { + sortPhysicsConstraint(constraint); + i++; + goto continue_outer; + } + } + } + + size_t n = _bones.size(); + for (i = 0; i < n; ++i) { + sortBone(_bones[i]); + } +} + +void Skeleton::printUpdateCache() { + for (size_t i = 0; i < _updateCache.size(); i++) { + Updatable *updatable = _updateCache[i]; + if (updatable->getRTTI().isExactly(Bone::rtti)) { + printf("bone %s\n", ((Bone *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(TransformConstraint::rtti)) { + printf("transform constraint %s\n", + ((TransformConstraint *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(IkConstraint::rtti)) { + printf("ik constraint %s\n", + ((IkConstraint *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(PathConstraint::rtti)) { + printf("path constraint %s\n", + ((PathConstraint *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(PhysicsConstraint::rtti)) { + printf("physics constraint %s\n", + ((PhysicsConstraint *) updatable)->getData().getName().buffer()); + } + } +} + +void Skeleton::updateWorldTransform(Physics physics) { + for (size_t i = 0, n = _bones.size(); i < n; i++) { + Bone *bone = _bones[i]; + bone->_ax = bone->_x; + bone->_ay = bone->_y; + bone->_arotation = bone->_rotation; + bone->_ascaleX = bone->_scaleX; + bone->_ascaleY = bone->_scaleY; + bone->_ashearX = bone->_shearX; + bone->_ashearY = bone->_shearY; + } + + for (size_t i = 0, n = _updateCache.size(); i < n; ++i) { + Updatable *updatable = _updateCache[i]; + updatable->update(physics); + } +} + +void Skeleton::updateWorldTransform(Physics physics, Bone *parent) { + // Apply the parent bone transform to the root bone. The root bone always + // inherits scale, rotation and reflection. + Bone *rootBone = getRootBone(); + float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d; + rootBone->_worldX = pa * _x + pb * _y + parent->_worldX; + rootBone->_worldY = pc * _x + pd * _y + parent->_worldY; + + float rx = (rootBone->_rotation + rootBone->_shearX) * MathUtil::Deg_Rad; + float ry = (rootBone->_rotation + 90 + rootBone->_shearY) * MathUtil::Deg_Rad; + float la = MathUtil::cos(rx) * rootBone->_scaleX; + float lb = MathUtil::cos(ry) * rootBone->_scaleY; + float lc = MathUtil::sin(rx) * rootBone->_scaleX; + float ld = MathUtil::sin(ry) * rootBone->_scaleY; + rootBone->_a = (pa * la + pb * lc) * _scaleX; + rootBone->_b = (pa * lb + pb * ld) * _scaleX; + rootBone->_c = (pc * la + pd * lc) * _scaleY; + rootBone->_d = (pc * lb + pd * ld) * _scaleY; + + // Update everything except root bone. + Bone *rb = getRootBone(); + for (size_t i = 0, n = _updateCache.size(); i < n; i++) { + Updatable *updatable = _updateCache[i]; + if (updatable != rb) + updatable->update(physics); + } +} + +void Skeleton::setToSetupPose() { + setBonesToSetupPose(); + setSlotsToSetupPose(); +} + +void Skeleton::setBonesToSetupPose() { + for (size_t i = 0, n = _bones.size(); i < n; ++i) { + _bones[i]->setToSetupPose(); + } + + for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) { + _ikConstraints[i]->setToSetupPose(); + } + + for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) { + _transformConstraints[i]->setToSetupPose(); + } + + for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) { + _pathConstraints[i]->setToSetupPose(); + } + + for (size_t i = 0, n = _physicsConstraints.size(); i < n; ++i) { + _physicsConstraints[i]->setToSetupPose(); + } +} + +void Skeleton::setSlotsToSetupPose() { + _drawOrder.clear(); + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + _drawOrder.add(_slots[i]); + } + + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + _slots[i]->setToSetupPose(); + } +} + +Bone *Skeleton::findBone(const String &boneName) { + return ContainerUtil::findWithDataName(_bones, boneName); +} + +Slot *Skeleton::findSlot(const String &slotName) { + return ContainerUtil::findWithDataName(_slots, slotName); +} + +void Skeleton::setSkin(const String &skinName) { + Skin *foundSkin = skinName.isEmpty() ? NULL : _data->findSkin(skinName); + setSkin(foundSkin); +} + +void Skeleton::setSkin(Skin *newSkin) { + if (_skin == newSkin) + return; + if (newSkin != NULL) { + if (_skin != NULL) { + Skeleton &thisRef = *this; + newSkin->attachAll(thisRef, *_skin); + } else { + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + Slot *slotP = _slots[i]; + Slot &slot = *slotP; + const String &name = slot._data.getAttachmentName(); + if (name.length() > 0) { + Attachment *attachment = newSkin->getAttachment(i, name); + if (attachment != NULL) { + slot.setAttachment(attachment); + } + } + } + } + } + + _skin = newSkin; + updateCache(); +} + +Attachment *Skeleton::getAttachment(const String &slotName, + const String &attachmentName) { + return getAttachment(_data->findSlot(slotName)->getIndex(), attachmentName); +} + +Attachment *Skeleton::getAttachment(int slotIndex, + const String &attachmentName) { + if (attachmentName.isEmpty()) + return NULL; + + if (_skin != NULL) { + Attachment *attachment = _skin->getAttachment(slotIndex, attachmentName); + if (attachment != NULL) { + return attachment; + } + } + + return _data->getDefaultSkin() != NULL + ? _data->getDefaultSkin()->getAttachment(slotIndex, attachmentName) + : NULL; +} + +void Skeleton::setAttachment(const String &slotName, + const String &attachmentName) { + assert(slotName.length() > 0); + + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + Slot *slot = _slots[i]; + if (slot->_data.getName() == slotName) { + Attachment *attachment = NULL; + if (attachmentName.length() > 0) { + attachment = getAttachment((int) i, attachmentName); + + assert(attachment != NULL); + } + + slot->setAttachment(attachment); + + return; + } + } + + printf("Slot not found: %s", slotName.buffer()); + + assert(false); +} + +IkConstraint *Skeleton::findIkConstraint(const String &constraintName) { + assert(constraintName.length() > 0); + + for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) { + IkConstraint *ikConstraint = _ikConstraints[i]; + if (ikConstraint->_data.getName() == constraintName) { + return ikConstraint; + } + } + return NULL; +} + +TransformConstraint * +Skeleton::findTransformConstraint(const String &constraintName) { + assert(constraintName.length() > 0); + + for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) { + TransformConstraint *transformConstraint = _transformConstraints[i]; + if (transformConstraint->_data.getName() == constraintName) { + return transformConstraint; + } + } + + return NULL; +} + +PathConstraint *Skeleton::findPathConstraint(const String &constraintName) { + assert(constraintName.length() > 0); + + for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) { + PathConstraint *constraint = _pathConstraints[i]; + if (constraint->_data.getName() == constraintName) { + return constraint; + } + } + + return NULL; +} + +PhysicsConstraint * +Skeleton::findPhysicsConstraint(const String &constraintName) { + assert(constraintName.length() > 0); + + for (size_t i = 0, n = _physicsConstraints.size(); i < n; ++i) { + PhysicsConstraint *constraint = _physicsConstraints[i]; + if (constraint->_data.getName() == constraintName) { + return constraint; + } + } + + return NULL; +} + +void Skeleton::getBounds(float &outX, float &outY, float &outWidth, + float &outHeight, Vector &outVertexBuffer) { + getBounds(outX, outY, outWidth, outHeight, outVertexBuffer, NULL); +} + +void Skeleton::getBounds(float &outX, float &outY, float &outWidth, + float &outHeight, Vector &outVertexBuffer, SkeletonClipping *clipper) { + static unsigned short quadIndices[] = {0, 1, 2, 2, 3, 0}; + float minX = FLT_MAX; + float minY = FLT_MAX; + float maxX = -FLT_MAX; + float maxY = -FLT_MAX; + + for (size_t i = 0; i < _drawOrder.size(); ++i) { + Slot *slot = _drawOrder[i]; + if (!slot->_bone._active) + continue; + size_t verticesLength = 0; + Attachment *attachment = slot->getAttachment(); + unsigned short *triangles = NULL; + size_t trianglesLength = 0; + + if (attachment != NULL && + attachment->getRTTI().instanceOf(RegionAttachment::rtti)) { + RegionAttachment *regionAttachment = + static_cast(attachment); + + verticesLength = 8; + if (outVertexBuffer.size() < 8) { + outVertexBuffer.setSize(8, 0); + } + regionAttachment->computeWorldVertices(*slot, outVertexBuffer, 0); + triangles = quadIndices; + trianglesLength = 6; + } else if (attachment != NULL && + attachment->getRTTI().instanceOf(MeshAttachment::rtti)) { + MeshAttachment *mesh = static_cast(attachment); + + verticesLength = mesh->getWorldVerticesLength(); + if (outVertexBuffer.size() < verticesLength) { + outVertexBuffer.setSize(verticesLength, 0); + } + + mesh->computeWorldVertices(*slot, 0, verticesLength, + outVertexBuffer.buffer(), 0); + triangles = mesh->getTriangles().buffer(); + trianglesLength = mesh->getTriangles().size(); + } else if (attachment != NULL && + attachment->getRTTI().instanceOf(ClippingAttachment::rtti) && clipper != NULL) { + clipper->clipStart(*slot, static_cast(attachment)); + continue; + } + + if (verticesLength > 0) { + float *vertices = outVertexBuffer.buffer(); + if (clipper != NULL && clipper->isClipping()) { + clipper->clipTriangles(outVertexBuffer.buffer(), triangles, trianglesLength); + vertices = clipper->getClippedVertices().buffer(); + verticesLength = clipper->getClippedVertices().size(); + } + for (size_t ii = 0; ii < verticesLength; ii += 2) { + float vx = vertices[ii]; + float vy = vertices[ii + 1]; + + minX = MathUtil::min(minX, vx); + minY = MathUtil::min(minY, vy); + maxX = MathUtil::max(maxX, vx); + maxY = MathUtil::max(maxY, vy); + } + } + if (clipper != NULL) clipper->clipEnd(*slot); + } + if (clipper != NULL) clipper->clipEnd(); + + outX = minX; + outY = minY; + outWidth = maxX - minX; + outHeight = maxY - minY; +} + +Bone *Skeleton::getRootBone() { return _bones.size() == 0 ? NULL : _bones[0]; } + +SkeletonData *Skeleton::getData() { return _data; } + +Vector &Skeleton::getBones() { return _bones; } + +Vector &Skeleton::getUpdateCacheList() { return _updateCache; } + +Vector &Skeleton::getSlots() { return _slots; } + +Vector &Skeleton::getDrawOrder() { return _drawOrder; } + +Vector &Skeleton::getIkConstraints() { return _ikConstraints; } + +Vector &Skeleton::getPathConstraints() { + return _pathConstraints; +} + +Vector &Skeleton::getTransformConstraints() { + return _transformConstraints; +} + +Vector &Skeleton::getPhysicsConstraints() { + return _physicsConstraints; +} + +Skin *Skeleton::getSkin() { return _skin; } + +Color &Skeleton::getColor() { return _color; } + +void Skeleton::setPosition(float x, float y) { + _x = x; + _y = y; +} + +float Skeleton::getX() { return _x; } + +void Skeleton::setX(float inValue) { _x = inValue; } + +float Skeleton::getY() { return _y; } + +void Skeleton::setY(float inValue) { _y = inValue; } + +float Skeleton::getScaleX() { return _scaleX; } + +void Skeleton::setScaleX(float inValue) { _scaleX = inValue; } + +float Skeleton::getScaleY() { return _scaleY * (Bone::isYDown() ? -1 : 1); } + +void Skeleton::setScaleY(float inValue) { _scaleY = inValue; } + +void Skeleton::sortIkConstraint(IkConstraint *constraint) { + constraint->_active = + constraint->_target->_active && + (!constraint->_data.isSkinRequired() || + (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) + return; + + Bone *target = constraint->getTarget(); + sortBone(target); + + Vector &constrained = constraint->getBones(); + Bone *parent = constrained[0]; + sortBone(parent); + + if (constrained.size() == 1) { + _updateCache.add(constraint); + sortReset(parent->_children); + } else { + Bone *child = constrained[constrained.size() - 1]; + sortBone(child); + + _updateCache.add(constraint); + + sortReset(parent->_children); + child->_sorted = true; + } +} + +void Skeleton::sortPathConstraint(PathConstraint *constraint) { + constraint->_active = + constraint->_target->_bone._active && + (!constraint->_data.isSkinRequired() || + (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) + return; + + Slot *slot = constraint->getTarget(); + int slotIndex = slot->getData().getIndex(); + Bone &slotBone = slot->getBone(); + if (_skin != NULL) + sortPathConstraintAttachment(_skin, slotIndex, slotBone); + if (_data->_defaultSkin != NULL && _data->_defaultSkin != _skin) + sortPathConstraintAttachment(_data->_defaultSkin, slotIndex, slotBone); + for (size_t ii = 0, nn = _data->_skins.size(); ii < nn; ii++) + sortPathConstraintAttachment(_data->_skins[ii], slotIndex, slotBone); + + Attachment *attachment = slot->getAttachment(); + if (attachment != NULL && + attachment->getRTTI().instanceOf(PathAttachment::rtti)) + sortPathConstraintAttachment(attachment, slotBone); + + Vector &constrained = constraint->getBones(); + size_t boneCount = constrained.size(); + for (size_t i = 0; i < boneCount; ++i) { + sortBone(constrained[i]); + } + + _updateCache.add(constraint); + + for (size_t i = 0; i < boneCount; i++) + sortReset(constrained[i]->getChildren()); + for (size_t i = 0; i < boneCount; i++) + constrained[i]->_sorted = true; +} + +void Skeleton::sortTransformConstraint(TransformConstraint *constraint) { + constraint->_active = + constraint->_target->_active && + (!constraint->_data.isSkinRequired() || + (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) + return; + + sortBone(constraint->getTarget()); + + Vector &constrained = constraint->getBones(); + size_t boneCount = constrained.size(); + if (constraint->_data.isLocal()) { + for (size_t i = 0; i < boneCount; i++) { + Bone *child = constrained[i]; + sortBone(child->getParent()); + sortBone(child); + } + } else { + for (size_t i = 0; i < boneCount; ++i) { + sortBone(constrained[i]); + } + } + + _updateCache.add(constraint); + + for (size_t i = 0; i < boneCount; ++i) + sortReset(constrained[i]->getChildren()); + for (size_t i = 0; i < boneCount; ++i) + constrained[i]->_sorted = true; +} + +void Skeleton::sortPhysicsConstraint(PhysicsConstraint *constraint) { + Bone *bone = constraint->getBone(); + constraint->_active = + bone->_active && + (!constraint->_data.isSkinRequired() || + (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) + return; + + sortBone(bone); + _updateCache.add(constraint); + sortReset(bone->getChildren()); + bone->_sorted = true; +} + +void Skeleton::sortPathConstraintAttachment(Skin *skin, size_t slotIndex, + Bone &slotBone) { + Skin::AttachmentMap::Entries attachments = skin->getAttachments(); + + while (attachments.hasNext()) { + Skin::AttachmentMap::Entry entry = attachments.next(); + if (entry._slotIndex == slotIndex) { + Attachment *value = entry._attachment; + sortPathConstraintAttachment(value, slotBone); + } + } +} + +void Skeleton::sortPathConstraintAttachment(Attachment *attachment, + Bone &slotBone) { + if (attachment == NULL || + !attachment->getRTTI().instanceOf(PathAttachment::rtti)) + return; + Vector &pathBones = + static_cast(attachment)->getBones(); + if (pathBones.size() == 0) + sortBone(&slotBone); + else { + for (size_t i = 0, n = pathBones.size(); i < n;) { + size_t nn = pathBones[i++]; + nn += i; + while (i < nn) { + sortBone(_bones[pathBones[i++]]); + } + } + } +} + +void Skeleton::sortBone(Bone *bone) { + if (bone->_sorted) + return; + Bone *parent = bone->_parent; + if (parent != NULL) + sortBone(parent); + bone->_sorted = true; + _updateCache.add(bone); +} + +void Skeleton::sortReset(Vector &bones) { + for (size_t i = 0, n = bones.size(); i < n; ++i) { + Bone *bone = bones[i]; + if (!bone->_active) + continue; + if (bone->_sorted) + sortReset(bone->getChildren()); + bone->_sorted = false; + } +} + +float Skeleton::getTime() { return _time; } + +void Skeleton::setTime(float time) { _time = time; } + +void Skeleton::update(float delta) { _time += delta; } + +void Skeleton::physicsTranslate(float x, float y) { + for (int i = 0; i < (int) _physicsConstraints.size(); i++) { + _physicsConstraints[i]->translate(x, y); + } +} + +void Skeleton::physicsRotate(float x, float y, float degrees) { + for (int i = 0; i < (int) _physicsConstraints.size(); i++) { + _physicsConstraints[i]->rotate(x, y, degrees); + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp new file mode 100644 index 0000000..a82ada1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -0,0 +1,1490 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +SkeletonBinary::SkeletonBinary(Atlas *atlasArray) : _attachmentLoader( + new (__FILE__, __LINE__) AtlasAttachmentLoader(atlasArray)), + _error(), _scale(1), _ownsLoader(true) { +} + +SkeletonBinary::SkeletonBinary(AttachmentLoader *attachmentLoader, bool ownsLoader) : _attachmentLoader( + attachmentLoader), + _error(), + _scale(1), + _ownsLoader(ownsLoader) { + assert(_attachmentLoader != NULL); +} + +SkeletonBinary::~SkeletonBinary() { + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + if (_ownsLoader) delete _attachmentLoader; +} + +SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, const int length) { + bool nonessential; + SkeletonData *skeletonData; + + DataInput *input = new (__FILE__, __LINE__) DataInput(); + input->cursor = binary; + input->end = binary + length; + + _linkedMeshes.clear(); + + skeletonData = new (__FILE__, __LINE__) SkeletonData(); + + char buffer[16] = {0}; + int lowHash = readInt(input); + int hightHash = readInt(input); + String hashString; + snprintf(buffer, 16, "%x", hightHash); + hashString.append(buffer); + snprintf(buffer, 16, "%x", lowHash); + hashString.append(buffer); + skeletonData->_hash = hashString; + + char *skeletonDataVersion = readString(input); + skeletonData->_version.own(skeletonDataVersion); + + if (!skeletonData->_version.startsWith(SPINE_VERSION_STRING)) { + char errorMsg[255]; + snprintf(errorMsg, 255, "Skeleton version %s does not match runtime version %s", skeletonData->_version.buffer(), SPINE_VERSION_STRING); + setError(errorMsg, ""); + delete input; + delete skeletonData; + return NULL; + } + + skeletonData->_x = readFloat(input); + skeletonData->_y = readFloat(input); + skeletonData->_width = readFloat(input); + skeletonData->_height = readFloat(input); + skeletonData->_referenceScale = readFloat(input) * this->_scale; + + nonessential = readBoolean(input); + + if (nonessential) { + skeletonData->_fps = readFloat(input); + skeletonData->_imagesPath.own(readString(input)); + skeletonData->_audioPath.own(readString(input)); + } + + int numStrings = readVarint(input, true); + for (int i = 0; i < numStrings; i++) + skeletonData->_strings.add(readString(input)); + + /* Bones. */ + int numBones = readVarint(input, true); + skeletonData->_bones.setSize(numBones, 0); + for (int i = 0; i < numBones; ++i) { + const char *name = readString(input); + BoneData *parent = i == 0 ? 0 : skeletonData->_bones[readVarint(input, true)]; + BoneData *data = new (__FILE__, __LINE__) BoneData(i, String(name, true), parent); + data->_rotation = readFloat(input); + data->_x = readFloat(input) * _scale; + data->_y = readFloat(input) * _scale; + data->_scaleX = readFloat(input); + data->_scaleY = readFloat(input); + data->_shearX = readFloat(input); + data->_shearY = readFloat(input); + data->_length = readFloat(input) * _scale; + data->_inherit = static_cast(readVarint(input, true)); + data->_skinRequired = readBoolean(input); + if (nonessential) { + readColor(input, data->getColor()); + data->_icon.own(readString(input)); + data->_visible = readBoolean(input); + } + skeletonData->_bones[i] = data; + } + + /* Slots. */ + int slotsCount = readVarint(input, true); + skeletonData->_slots.setSize(slotsCount, 0); + for (int i = 0; i < slotsCount; ++i) { + String slotName = String(readString(input), true); + BoneData *boneData = skeletonData->_bones[readVarint(input, true)]; + SlotData *slotData = new (__FILE__, __LINE__) SlotData(i, slotName, *boneData); + + readColor(input, slotData->getColor()); + unsigned char a = readByte(input); + unsigned char r = readByte(input); + unsigned char g = readByte(input); + unsigned char b = readByte(input); + if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) { + slotData->getDarkColor().set(r / 255.0f, g / 255.0f, b / 255.0f, 1); + slotData->setHasDarkColor(true); + } + slotData->_attachmentName = readStringRef(input, skeletonData); + slotData->_blendMode = static_cast(readVarint(input, true)); + if (nonessential) { + slotData->_visible = readBoolean(input); + } + skeletonData->_slots[i] = slotData; + } + + /* IK constraints. */ + int ikConstraintsCount = readVarint(input, true); + skeletonData->_ikConstraints.setSize(ikConstraintsCount, 0); + for (int i = 0; i < ikConstraintsCount; ++i) { + const char *name = readString(input); + IkConstraintData *data = new (__FILE__, __LINE__) IkConstraintData(String(name, true)); + data->setOrder(readVarint(input, true)); + int bonesCount = readVarint(input, true); + data->_bones.setSize(bonesCount, 0); + for (int ii = 0; ii < bonesCount; ++ii) + data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; + data->_target = skeletonData->_bones[readVarint(input, true)]; + int flags = readByte(input); + data->_skinRequired = (flags & 1) != 0; + data->_bendDirection = (flags & 2) != 0 ? 1 : -1; + data->_compress = (flags & 4) != 0; + data->_stretch = (flags & 8) != 0; + data->_uniform = (flags & 16) != 0; + if ((flags & 32) != 0) data->_mix = (flags & 64) != 0 ? readFloat(input) : 1; + if ((flags & 128) != 0) data->_softness = readFloat(input) * _scale; + + skeletonData->_ikConstraints[i] = data; + } + + /* Transform constraints. */ + int transformConstraintsCount = readVarint(input, true); + skeletonData->_transformConstraints.setSize(transformConstraintsCount, 0); + for (int i = 0; i < transformConstraintsCount; ++i) { + const char *name = readString(input); + TransformConstraintData *data = new (__FILE__, __LINE__) TransformConstraintData(String(name, true)); + data->setOrder(readVarint(input, true)); + int bonesCount = readVarint(input, true); + data->_bones.setSize(bonesCount, 0); + for (int ii = 0; ii < bonesCount; ++ii) + data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; + data->_target = skeletonData->_bones[readVarint(input, true)]; + int flags = readByte(input); + data->_skinRequired = (flags & 1) != 0; + data->_local = (flags & 2) != 0; + data->_relative = (flags & 4) != 0; + if ((flags & 8) != 0) data->_offsetRotation = readFloat(input); + if ((flags & 16) != 0) data->_offsetX = readFloat(input) * _scale; + if ((flags & 32) != 0) data->_offsetY = readFloat(input) * _scale; + if ((flags & 64) != 0) data->_offsetScaleX = readFloat(input); + if ((flags & 128) != 0) data->_offsetScaleY = readFloat(input); + flags = readByte(input); + if ((flags & 1) != 0) data->_offsetShearY = readFloat(input); + if ((flags & 2) != 0) data->_mixRotate = readFloat(input); + if ((flags & 4) != 0) data->_mixX = readFloat(input); + if ((flags & 8) != 0) data->_mixY = readFloat(input); + if ((flags & 16) != 0) data->_mixScaleX = readFloat(input); + if ((flags & 32) != 0) data->_mixScaleY = readFloat(input); + if ((flags & 64) != 0) data->_mixShearY = readFloat(input); + + skeletonData->_transformConstraints[i] = data; + } + + /* Path constraints */ + int pathConstraintsCount = readVarint(input, true); + skeletonData->_pathConstraints.setSize(pathConstraintsCount, 0); + for (int i = 0; i < pathConstraintsCount; ++i) { + const char *name = readString(input); + PathConstraintData *data = new (__FILE__, __LINE__) PathConstraintData(String(name, true)); + data->setOrder(readVarint(input, true)); + data->setSkinRequired(readBoolean(input)); + int bonesCount = readVarint(input, true); + data->_bones.setSize(bonesCount, 0); + for (int ii = 0; ii < bonesCount; ++ii) + data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; + data->_target = skeletonData->_slots[readVarint(input, true)]; + int flags = readByte(input); + data->_positionMode = (PositionMode) (flags & 1); + data->_spacingMode = (SpacingMode) ((flags >> 1) & 3); + data->_rotateMode = (RotateMode) ((flags >> 3) & 3); + if ((flags & 128) != 0) data->_offsetRotation = readFloat(input); + data->_position = readFloat(input); + if (data->_positionMode == PositionMode_Fixed) data->_position *= _scale; + data->_spacing = readFloat(input); + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) + data->_spacing *= _scale; + data->_mixRotate = readFloat(input); + data->_mixX = readFloat(input); + data->_mixY = readFloat(input); + skeletonData->_pathConstraints[i] = data; + } + + // Physics constraints. + int physicsConstraintsCount = readVarint(input, true); + skeletonData->_physicsConstraints.setSize(physicsConstraintsCount, 0); + for (int i = 0; i < physicsConstraintsCount; i++) { + const char *name = readString(input); + PhysicsConstraintData *data = new (__FILE__, __LINE__) PhysicsConstraintData(String(name, true)); + data->_order = readVarint(input, true); + data->_bone = skeletonData->_bones[readVarint(input, true)]; + int flags = readByte(input); + data->_skinRequired = (flags & 1) != 0; + if ((flags & 2) != 0) data->_x = readFloat(input); + if ((flags & 4) != 0) data->_y = readFloat(input); + if ((flags & 8) != 0) data->_rotate = readFloat(input); + if ((flags & 16) != 0) data->_scaleX = readFloat(input); + if ((flags & 32) != 0) data->_shearX = readFloat(input); + data->_limit = ((flags & 64) != 0 ? readFloat(input) : 5000) * _scale; + data->_step = 1.f / readByte(input); + data->_inertia = readFloat(input); + data->_strength = readFloat(input); + data->_damping = readFloat(input); + data->_massInverse = (flags & 128) != 0 ? readFloat(input) : 1; + data->_wind = readFloat(input); + data->_gravity = readFloat(input); + flags = readByte(input); + if ((flags & 1) != 0) data->_inertiaGlobal = true; + if ((flags & 2) != 0) data->_strengthGlobal = true; + if ((flags & 4) != 0) data->_dampingGlobal = true; + if ((flags & 8) != 0) data->_massGlobal = true; + if ((flags & 16) != 0) data->_windGlobal = true; + if ((flags & 32) != 0) data->_gravityGlobal = true; + if ((flags & 64) != 0) data->_mixGlobal = true; + data->_mix = (flags & 128) != 0 ? readFloat(input) : 1; + skeletonData->_physicsConstraints[i] = data; + } + + /* Default skin. */ + Skin *defaultSkin = readSkin(input, true, skeletonData, nonessential); + if (defaultSkin) { + skeletonData->_defaultSkin = defaultSkin; + skeletonData->_skins.add(defaultSkin); + } + + if (!this->getError().isEmpty()) { + delete input; + delete skeletonData; + return NULL; + } + + /* Skins. */ + for (size_t i = 0, n = (size_t) readVarint(input, true); i < n; ++i) { + Skin *skin = readSkin(input, false, skeletonData, nonessential); + if (skin) + skeletonData->_skins.add(skin); + else { + delete input; + delete skeletonData; + return NULL; + } + } + + /* Linked meshes. */ + for (int i = 0, n = (int) _linkedMeshes.size(); i < n; ++i) { + LinkedMesh *linkedMesh = _linkedMeshes[i]; + Skin *skin = skeletonData->_skins[linkedMesh->_skinIndex]; + Attachment *parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); + if (parent == NULL) { + delete input; + delete skeletonData; + setError("Parent mesh not found: ", linkedMesh->_parent.buffer()); + return NULL; + } + linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritTimeline ? static_cast(parent) + : linkedMesh->_mesh; + linkedMesh->_mesh->setParentMesh(static_cast(parent)); + if (linkedMesh->_mesh->_region) linkedMesh->_mesh->updateRegion(); + _attachmentLoader->configureAttachment(linkedMesh->_mesh); + } + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + /* Events. */ + int eventsCount = readVarint(input, true); + skeletonData->_events.setSize(eventsCount, 0); + for (int i = 0; i < eventsCount; ++i) { + const char *name = readString(input); + EventData *eventData = new (__FILE__, __LINE__) EventData(String(name, true)); + eventData->_intValue = readVarint(input, false); + eventData->_floatValue = readFloat(input); + eventData->_stringValue.own(readString(input)); + eventData->_audioPath.own(readString(input)); + if (!eventData->_audioPath.isEmpty()) { + eventData->_volume = readFloat(input); + eventData->_balance = readFloat(input); + } + skeletonData->_events[i] = eventData; + } + + /* Animations. */ + int animationsCount = readVarint(input, true); + skeletonData->_animations.setSize(animationsCount, 0); + for (int i = 0; i < animationsCount; ++i) { + String name(readString(input), true); + Animation *animation = readAnimation(name, input, skeletonData); + if (!animation) { + delete input; + delete skeletonData; + return NULL; + } + skeletonData->_animations[i] = animation; + } + + delete input; + return skeletonData; +} + +SkeletonData *SkeletonBinary::readSkeletonDataFile(const String &path) { + int length; + SkeletonData *skeletonData; + const char *binary = SpineExtension::readFile(path.buffer(), &length); + if (length == 0 || !binary) { + setError("Unable to read skeleton file: ", path.buffer()); + return NULL; + } + skeletonData = readSkeletonData((unsigned char *) binary, length); + SpineExtension::free(binary, __FILE__, __LINE__); + return skeletonData; +} + +void SkeletonBinary::setError(const char *value1, const char *value2) { + char message[256]; + int length; + strcpy(message, value1); + length = (int) strlen(value1); + if (value2) strncat(message + length, value2, 255 - length); + _error = String(message); +} + +char *SkeletonBinary::readString(DataInput *input) { + int length = readVarint(input, true); + char *string; + if (length == 0) return NULL; + string = SpineExtension::alloc(length, __FILE__, __LINE__); + memcpy(string, input->cursor, length - 1); + input->cursor += length - 1; + string[length - 1] = '\0'; + return string; +} + +char *SkeletonBinary::readStringRef(DataInput *input, SkeletonData *skeletonData) { + int index = readVarint(input, true); + return index == 0 ? NULL : skeletonData->_strings[index - 1]; +} + +float SkeletonBinary::readFloat(DataInput *input) { + union { + int intValue; + float floatValue; + } intToFloat; + intToFloat.intValue = readInt(input); + return intToFloat.floatValue; +} + +unsigned char SkeletonBinary::readByte(DataInput *input) { + return *input->cursor++; +} + +signed char SkeletonBinary::readSByte(DataInput *input) { + return (signed char) readByte(input); +} + +bool SkeletonBinary::readBoolean(DataInput *input) { + return readByte(input) != 0; +} + +int SkeletonBinary::readInt(DataInput *input) { + int result = readByte(input); + result <<= 8; + result |= readByte(input); + result <<= 8; + result |= readByte(input); + result <<= 8; + result |= readByte(input); + return result; +} + +void SkeletonBinary::readColor(DataInput *input, Color &color) { + color.r = readByte(input) / 255.0f; + color.g = readByte(input) / 255.0f; + color.b = readByte(input) / 255.0f; + color.a = readByte(input) / 255.0f; +} + +int SkeletonBinary::readVarint(DataInput *input, bool optimizePositive) { + unsigned char b = readByte(input); + int value = b & 0x7F; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 7; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 14; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 21; + if (b & 0x80) value |= (readByte(input) & 0x7F) << 28; + } + } + } + if (!optimizePositive) value = (((unsigned int) value >> 1) ^ -(value & 1)); + return value; +} + +Skin *SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential) { + Skin *skin; + int slotCount = 0; + if (defaultSkin) { + slotCount = readVarint(input, true); + if (slotCount == 0) return NULL; + skin = new (__FILE__, __LINE__) Skin("default"); + } else { + skin = new (__FILE__, __LINE__) Skin(String(readString(input), true)); + + if (nonessential) readColor(input, skin->getColor()); + + for (int i = 0, n = readVarint(input, true); i < n; i++) { + int boneIndex = readVarint(input, true); + if (boneIndex >= (int) skeletonData->_bones.size()) return NULL; + skin->getBones().add(skeletonData->_bones[boneIndex]); + } + + for (int i = 0, n = readVarint(input, true); i < n; i++) { + int ikIndex = readVarint(input, true); + if (ikIndex >= (int) skeletonData->_ikConstraints.size()) return NULL; + skin->getConstraints().add(skeletonData->_ikConstraints[ikIndex]); + } + + for (int i = 0, n = readVarint(input, true); i < n; i++) { + int transformIndex = readVarint(input, true); + if (transformIndex >= (int) skeletonData->_transformConstraints.size()) return NULL; + skin->getConstraints().add(skeletonData->_transformConstraints[transformIndex]); + } + + for (int i = 0, n = readVarint(input, true); i < n; i++) { + int pathIndex = readVarint(input, true); + if (pathIndex >= (int) skeletonData->_pathConstraints.size()) return NULL; + skin->getConstraints().add(skeletonData->_pathConstraints[pathIndex]); + } + + for (int i = 0, n = readVarint(input, true); i < n; i++) { + int physicsIndex = readVarint(input, true); + if (physicsIndex >= (int) skeletonData->_physicsConstraints.size()) return NULL; + skin->getConstraints().add(skeletonData->_physicsConstraints[physicsIndex]); + } + slotCount = readVarint(input, true); + } + + for (int i = 0; i < slotCount; ++i) { + int slotIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + String name(readStringRef(input, skeletonData)); + Attachment *attachment = readAttachment(input, skin, slotIndex, name, skeletonData, nonessential); + if (attachment) + skin->setAttachment(slotIndex, String(name), attachment); + else { + delete skin; + return NULL; + } + } + } + return skin; +} + +Sequence *SkeletonBinary::readSequence(DataInput *input) { + Sequence *sequence = new (__FILE__, __LINE__) Sequence(readVarint(input, true)); + sequence->_start = readVarint(input, true); + sequence->_digits = readVarint(input, true); + sequence->_setupIndex = readVarint(input, true); + return sequence; +} + +Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName, + SkeletonData *skeletonData, bool nonessential) { + + int flags = readByte(input); + String name = (flags & 8) != 0 ? readStringRef(input, skeletonData) : attachmentName; + AttachmentType type = static_cast(flags & 0x7); + switch (type) { + case AttachmentType_Region: { + String path = (flags & 16) != 0 ? readStringRef(input, skeletonData) : name; + Color color(1, 1, 1, 1); + if ((flags & 32) != 0) readColor(input, color); + Sequence *sequence = (flags & 64) != 0 ? readSequence(input) : nullptr; + float rotation = (flags & 128) != 0 ? readFloat(input) : 0; + float x = readFloat(input) * _scale; + float y = readFloat(input) * _scale; + float scaleX = readFloat(input); + float scaleY = readFloat(input); + float width = readFloat(input) * _scale; + float height = readFloat(input) * _scale; + RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path), sequence); + if (!region) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + region->_path = path; + region->_rotation = rotation; + region->_x = x; + region->_y = y; + region->_scaleX = scaleX; + region->_scaleY = scaleY; + region->_width = width; + region->_height = height; + region->getColor().set(color); + region->_sequence = sequence; + if (sequence == NULL) region->updateRegion(); + _attachmentLoader->configureAttachment(region); + return region; + } + case AttachmentType_Boundingbox: { + BoundingBoxAttachment *box = _attachmentLoader->newBoundingBoxAttachment(*skin, String(name)); + if (!box) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + int verticesLength = readVertices(input, box->getVertices(), box->getBones(), (flags & 16) != 0); + box->setWorldVerticesLength(verticesLength); + if (nonessential) { + readColor(input, box->getColor()); + } + _attachmentLoader->configureAttachment(box); + return box; + } + case AttachmentType_Mesh: { + Vector uvs; + Vector triangles; + Vector vertices; + Vector bones; + int hullLength; + float width = 0; + float height = 0; + Vector edges; + + String path = (flags & 16) != 0 ? readStringRef(input, skeletonData) : name; + Color color(1, 1, 1, 1); + if ((flags & 32) != 0) readColor(input, color); + Sequence *sequence = (flags & 64) != 0 ? readSequence(input) : nullptr; + hullLength = readVarint(input, true); + int verticesLength = readVertices(input, vertices, bones, (flags & 128) != 0); + readFloatArray(input, verticesLength, 1, uvs); + readShortArray(input, triangles, (verticesLength - hullLength - 2) * 3); + + if (nonessential) { + readShortArray(input, edges, readVarint(input, true)); + width = readFloat(input); + height = readFloat(input); + } + + MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path), sequence); + if (!mesh) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + mesh->_path = path; + mesh->_color.set(color); + mesh->_bones.addAll(bones); + mesh->_vertices.addAll(vertices); + mesh->setWorldVerticesLength(verticesLength); + mesh->_triangles.addAll(triangles); + mesh->_regionUVs.addAll(uvs); + if (sequence == NULL) mesh->updateRegion(); + mesh->_hullLength = hullLength; + mesh->_sequence = sequence; + if (nonessential) { + mesh->_edges.addAll(edges); + mesh->_width = width; + mesh->_height = height; + } + _attachmentLoader->configureAttachment(mesh); + return mesh; + } + case AttachmentType_Linkedmesh: { + String path = (flags & 16) != 0 ? readStringRef(input, skeletonData) : name; + Color color(1, 1, 1, 1); + if ((flags & 32) != 0) readColor(input, color); + Sequence *sequence = (flags & 64) != 0 ? readSequence(input) : nullptr; + bool inheritTimelines = (flags & 128) != 0; + int skinIndex = readVarint(input, true); + String parent(readStringRef(input, skeletonData)); + float width = 0, height = 0; + if (nonessential) { + width = readFloat(input) * _scale; + height = readFloat(input) * _scale; + } + + MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path), sequence); + if (!mesh) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + mesh->_path = path; + mesh->_color.set(color); + mesh->_sequence = sequence; + if (nonessential) { + mesh->_width = width; + mesh->_height = height; + } + + LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, skinIndex, slotIndex, + String(parent), inheritTimelines); + _linkedMeshes.add(linkedMesh); + return mesh; + } + case AttachmentType_Path: { + PathAttachment *path = _attachmentLoader->newPathAttachment(*skin, String(name)); + if (!path) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + path->_closed = (flags & 16) != 0; + path->_constantSpeed = (flags & 32) != 0; + int verticesLength = readVertices(input, path->getVertices(), path->getBones(), (flags & 64) != 0); + path->setWorldVerticesLength(verticesLength); + int lengthsLength = verticesLength / 6; + path->_lengths.setSize(lengthsLength, 0); + for (int i = 0; i < lengthsLength; ++i) { + path->_lengths[i] = readFloat(input) * _scale; + } + if (nonessential) { + readColor(input, path->getColor()); + } + _attachmentLoader->configureAttachment(path); + return path; + } + case AttachmentType_Point: { + PointAttachment *point = _attachmentLoader->newPointAttachment(*skin, String(name)); + if (!point) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + point->_rotation = readFloat(input); + point->_x = readFloat(input) * _scale; + point->_y = readFloat(input) * _scale; + + if (nonessential) { + readColor(input, point->getColor()); + } + _attachmentLoader->configureAttachment(point); + return point; + } + case AttachmentType_Clipping: { + int endSlotIndex = readVarint(input, true); + ClippingAttachment *clip = _attachmentLoader->newClippingAttachment(*skin, name); + if (!clip) { + setError("Error reading attachment: ", name.buffer()); + return NULL; + } + int verticesLength = readVertices(input, clip->getVertices(), clip->getBones(), (flags & 16) != 0); + clip->setWorldVerticesLength(verticesLength); + clip->_endSlot = skeletonData->_slots[endSlotIndex]; + if (nonessential) { + readColor(input, clip->getColor()); + } + _attachmentLoader->configureAttachment(clip); + return clip; + } + } + return NULL; +} + +int SkeletonBinary::readVertices(DataInput *input, Vector &vertices, Vector &bones, bool weighted) { + float scale = _scale; + int vertexCount = readVarint(input, true); + int verticesLength = vertexCount << 1; + if (!weighted) { + readFloatArray(input, verticesLength, scale, vertices); + return verticesLength; + } + vertices.ensureCapacity(verticesLength * 3 * 3); + bones.ensureCapacity(verticesLength * 3); + for (int i = 0; i < vertexCount; ++i) { + int boneCount = readVarint(input, true); + bones.add(boneCount); + for (int ii = 0; ii < boneCount; ++ii) { + bones.add(readVarint(input, true)); + vertices.add(readFloat(input) * scale); + vertices.add(readFloat(input) * scale); + vertices.add(readFloat(input)); + } + } + return verticesLength; +} + +void SkeletonBinary::readFloatArray(DataInput *input, int n, float scale, Vector &array) { + array.setSize(n, 0); + + int i; + if (scale == 1) { + for (i = 0; i < n; ++i) { + array[i] = readFloat(input); + } + } else { + for (i = 0; i < n; ++i) { + array[i] = readFloat(input) * scale; + } + } +} + +void SkeletonBinary::readShortArray(DataInput *input, Vector &array, int n) { + array.setSize(n, 0); + for (int i = 0; i < n; ++i) { + array[i] = (short) readVarint(input, true); + } +} + +void SkeletonBinary::setBezier(DataInput *input, CurveTimeline *timeline, int bezier, int frame, int value, float time1, + float time2, + float value1, float value2, float scale) { + float cx1 = readFloat(input); + float cy1 = readFloat(input); + float cx2 = readFloat(input); + float cy2 = readFloat(input); + timeline->setBezier(bezier, frame, value, time1, value1, cx1, cy1 * scale, cx2, cy2 * scale, time2, value2); +} + +void SkeletonBinary::readTimeline(DataInput *input, Vector &timelines, CurveTimeline1 *timeline, float scale) { + float time = readFloat(input); + float value = readFloat(input) * scale; + for (int frame = 0, bezier = 0, frameLast = (int) timeline->getFrameCount() - 1;; frame++) { + timeline->setFrame(frame, time, value); + if (frame == frameLast) break; + float time2 = readFloat(input); + float value2 = readFloat(input) * scale; + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale); + } + time = time2; + value = value2; + } + timelines.add(timeline); +} + +void SkeletonBinary::readTimeline2(DataInput *input, Vector &timelines, CurveTimeline2 *timeline, float scale) { + float time = readFloat(input); + float value1 = readFloat(input) * scale; + float value2 = readFloat(input) * scale; + for (int frame = 0, bezier = 0, frameLast = (int) timeline->getFrameCount() - 1;; frame++) { + timeline->setFrame(frame, time, value1, value2); + if (frame == frameLast) break; + float time2 = readFloat(input); + float nvalue1 = readFloat(input) * scale; + float nvalue2 = readFloat(input) * scale; + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale); + setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + } + timelines.add(timeline); +} + +Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, SkeletonData *skeletonData) { + Vector timelines; + float scale = _scale; + int numTimelines = readVarint(input, true); + SP_UNUSED(numTimelines); + // Slot timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int slotIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + unsigned char timelineType = readByte(input); + int frameCount = readVarint(input, true); + int frameLast = frameCount - 1; + switch (timelineType) { + case SLOT_ATTACHMENT: { + AttachmentTimeline *timeline = new (__FILE__, __LINE__) AttachmentTimeline(frameCount, slotIndex); + for (int frame = 0; frame < frameCount; ++frame) { + float time = readFloat(input); + String attachmentName(readStringRef(input, skeletonData)); + timeline->setFrame(frame, time, attachmentName); + } + timelines.add(timeline); + break; + } + case SLOT_RGBA: { + int bezierCount = readVarint(input, true); + RGBATimeline *timeline = new (__FILE__, __LINE__) RGBATimeline(frameCount, bezierCount, slotIndex); + + float time = readFloat(input); + float r = readByte(input) / 255.0; + float g = readByte(input) / 255.0; + float b = readByte(input) / 255.0; + float a = readByte(input) / 255.0; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b, a); + if (frame == frameLast) break; + + float time2 = readFloat(input); + float r2 = readByte(input) / 255.0; + float g2 = readByte(input) / 255.0; + float b2 = readByte(input) / 255.0; + float a2 = readByte(input) / 255.0; + + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + a = a2; + } + timelines.add(timeline); + break; + } + case SLOT_RGB: { + int bezierCount = readVarint(input, true); + RGBTimeline *timeline = new (__FILE__, __LINE__) RGBTimeline(frameCount, bezierCount, slotIndex); + + float time = readFloat(input); + float r = readByte(input) / 255.0; + float g = readByte(input) / 255.0; + float b = readByte(input) / 255.0; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b); + if (frame == frameLast) break; + + float time2 = readFloat(input); + float r2 = readByte(input) / 255.0; + float g2 = readByte(input) / 255.0; + float b2 = readByte(input) / 255.0; + + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + } + timelines.add(timeline); + break; + } + case SLOT_RGBA2: { + int bezierCount = readVarint(input, true); + RGBA2Timeline *timeline = new (__FILE__, __LINE__) RGBA2Timeline(frameCount, bezierCount, slotIndex); + + float time = readFloat(input); + float r = readByte(input) / 255.0; + float g = readByte(input) / 255.0; + float b = readByte(input) / 255.0; + float a = readByte(input) / 255.0; + float r2 = readByte(input) / 255.0; + float g2 = readByte(input) / 255.0; + float b2 = readByte(input) / 255.0; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b, a, r2, g2, b2); + if (frame == frameLast) break; + float time2 = readFloat(input); + float nr = readByte(input) / 255.0; + float ng = readByte(input) / 255.0; + float nb = readByte(input) / 255.0; + float na = readByte(input) / 255.0; + float nr2 = readByte(input) / 255.0; + float ng2 = readByte(input) / 255.0; + float nb2 = readByte(input) / 255.0; + + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + a = na; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.add(timeline); + break; + } + case SLOT_RGB2: { + int bezierCount = readVarint(input, true); + RGB2Timeline *timeline = new (__FILE__, __LINE__) RGB2Timeline(frameCount, bezierCount, slotIndex); + + float time = readFloat(input); + float r = readByte(input) / 255.0; + float g = readByte(input) / 255.0; + float b = readByte(input) / 255.0; + float r2 = readByte(input) / 255.0; + float g2 = readByte(input) / 255.0; + float b2 = readByte(input) / 255.0; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b, r2, g2, b2); + if (frame == frameLast) break; + float time2 = readFloat(input); + float nr = readByte(input) / 255.0; + float ng = readByte(input) / 255.0; + float nb = readByte(input) / 255.0; + float nr2 = readByte(input) / 255.0; + float ng2 = readByte(input) / 255.0; + float nb2 = readByte(input) / 255.0; + + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.add(timeline); + break; + } + case SLOT_ALPHA: { + int bezierCount = readVarint(input, true); + AlphaTimeline *timeline = new (__FILE__, __LINE__) AlphaTimeline(frameCount, bezierCount, slotIndex); + float time = readFloat(input); + float a = readByte(input) / 255.0; + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, a); + if (frame == frameLast) break; + float time2 = readFloat(input); + float a2 = readByte(input) / 255.0; + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1); + } + time = time2; + a = a2; + } + timelines.add(timeline); + break; + } + default: { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Invalid timeline type for a slot: ", skeletonData->_slots[slotIndex]->_name.buffer()); + return NULL; + } + } + } + } + + // Bone timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int boneIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + unsigned char timelineType = readByte(input); + int frameCount = readVarint(input, true); + if (timelineType == BONE_INHERIT) { + InheritTimeline *timeline = new (__FILE__, __LINE__) InheritTimeline(frameCount, boneIndex); + for (int frame = 0; frame < frameCount; frame++) { + float time = readFloat(input); + Inherit inherit = (Inherit) readByte(input); + timeline->setFrame(frame, time, inherit); + } + timelines.add(timeline); + continue; + } + int bezierCount = readVarint(input, true); + switch (timelineType) { + case BONE_ROTATE: + readTimeline(input, timelines, + new (__FILE__, __LINE__) RotateTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_TRANSLATE: + readTimeline2(input, timelines, new (__FILE__, __LINE__) TranslateTimeline(frameCount, bezierCount, boneIndex), scale); + break; + case BONE_TRANSLATEX: + readTimeline(input, timelines, new (__FILE__, __LINE__) TranslateXTimeline(frameCount, bezierCount, boneIndex), scale); + break; + case BONE_TRANSLATEY: + readTimeline(input, timelines, new (__FILE__, __LINE__) TranslateYTimeline(frameCount, bezierCount, boneIndex), scale); + break; + case BONE_SCALE: + readTimeline2(input, timelines, + new (__FILE__, __LINE__) ScaleTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SCALEX: + readTimeline(input, timelines, + new (__FILE__, __LINE__) ScaleXTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SCALEY: + readTimeline(input, timelines, + new (__FILE__, __LINE__) ScaleYTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SHEAR: + readTimeline2(input, timelines, + new (__FILE__, __LINE__) ShearTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SHEARX: + readTimeline(input, timelines, + new (__FILE__, __LINE__) ShearXTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + case BONE_SHEARY: + readTimeline(input, timelines, + new (__FILE__, __LINE__) ShearYTimeline(frameCount, bezierCount, boneIndex), + 1); + break; + default: { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Invalid timeline type for a bone: ", skeletonData->_bones[boneIndex]->_name.buffer()); + return NULL; + } + } + } + } + + // IK timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int index = readVarint(input, true); + int frameCount = readVarint(input, true); + int frameLast = frameCount - 1; + int bezierCount = readVarint(input, true); + IkConstraintTimeline *timeline = new (__FILE__, __LINE__) IkConstraintTimeline(frameCount, bezierCount, index); + int flags = readByte(input); + float time = readFloat(input), mix = (flags & 1) != 0 ? ((flags & 2) != 0 ? readFloat(input) : 1) : 0; + float softness = (flags & 4) != 0 ? readFloat(input) * scale : 0; + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mix, softness, (flags & 8) != 0 ? 1 : -1, (flags & 16) != 0, (flags & 32) != 0); + if (frame == frameLast) break; + flags = readByte(input); + float time2 = readFloat(input), mix2 = (flags & 1) != 0 ? ((flags & 2) != 0 ? readFloat(input) : 1) : 0; + float softness2 = (flags & 4) != 0 ? readFloat(input) * scale : 0; + if ((flags & 64) != 0) + timeline->setStepped(frame); + else if ((flags & 128) != 0) { + setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + } + timelines.add(timeline); + } + + // Transform constraint timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int index = readVarint(input, true); + int frameCount = readVarint(input, true); + int frameLast = frameCount - 1; + int bezierCount = readVarint(input, true); + TransformConstraintTimeline *timeline = new TransformConstraintTimeline(frameCount, bezierCount, index); + float time = readFloat(input); + float mixRotate = readFloat(input); + float mixX = readFloat(input); + float mixY = readFloat(input); + float mixScaleX = readFloat(input); + float mixScaleY = readFloat(input); + float mixShearY = readFloat(input); + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + if (frame == frameLast) break; + float time2 = readFloat(input); + float mixRotate2 = readFloat(input); + float mixX2 = readFloat(input); + float mixY2 = readFloat(input); + float mixScaleX2 = readFloat(input); + float mixScaleY2 = readFloat(input); + float mixShearY2 = readFloat(input); + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + } + timelines.add(timeline); + } + + // Path constraint timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + int index = readVarint(input, true); + PathConstraintData *data = skeletonData->_pathConstraints[index]; + for (int ii = 0, nn = readVarint(input, true); ii < nn; ii++) { + int type = readByte(input); + int frameCount = readVarint(input, true); + int bezierCount = readVarint(input, true); + switch (type) { + case PATH_POSITION: { + readTimeline(input, timelines, new PathConstraintPositionTimeline(frameCount, bezierCount, index), + data->_positionMode == PositionMode_Fixed ? scale : 1); + break; + } + case PATH_SPACING: { + readTimeline(input, timelines, + new PathConstraintSpacingTimeline(frameCount, + bezierCount, + index), + data->_spacingMode == SpacingMode_Length || + data->_spacingMode == SpacingMode_Fixed + ? scale + : 1); + break; + } + case PATH_MIX: + PathConstraintMixTimeline *timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index); + float time = readFloat(input); + float mixRotate = readFloat(input); + float mixX = readFloat(input); + float mixY = readFloat(input); + for (int frame = 0, bezier = 0, frameLast = (int) timeline->getFrameCount() - 1;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY); + if (frame == frameLast) break; + float time2 = readFloat(input); + float mixRotate2 = readFloat(input); + float mixX2 = readFloat(input); + float mixY2 = readFloat(input); + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + } + timelines.add(timeline); + } + } + } + + // Physics timelines. + for (int i = 0, n = readVarint(input, true); i < n; i++) { + int index = readVarint(input, true) - 1; + for (int ii = 0, nn = readVarint(input, true); ii < nn; ii++) { + int type = readByte(input); + int frameCount = readVarint(input, true); + if (type == PHYSICS_RESET) { + PhysicsConstraintResetTimeline *timeline = new (__FILE__, __LINE__) PhysicsConstraintResetTimeline(frameCount, index); + for (int frame = 0; frame < frameCount; frame++) + timeline->setFrame(frame, readFloat(input)); + timelines.add(timeline); + continue; + } + int bezierCount = readVarint(input, true); + switch (type) { + case PHYSICS_INERTIA: + readTimeline(input, timelines, new PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index), 1); + break; + case PHYSICS_STRENGTH: + readTimeline(input, timelines, new PhysicsConstraintStrengthTimeline(frameCount, bezierCount, index), 1); + break; + case PHYSICS_DAMPING: + readTimeline(input, timelines, new PhysicsConstraintDampingTimeline(frameCount, bezierCount, index), 1); + break; + case PHYSICS_MASS: + readTimeline(input, timelines, new PhysicsConstraintMassTimeline(frameCount, bezierCount, index), 1); + break; + case PHYSICS_WIND: + readTimeline(input, timelines, new PhysicsConstraintWindTimeline(frameCount, bezierCount, index), 1); + break; + case PHYSICS_GRAVITY: + readTimeline(input, timelines, new PhysicsConstraintGravityTimeline(frameCount, bezierCount, index), 1); + break; + case PHYSICS_MIX: + readTimeline(input, timelines, new PhysicsConstraintMixTimeline(frameCount, bezierCount, index), 1); + } + } + } + + // Attachment timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) { + Skin *skin = skeletonData->_skins[readVarint(input, true)]; + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { + int slotIndex = readVarint(input, true); + for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) { + const char *attachmentName = readStringRef(input, skeletonData); + Attachment *baseAttachment = skin->getAttachment(slotIndex, String(attachmentName)); + if (!baseAttachment) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Attachment not found: ", attachmentName); + return NULL; + } + unsigned int timelineType = readByte(input); + int frameCount = readVarint(input, true); + int frameLast = frameCount - 1; + + switch (timelineType) { + case ATTACHMENT_DEFORM: { + VertexAttachment *attachment = static_cast(baseAttachment); + bool weighted = attachment->_bones.size() > 0; + Vector &vertices = attachment->_vertices; + int deformLength = weighted ? (int) vertices.size() / 3 * 2 : (int) vertices.size(); + + int bezierCount = readVarint(input, true); + DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frameCount, bezierCount, slotIndex, + attachment); + + float time = readFloat(input); + for (int frame = 0, bezier = 0;; ++frame) { + Vector deform; + size_t end = (size_t) readVarint(input, true); + if (end == 0) { + if (weighted) { + deform.setSize(deformLength, 0); + for (int iiii = 0; iiii < deformLength; ++iiii) + deform[iiii] = 0; + } else { + deform.clearAndAddAll(vertices); + } + } else { + deform.setSize(deformLength, 0); + size_t start = (size_t) readVarint(input, true); + end += start; + if (scale == 1) { + for (size_t v = start; v < end; ++v) + deform[v] = readFloat(input); + } else { + for (size_t v = start; v < end; ++v) + deform[v] = readFloat(input) * scale; + } + + if (!weighted) { + for (size_t v = 0, vn = deform.size(); v < vn; ++v) + deform[v] += vertices[v]; + } + } + + timeline->setFrame(frame, time, deform); + if (frame == frameLast) break; + float time2 = readFloat(input); + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1); + } + time = time2; + } + + timelines.add(timeline); + break; + } + case ATTACHMENT_SEQUENCE: { + SequenceTimeline *timeline = new (__FILE__, __LINE__) SequenceTimeline(frameCount, slotIndex, baseAttachment); + for (int frame = 0; frame < frameCount; frame++) { + float time = readFloat(input); + int modeAndIndex = readInt(input); + float delay = readFloat(input); + timeline->setFrame(frame, time, (spine::SequenceMode)(modeAndIndex & 0xf), modeAndIndex >> 4, delay); + } + timelines.add(timeline); + break; + } + } + } + } + } + + // Draw order timeline. + size_t drawOrderCount = (size_t) readVarint(input, true); + if (drawOrderCount > 0) { + DrawOrderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderTimeline(drawOrderCount); + + size_t slotCount = skeletonData->_slots.size(); + for (size_t i = 0; i < drawOrderCount; ++i) { + float time = readFloat(input); + size_t offsetCount = (size_t) readVarint(input, true); + + Vector drawOrder; + drawOrder.setSize(slotCount, 0); + for (int ii = (int) slotCount - 1; ii >= 0; --ii) + drawOrder[ii] = -1; + + Vector unchanged; + unchanged.setSize(slotCount - offsetCount, 0); + size_t originalIndex = 0, unchangedIndex = 0; + for (size_t ii = 0; ii < offsetCount; ++ii) { + size_t slotIndex = (size_t) readVarint(input, true); + // Collect unchanged items. + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = (int) originalIndex++; + // Set changed items. + size_t index = originalIndex; + drawOrder[index + (size_t) readVarint(input, true)] = (int) originalIndex++; + } + + // Collect remaining unchanged items. + while (originalIndex < slotCount) { + unchanged[unchangedIndex++] = (int) originalIndex++; + } + + // Fill in unchanged items. + for (int ii = (int) slotCount - 1; ii >= 0; --ii) + if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; + timeline->setFrame(i, time, drawOrder); + } + timelines.add(timeline); + } + + // Event timeline. + int eventCount = readVarint(input, true); + if (eventCount > 0) { + EventTimeline *timeline = new (__FILE__, __LINE__) EventTimeline(eventCount); + + for (int i = 0; i < eventCount; ++i) { + float time = readFloat(input); + EventData *eventData = skeletonData->_events[readVarint(input, true)]; + Event *event = new (__FILE__, __LINE__) Event(time, *eventData); + + event->_intValue = readVarint(input, false); + event->_floatValue = readFloat(input); + const char *event_stringValue = readString(input); + if (event_stringValue == nullptr) { + event->_stringValue = eventData->_stringValue; + } else { + event->_stringValue = String(event_stringValue); + SpineExtension::free(event_stringValue, __FILE__, __LINE__); + } + + if (!eventData->_audioPath.isEmpty()) { + event->_volume = readFloat(input); + event->_balance = readFloat(input); + } + timeline->setFrame(i, event); + } + timelines.add(timeline); + } + + float duration = 0; + for (int i = 0, n = (int) timelines.size(); i < n; i++) { + duration = MathUtil::max(duration, (timelines[i])->getDuration()); + } + return new (__FILE__, __LINE__) Animation(String(name), timelines, duration); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp new file mode 100644 index 0000000..5681af4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp @@ -0,0 +1,231 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include + +using namespace spine; + +SkeletonBounds::SkeletonBounds() : _minX(0), _minY(0), _maxX(0), _maxY(0) { +} + +SkeletonBounds::~SkeletonBounds() { + for (size_t i = 0, n = _polygons.size(); i < n; i++) + _polygonPool.free(_polygons[i]); + _polygons.clear(); +} + +void SkeletonBounds::update(Skeleton &skeleton, bool updateAabb) { + Vector &slots = skeleton.getSlots(); + size_t slotCount = slots.size(); + + _boundingBoxes.clear(); + for (size_t i = 0, n = _polygons.size(); i < n; ++i) { + _polygonPool.free(_polygons[i]); + } + + _polygons.clear(); + + for (size_t i = 0; i < slotCount; i++) { + Slot *slot = slots[i]; + if (!slot->getBone().isActive()) continue; + + Attachment *attachment = slot->getAttachment(); + if (attachment == NULL || !attachment->getRTTI().instanceOf(BoundingBoxAttachment::rtti)) continue; + BoundingBoxAttachment *boundingBox = static_cast(attachment); + _boundingBoxes.add(boundingBox); + + spine::Polygon *polygonP = _polygonPool.obtain(); + _polygons.add(polygonP); + + Polygon &polygon = *polygonP; + + size_t count = boundingBox->getWorldVerticesLength(); + polygon._count = (int) count; + if (polygon._vertices.size() < count) { + polygon._vertices.setSize(count, 0); + } + boundingBox->computeWorldVertices(*slot, polygon._vertices); + } + + if (updateAabb) + aabbCompute(); + else { + _minX = FLT_MIN; + _minY = FLT_MIN; + _maxX = FLT_MAX; + _maxY = FLT_MAX; + } +} + +bool SkeletonBounds::aabbcontainsPoint(float x, float y) { + return x >= _minX && x <= _maxX && y >= _minY && y <= _maxY; +} + +bool SkeletonBounds::aabbintersectsSegment(float x1, float y1, float x2, float y2) { + float minX = _minX; + float minY = _minY; + float maxX = _maxX; + float maxY = _maxY; + + if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || + (y1 >= maxY && y2 >= maxY)) { + return false; + } + + float m = (y2 - y1) / (x2 - x1); + float y = m * (minX - x1) + y1; + if (y > minY && y < maxY) return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) return true; + float x = (minY - y1) / m + x1; + if (x > minX && x < maxX) return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) return true; + return false; +} + +bool SkeletonBounds::aabbIntersectsSkeleton(SkeletonBounds &bounds) { + return _minX < bounds._maxX && _maxX > bounds._minX && _minY < bounds._maxY && _maxY > bounds._minY; +} + +bool SkeletonBounds::containsPoint(spine::Polygon *polygon, float x, float y) { + Vector &vertices = polygon->_vertices; + int nn = polygon->_count; + + int prevIndex = nn - 2; + bool inside = false; + for (int ii = 0; ii < nn; ii += 2) { + float vertexY = vertices[ii + 1]; + float prevY = vertices[prevIndex + 1]; + if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { + float vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) { + inside = !inside; + } + } + prevIndex = ii; + } + return inside; +} + +BoundingBoxAttachment *SkeletonBounds::containsPoint(float x, float y) { + for (size_t i = 0, n = _polygons.size(); i < n; ++i) + if (containsPoint(_polygons[i], x, y)) return _boundingBoxes[i]; + return NULL; +} + +BoundingBoxAttachment *SkeletonBounds::intersectsSegment(float x1, float y1, float x2, float y2) { + for (size_t i = 0, n = _polygons.size(); i < n; ++i) + if (intersectsSegment(_polygons[i], x1, y1, x2, y2)) return _boundingBoxes[i]; + return NULL; +} + +bool SkeletonBounds::intersectsSegment(spine::Polygon *polygon, float x1, float y1, float x2, float y2) { + Vector &vertices = polygon->_vertices; + size_t nn = polygon->_count; + + float width12 = x1 - x2, height12 = y1 - y2; + float det1 = x1 * y2 - y1 * x2; + float x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (size_t ii = 0; ii < nn; ii += 2) { + float x4 = vertices[ii], y4 = vertices[ii + 1]; + float det2 = x3 * y4 - y3 * x4; + float width34 = x3 - x4, height34 = y3 - y4; + float det3 = width12 * height34 - height12 * width34; + float x = (det1 * width34 - width12 * det2) / det3; + if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { + float y = (det1 * height34 - height12 * det2) / det3; + if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) { + return true; + } + } + x3 = x4; + y3 = y4; + } + + return false; +} + +spine::Polygon *SkeletonBounds::getPolygon(BoundingBoxAttachment *attachment) { + int index = _boundingBoxes.indexOf(attachment); + return index == -1 ? NULL : _polygons[index]; +} + +BoundingBoxAttachment *SkeletonBounds::getBoundingBox(Polygon *polygon) { + int index = _polygons.indexOf(polygon); + return index == -1 ? NULL : _boundingBoxes[index]; +} + +Vector &SkeletonBounds::getPolygons() { + return _polygons; +} + +Vector &SkeletonBounds::getBoundingBoxes() { + return _boundingBoxes; +} + +float SkeletonBounds::getWidth() { + return _maxX - _minX; +} + +float SkeletonBounds::getHeight() { + return _maxY - _minY; +} + +void SkeletonBounds::aabbCompute() { + float minX = FLT_MAX; + float minY = FLT_MAX; + float maxX = FLT_MIN; + float maxY = FLT_MIN; + + for (size_t i = 0, n = _polygons.size(); i < n; ++i) { + spine::Polygon *polygon = _polygons[i]; + Vector &vertices = polygon->_vertices; + for (int ii = 0, nn = polygon->_count; ii < nn; ii += 2) { + float x = vertices[ii]; + float y = vertices[ii + 1]; + minX = MathUtil::min(minX, x); + minY = MathUtil::min(minY, y); + maxX = MathUtil::max(maxX, x); + maxY = MathUtil::max(maxY, y); + } + } + _minX = minX; + _minY = minY; + _maxX = maxX; + _maxY = maxY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp new file mode 100644 index 0000000..fbe09ed --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp @@ -0,0 +1,397 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +using namespace spine; + +SkeletonClipping::SkeletonClipping() : _clipAttachment(NULL) { + _clipOutput.ensureCapacity(128); + _clippedVertices.ensureCapacity(128); + _clippedTriangles.ensureCapacity(128); + _clippedUVs.ensureCapacity(128); +} + +size_t SkeletonClipping::clipStart(Slot &slot, ClippingAttachment *clip) { + if (_clipAttachment != NULL) { + return 0; + } + + _clipAttachment = clip; + + int n = (int) clip->getWorldVerticesLength(); + _clippingPolygon.setSize(n, 0); + clip->computeWorldVertices(slot, 0, n, _clippingPolygon, 0, 2); + makeClockwise(_clippingPolygon); + _clippingPolygons = &_triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon)); + + for (size_t i = 0; i < _clippingPolygons->size(); ++i) { + Vector *polygonP = (*_clippingPolygons)[i]; + Vector &polygon = *polygonP; + makeClockwise(polygon); + polygon.add(polygon[0]); + polygon.add(polygon[1]); + } + + return (*_clippingPolygons).size(); +} + +void SkeletonClipping::clipEnd(Slot &slot) { + if (_clipAttachment != NULL && _clipAttachment->_endSlot == &slot._data) { + clipEnd(); + } +} + +void SkeletonClipping::clipEnd() { + if (_clipAttachment == NULL) return; + + _clipAttachment = NULL; + _clippingPolygons = NULL; + _clippedVertices.clear(); + _clippedUVs.clear(); + _clippedTriangles.clear(); + _clippingPolygon.clear(); +} + +void SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, + size_t trianglesLength) { + Vector &clipOutput = _clipOutput; + Vector &clippedVertices = _clippedVertices; + Vector &clippedTriangles = _clippedTriangles; + Vector *> &polygons = *_clippingPolygons; + size_t polygonsCount = (*_clippingPolygons).size(); + + size_t index = 0; + clippedVertices.clear(); + _clippedUVs.clear(); + clippedTriangles.clear(); + + int stride = 2; + size_t i = 0; +continue_outer: + for (; i < trianglesLength; i += 3) { + int vertexOffset = triangles[i] * stride; + float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + + vertexOffset = triangles[i + 1] * stride; + float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + + vertexOffset = triangles[i + 2] * stride; + float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + + for (size_t p = 0; p < polygonsCount; p++) { + size_t s = clippedVertices.size(); + if (clip(x1, y1, x2, y2, x3, y3, &(*polygons[p]), &clipOutput)) { + size_t clipOutputLength = clipOutput.size(); + if (clipOutputLength == 0) continue; + + size_t clipOutputCount = clipOutputLength >> 1; + clippedVertices.setSize(s + clipOutputCount * 2, 0); + for (size_t ii = 0; ii < clipOutputLength; ii += 2) { + float x = clipOutput[ii], y = clipOutput[ii + 1]; + clippedVertices[s] = x; + clippedVertices[s + 1] = y; + s += 2; + } + + s = clippedTriangles.size(); + clippedTriangles.setSize(s + 3 * (clipOutputCount - 2), 0); + clipOutputCount--; + for (size_t ii = 1; ii < clipOutputCount; ii++) { + clippedTriangles[s] = (unsigned short) (index); + clippedTriangles[s + 1] = (unsigned short) (index + ii); + clippedTriangles[s + 2] = (unsigned short) (index + ii + 1); + s += 3; + } + index += clipOutputCount + 1; + } else { + clippedVertices.setSize(s + 3 * 2, 0); + clippedVertices[s] = x1; + clippedVertices[s + 1] = y1; + clippedVertices[s + 2] = x2; + clippedVertices[s + 3] = y2; + clippedVertices[s + 4] = x3; + clippedVertices[s + 5] = y3; + + s = clippedTriangles.size(); + clippedTriangles.setSize(s + 3, 0); + clippedTriangles[s] = (unsigned short) index; + clippedTriangles[s + 1] = (unsigned short) (index + 1); + clippedTriangles[s + 2] = (unsigned short) (index + 2); + index += 3; + i += 3; + goto continue_outer; + } + } + } +} + +void SkeletonClipping::clipTriangles(Vector &vertices, Vector &triangles, Vector &uvs, + size_t stride) { + clipTriangles(vertices.buffer(), triangles.buffer(), triangles.size(), uvs.buffer(), stride); +} + +void SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, + size_t trianglesLength, float *uvs, size_t stride) { + Vector &clipOutput = _clipOutput; + Vector &clippedVertices = _clippedVertices; + Vector &clippedTriangles = _clippedTriangles; + Vector *> &polygons = *_clippingPolygons; + size_t polygonsCount = (*_clippingPolygons).size(); + + size_t index = 0; + clippedVertices.clear(); + _clippedUVs.clear(); + clippedTriangles.clear(); + + size_t i = 0; +continue_outer: + for (; i < trianglesLength; i += 3) { + int vertexOffset = triangles[i] * (int) stride; + float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + + vertexOffset = triangles[i + 1] * (int) stride; + float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + float u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + + vertexOffset = triangles[i + 2] * (int) stride; + float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + float u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + + for (size_t p = 0; p < polygonsCount; p++) { + size_t s = clippedVertices.size(); + if (clip(x1, y1, x2, y2, x3, y3, &(*polygons[p]), &clipOutput)) { + size_t clipOutputLength = clipOutput.size(); + if (clipOutputLength == 0) continue; + float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + float d = 1 / (d0 * d2 + d1 * (y1 - y3)); + + size_t clipOutputCount = clipOutputLength >> 1; + clippedVertices.setSize(s + clipOutputCount * 2, 0); + _clippedUVs.setSize(s + clipOutputCount * 2, 0); + for (size_t ii = 0; ii < clipOutputLength; ii += 2) { + float x = clipOutput[ii], y = clipOutput[ii + 1]; + clippedVertices[s] = x; + clippedVertices[s + 1] = y; + float c0 = x - x3, c1 = y - y3; + float a = (d0 * c0 + d1 * c1) * d; + float b = (d4 * c0 + d2 * c1) * d; + float c = 1 - a - b; + _clippedUVs[s] = u1 * a + u2 * b + u3 * c; + _clippedUVs[s + 1] = v1 * a + v2 * b + v3 * c; + s += 2; + } + + s = clippedTriangles.size(); + clippedTriangles.setSize(s + 3 * (clipOutputCount - 2), 0); + clipOutputCount--; + for (size_t ii = 1; ii < clipOutputCount; ii++) { + clippedTriangles[s] = (unsigned short) (index); + clippedTriangles[s + 1] = (unsigned short) (index + ii); + clippedTriangles[s + 2] = (unsigned short) (index + ii + 1); + s += 3; + } + index += clipOutputCount + 1; + } else { + clippedVertices.setSize(s + 3 * 2, 0); + _clippedUVs.setSize(s + 3 * 2, 0); + clippedVertices[s] = x1; + clippedVertices[s + 1] = y1; + clippedVertices[s + 2] = x2; + clippedVertices[s + 3] = y2; + clippedVertices[s + 4] = x3; + clippedVertices[s + 5] = y3; + + _clippedUVs[s] = u1; + _clippedUVs[s + 1] = v1; + _clippedUVs[s + 2] = u2; + _clippedUVs[s + 3] = v2; + _clippedUVs[s + 4] = u3; + _clippedUVs[s + 5] = v3; + + s = clippedTriangles.size(); + clippedTriangles.setSize(s + 3, 0); + clippedTriangles[s] = (unsigned short) index; + clippedTriangles[s + 1] = (unsigned short) (index + 1); + clippedTriangles[s + 2] = (unsigned short) (index + 2); + index += 3; + i += 3; + goto continue_outer; + } + } + } +} + +bool SkeletonClipping::isClipping() { + return _clipAttachment != NULL; +} + +Vector &SkeletonClipping::getClippedVertices() { + return _clippedVertices; +} + +Vector &SkeletonClipping::getClippedTriangles() { + return _clippedTriangles; +} + +Vector &SkeletonClipping::getClippedUVs() { + return _clippedUVs; +} + +bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector *clippingArea, + Vector *output) { + Vector *originalOutput = output; + bool clipped = false; + + // Avoid copy at the end. + Vector *input; + if (clippingArea->size() % 4 >= 2) { + input = output; + output = &_scratch; + } else + input = &_scratch; + + input->clear(); + input->add(x1); + input->add(y1); + input->add(x2); + input->add(y2); + input->add(x3); + input->add(y3); + input->add(x1); + input->add(y1); + output->clear(); + + size_t clippingVerticesLast = clippingArea->size() - 4; + Vector &clippingVertices = *clippingArea; + for (size_t i = 0;; i += 2) { + float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + float ex = edgeX - clippingVertices[i + 2], ey = edgeY - clippingVertices[i + 3]; + + size_t outputStart = output->size(); + Vector &inputVertices = *input; + for (size_t ii = 0, nn = input->size() - 2; ii < nn;) { + float inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + ii += 2; + float inputX2 = inputVertices[ii], inputY2 = inputVertices[ii + 1]; + float s2 = ey * (edgeX - inputX2) > ex * (edgeY - inputY2); + float s1 = ey * (edgeX - inputX) - ex * (edgeY - inputY); + if (s1 > 0) { + if (s2) {// v1 inside, v2 inside + output->add(inputX2); + output->add(inputY2); + continue; + } + // v1 inside, v2 outside + float ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + output->add(inputX + ix * t); + output->add(inputY + iy * t); + } else { + output->add(inputX2); + output->add(inputY2); + } + } else if (s2) {// v1 outside, v2 inside + float ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + output->add(inputX + ix * t); + output->add(inputY + iy * t); + output->add(inputX2); + output->add(inputY2); + } else { + output->add(inputX2); + output->add(inputY2); + continue; + } + } + clipped = true; + } + + + if (outputStart == output->size()) { + // All edges outside. + originalOutput->clear(); + return true; + } + + output->add((*output)[0]); + output->add((*output)[1]); + + if (i == clippingVerticesLast) { + break; + } + Vector *temp = output; + output = input; + output->clear(); + input = temp; + } + + if (originalOutput != output) { + originalOutput->clear(); + for (size_t i = 0, n = output->size() - 2; i < n; ++i) + originalOutput->add((*output)[i]); + } else + originalOutput->setSize(originalOutput->size() - 2, 0); + + if (originalOutput->size() < 6) { + originalOutput->clear(); + return false; + } + return clipped; +} + +void SkeletonClipping::makeClockwise(Vector &polygon) { + size_t verticeslength = polygon.size(); + + float area = polygon[verticeslength - 2] * polygon[1] - polygon[0] * polygon[verticeslength - 1]; + float p1x, p1y, p2x, p2y; + + for (size_t i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = polygon[i]; + p1y = polygon[i + 1]; + p2x = polygon[i + 2]; + p2y = polygon[i + 3]; + area += p1x * p2y - p2x * p1y; + } + + if (area < 0) return; + + for (size_t i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + float x = polygon[i], y = polygon[i + 1]; + int other = (int) (lastX - i); + polygon[i] = polygon[other]; + polygon[i + 1] = polygon[other + 1]; + polygon[other] = x; + polygon[other + 1] = y; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp new file mode 100644 index 0000000..e3b35f0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -0,0 +1,244 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +SkeletonData::SkeletonData() : _name(), + _defaultSkin(NULL), + _x(0), + _y(0), + _width(0), + _height(0), + _referenceScale(100), + _version(), + _hash(), + _fps(0), + _imagesPath() { +} + +SkeletonData::~SkeletonData() { + ContainerUtil::cleanUpVectorOfPointers(_bones); + ContainerUtil::cleanUpVectorOfPointers(_slots); + ContainerUtil::cleanUpVectorOfPointers(_skins); + + _defaultSkin = NULL; + + ContainerUtil::cleanUpVectorOfPointers(_events); + ContainerUtil::cleanUpVectorOfPointers(_animations); + ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); + ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); + ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); + ContainerUtil::cleanUpVectorOfPointers(_physicsConstraints); + for (size_t i = 0; i < _strings.size(); i++) { + SpineExtension::free(_strings[i], __FILE__, __LINE__); + } +} + +BoneData *SkeletonData::findBone(const String &boneName) { + return ContainerUtil::findWithName(_bones, boneName); +} + +SlotData *SkeletonData::findSlot(const String &slotName) { + return ContainerUtil::findWithName(_slots, slotName); +} + +Skin *SkeletonData::findSkin(const String &skinName) { + return ContainerUtil::findWithName(_skins, skinName); +} + +spine::EventData *SkeletonData::findEvent(const String &eventDataName) { + return ContainerUtil::findWithName(_events, eventDataName); +} + +Animation *SkeletonData::findAnimation(const String &animationName) { + return ContainerUtil::findWithName(_animations, animationName); +} + +IkConstraintData *SkeletonData::findIkConstraint(const String &constraintName) { + return ContainerUtil::findWithName(_ikConstraints, constraintName); +} + +TransformConstraintData *SkeletonData::findTransformConstraint(const String &constraintName) { + return ContainerUtil::findWithName(_transformConstraints, constraintName); +} + +PathConstraintData *SkeletonData::findPathConstraint(const String &constraintName) { + return ContainerUtil::findWithName(_pathConstraints, constraintName); +} + +PhysicsConstraintData *SkeletonData::findPhysicsConstraint(const String &constraintName) { + return ContainerUtil::findWithName(_physicsConstraints, constraintName); +} + +const String &SkeletonData::getName() { + return _name; +} + +void SkeletonData::setName(const String &inValue) { + _name = inValue; +} + +Vector &SkeletonData::getBones() { + return _bones; +} + +Vector &SkeletonData::getSlots() { + return _slots; +} + +Vector &SkeletonData::getSkins() { + return _skins; +} + +Skin *SkeletonData::getDefaultSkin() { + return _defaultSkin; +} + +void SkeletonData::setDefaultSkin(Skin *inValue) { + _defaultSkin = inValue; +} + +Vector &SkeletonData::getEvents() { + return _events; +} + +Vector &SkeletonData::getAnimations() { + return _animations; +} + +Vector &SkeletonData::getIkConstraints() { + return _ikConstraints; +} + +Vector &SkeletonData::getTransformConstraints() { + return _transformConstraints; +} + +Vector &SkeletonData::getPathConstraints() { + return _pathConstraints; +} + +Vector &SkeletonData::getPhysicsConstraints() { + return _physicsConstraints; +} + +float SkeletonData::getX() { + return _x; +} + +void SkeletonData::setX(float inValue) { + _x = inValue; +} + +float SkeletonData::getY() { + return _y; +} + +void SkeletonData::setY(float inValue) { + _y = inValue; +} + +float SkeletonData::getWidth() { + return _width; +} + +void SkeletonData::setWidth(float inValue) { + _width = inValue; +} + +float SkeletonData::getHeight() { + return _height; +} + +void SkeletonData::setHeight(float inValue) { + _height = inValue; +} + +float SkeletonData::getReferenceScale() { + return _referenceScale; +} + +void SkeletonData::setReferenceScale(float inValue) { + _referenceScale = inValue; +} + +const String &SkeletonData::getVersion() { + return _version; +} + +void SkeletonData::setVersion(const String &inValue) { + _version = inValue; +} + +const String &SkeletonData::getHash() { + return _hash; +} + +void SkeletonData::setHash(const String &inValue) { + _hash = inValue; +} + +const String &SkeletonData::getImagesPath() { + return _imagesPath; +} + +void SkeletonData::setImagesPath(const String &inValue) { + _imagesPath = inValue; +} + + +const String &SkeletonData::getAudioPath() { + return _audioPath; +} + +void SkeletonData::setAudioPath(const String &inValue) { + _audioPath = inValue; +} + +float SkeletonData::getFps() { + return _fps; +} + +void SkeletonData::setFps(float inValue) { + _fps = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp new file mode 100644 index 0000000..7dc5d34 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -0,0 +1,1617 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +static float toColor(const char *value, size_t index) { + char digits[3]; + char *error; + int color; + + if (index >= strlen(value) / 2) return -1; + + value += index * 2; + + digits[0] = *value; + digits[1] = *(value + 1); + digits[2] = '\0'; + color = (int) strtoul(digits, &error, 16); + if (*error != 0) return -1; + + return color / (float) 255; +} + +static void toColor(Color &color, const char *value, bool hasAlpha) { + color.r = toColor(value, 0); + color.g = toColor(value, 1); + color.b = toColor(value, 2); + if (hasAlpha) color.a = toColor(value, 3); +} + +SkeletonJson::SkeletonJson(Atlas *atlas) : _attachmentLoader(new (__FILE__, __LINE__) AtlasAttachmentLoader(atlas)), + _scale(1), _ownsLoader(true) {} + +SkeletonJson::SkeletonJson(AttachmentLoader *attachmentLoader, bool ownsLoader) : _attachmentLoader(attachmentLoader), + _scale(1), + _ownsLoader(ownsLoader) { + assert(_attachmentLoader != NULL); +} + +SkeletonJson::~SkeletonJson() { + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + + if (_ownsLoader) delete _attachmentLoader; +} + +SkeletonData *SkeletonJson::readSkeletonDataFile(const String &path) { + int length; + SkeletonData *skeletonData; + const char *json = SpineExtension::readFile(path, &length); + if (length == 0 || !json) { + setError(NULL, "Unable to read skeleton file: ", path); + return NULL; + } + + skeletonData = readSkeletonData(json); + + SpineExtension::free(json, __FILE__, __LINE__); + + return skeletonData; +} + +SkeletonData *SkeletonJson::readSkeletonData(const char *json) { + int i, ii; + SkeletonData *skeletonData; + Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *physics, *slots, *skins, *animations, *events; + + _error = ""; + _linkedMeshes.clear(); + + root = new (__FILE__, __LINE__) Json(json); + + if (!root) { + setError(NULL, "Invalid skeleton JSON: ", Json::getError()); + return NULL; + } + + skeletonData = new (__FILE__, __LINE__) SkeletonData(); + + skeleton = Json::getItem(root, "skeleton"); + if (skeleton) { + skeletonData->_hash = Json::getString(skeleton, "hash", 0); + skeletonData->_version = Json::getString(skeleton, "spine", 0); + if (!skeletonData->_version.startsWith(SPINE_VERSION_STRING)) { + char errorMsg[255]; + snprintf(errorMsg, 255, "Skeleton version %s does not match runtime version %s", skeletonData->_version.buffer(), SPINE_VERSION_STRING); + delete skeletonData; + setError(NULL, errorMsg, ""); + return NULL; + } + skeletonData->_x = Json::getFloat(skeleton, "x", 0); + skeletonData->_y = Json::getFloat(skeleton, "y", 0); + skeletonData->_width = Json::getFloat(skeleton, "width", 0); + skeletonData->_height = Json::getFloat(skeleton, "height", 0); + skeletonData->_referenceScale = Json::getFloat(skeleton, "referenceScale", 100) * _scale; + skeletonData->_fps = Json::getFloat(skeleton, "fps", 30); + skeletonData->_audioPath = Json::getString(skeleton, "audio", 0); + skeletonData->_imagesPath = Json::getString(skeleton, "images", 0); + } + + /* Bones. */ + bones = Json::getItem(root, "bones"); + skeletonData->_bones.setSize(bones->_size, 0); + int bonesCount = 0; + for (boneMap = bones->_child, i = 0; boneMap; boneMap = boneMap->_next, ++i) { + BoneData *data; + const char *inherit; + + BoneData *parent = 0; + const char *parentName = Json::getString(boneMap, "parent", 0); + if (parentName) { + parent = skeletonData->findBone(parentName); + if (!parent) { + delete skeletonData; + setError(root, "Parent bone not found: ", parentName); + return NULL; + } + } + + data = new (__FILE__, __LINE__) BoneData(bonesCount, Json::getString(boneMap, "name", 0), parent); + + data->_length = Json::getFloat(boneMap, "length", 0) * _scale; + data->_x = Json::getFloat(boneMap, "x", 0) * _scale; + data->_y = Json::getFloat(boneMap, "y", 0) * _scale; + data->_rotation = Json::getFloat(boneMap, "rotation", 0); + data->_scaleX = Json::getFloat(boneMap, "scaleX", 1); + data->_scaleY = Json::getFloat(boneMap, "scaleY", 1); + data->_shearX = Json::getFloat(boneMap, "shearX", 0); + data->_shearY = Json::getFloat(boneMap, "shearY", 0); + inherit = Json::getString(boneMap, "inherit", "normal"); + data->_inherit = Inherit_Normal; + if (strcmp(inherit, "normal") == 0) data->_inherit = Inherit_Normal; + else if (strcmp(inherit, "onlyTranslation") == 0) + data->_inherit = Inherit_OnlyTranslation; + else if (strcmp(inherit, "noRotationOrReflection") == 0) + data->_inherit = Inherit_NoRotationOrReflection; + else if (strcmp(inherit, "noScale") == 0) + data->_inherit = Inherit_NoScale; + else if (strcmp(inherit, "noScaleOrReflection") == 0) + data->_inherit = Inherit_NoScaleOrReflection; + data->_skinRequired = Json::getBoolean(boneMap, "skin", false); + + const char *color = Json::getString(boneMap, "color", NULL); + if (color) toColor(data->getColor(), color, true); + + data->_icon = Json::getString(boneMap, "icon", ""); + data->_visible = Json::getBoolean(boneMap, "visible", true); + + skeletonData->_bones[i] = data; + bonesCount++; + } + + /* Slots. */ + slots = Json::getItem(root, "slots"); + if (slots) { + Json *slotMap; + skeletonData->_slots.ensureCapacity(slots->_size); + skeletonData->_slots.setSize(slots->_size, 0); + for (slotMap = slots->_child, i = 0; slotMap; slotMap = slotMap->_next, ++i) { + SlotData *data; + const char *color; + const char *dark; + Json *item; + + const char *boneName = Json::getString(slotMap, "bone", 0); + BoneData *boneData = skeletonData->findBone(boneName); + if (!boneData) { + delete skeletonData; + setError(root, "Slot bone not found: ", boneName); + return NULL; + } + + String slotName = String(Json::getString(slotMap, "name", 0)); + data = new (__FILE__, __LINE__) SlotData(i, slotName, *boneData); + + color = Json::getString(slotMap, "color", 0); + if (color) { + Color &c = data->getColor(); + c.r = toColor(color, 0); + c.g = toColor(color, 1); + c.b = toColor(color, 2); + c.a = toColor(color, 3); + } + + dark = Json::getString(slotMap, "dark", 0); + if (dark) { + Color &darkColor = data->getDarkColor(); + darkColor.r = toColor(dark, 0); + darkColor.g = toColor(dark, 1); + darkColor.b = toColor(dark, 2); + darkColor.a = 1; + data->setHasDarkColor(true); + } + + item = Json::getItem(slotMap, "attachment"); + if (item) data->setAttachmentName(item->_valueString); + + item = Json::getItem(slotMap, "blend"); + if (item) { + if (strcmp(item->_valueString, "additive") == 0) data->_blendMode = BlendMode_Additive; + else if (strcmp(item->_valueString, "multiply") == 0) + data->_blendMode = BlendMode_Multiply; + else if (strcmp(item->_valueString, "screen") == 0) + data->_blendMode = BlendMode_Screen; + } + data->_visible = Json::getBoolean(slotMap, "visible", true); + skeletonData->_slots[i] = data; + } + } + + /* IK constraints. */ + ik = Json::getItem(root, "ik"); + if (ik) { + Json *constraintMap; + skeletonData->_ikConstraints.ensureCapacity(ik->_size); + skeletonData->_ikConstraints.setSize(ik->_size, 0); + for (constraintMap = ik->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *targetName; + + IkConstraintData *data = new (__FILE__, __LINE__) IkConstraintData( + Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.ensureCapacity(boneMap->_size); + data->_bones.setSize(boneMap->_size, 0); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) { + delete skeletonData; + setError(root, "IK bone not found: ", boneMap->_valueString); + return NULL; + } + } + + targetName = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findBone(targetName); + if (!data->_target) { + delete skeletonData; + setError(root, "Target bone not found: ", targetName); + return NULL; + } + + data->_mix = Json::getFloat(constraintMap, "mix", 1); + data->_softness = Json::getFloat(constraintMap, "softness", 0) * _scale; + data->_bendDirection = Json::getInt(constraintMap, "bendPositive", 1) ? 1 : -1; + data->_compress = Json::getInt(constraintMap, "compress", 0) ? true : false; + data->_stretch = Json::getInt(constraintMap, "stretch", 0) ? true : false; + data->_uniform = Json::getInt(constraintMap, "uniform", 0) ? true : false; + + skeletonData->_ikConstraints[i] = data; + } + } + + /* Transform constraints. */ + transform = Json::getItem(root, "transform"); + if (transform) { + Json *constraintMap; + skeletonData->_transformConstraints.ensureCapacity(transform->_size); + skeletonData->_transformConstraints.setSize(transform->_size, 0); + for (constraintMap = transform->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *name; + + TransformConstraintData *data = new (__FILE__, __LINE__) TransformConstraintData( + Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.ensureCapacity(boneMap->_size); + data->_bones.setSize(boneMap->_size, 0); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) { + delete skeletonData; + setError(root, "Transform bone not found: ", boneMap->_valueString); + return NULL; + } + } + + name = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findBone(name); + if (!data->_target) { + delete skeletonData; + setError(root, "Target bone not found: ", name); + return NULL; + } + + data->_local = Json::getInt(constraintMap, "local", 0) ? true : false; + data->_relative = Json::getInt(constraintMap, "relative", 0) ? true : false; + data->_offsetRotation = Json::getFloat(constraintMap, "rotation", 0); + data->_offsetX = Json::getFloat(constraintMap, "x", 0) * _scale; + data->_offsetY = Json::getFloat(constraintMap, "y", 0) * _scale; + data->_offsetScaleX = Json::getFloat(constraintMap, "scaleX", 0); + data->_offsetScaleY = Json::getFloat(constraintMap, "scaleY", 0); + data->_offsetShearY = Json::getFloat(constraintMap, "shearY", 0); + + data->_mixRotate = Json::getFloat(constraintMap, "mixRotate", 1); + data->_mixX = Json::getFloat(constraintMap, "mixX", 1); + data->_mixY = Json::getFloat(constraintMap, "mixY", data->_mixX); + data->_mixScaleX = Json::getFloat(constraintMap, "mixScaleX", 1); + data->_mixScaleY = Json::getFloat(constraintMap, "mixScaleY", data->_mixScaleX); + data->_mixShearY = Json::getFloat(constraintMap, "mixShearY", 1); + + skeletonData->_transformConstraints[i] = data; + } + } + + /* Path constraints */ + path = Json::getItem(root, "path"); + if (path) { + Json *constraintMap; + skeletonData->_pathConstraints.ensureCapacity(path->_size); + skeletonData->_pathConstraints.setSize(path->_size, 0); + for (constraintMap = path->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *name; + const char *item; + + PathConstraintData *data = new (__FILE__, __LINE__) PathConstraintData( + Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.ensureCapacity(boneMap->_size); + data->_bones.setSize(boneMap->_size, 0); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) { + delete skeletonData; + setError(root, "Path bone not found: ", boneMap->_valueString); + return NULL; + } + } + + name = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findSlot(name); + if (!data->_target) { + delete skeletonData; + setError(root, "Target slot not found: ", name); + return NULL; + } + + item = Json::getString(constraintMap, "positionMode", "percent"); + if (strcmp(item, "fixed") == 0) { + data->_positionMode = PositionMode_Fixed; + } else if (strcmp(item, "percent") == 0) { + data->_positionMode = PositionMode_Percent; + } + + item = Json::getString(constraintMap, "spacingMode", "length"); + if (strcmp(item, "length") == 0) data->_spacingMode = SpacingMode_Length; + else if (strcmp(item, "fixed") == 0) + data->_spacingMode = SpacingMode_Fixed; + else if (strcmp(item, "percent") == 0) + data->_spacingMode = SpacingMode_Percent; + else + data->_spacingMode = SpacingMode_Proportional; + + item = Json::getString(constraintMap, "rotateMode", "tangent"); + if (strcmp(item, "tangent") == 0) data->_rotateMode = RotateMode_Tangent; + else if (strcmp(item, "chain") == 0) + data->_rotateMode = RotateMode_Chain; + else if (strcmp(item, "chainScale") == 0) + data->_rotateMode = RotateMode_ChainScale; + + data->_offsetRotation = Json::getFloat(constraintMap, "rotation", 0); + data->_position = Json::getFloat(constraintMap, "position", 0); + if (data->_positionMode == PositionMode_Fixed) data->_position *= _scale; + data->_spacing = Json::getFloat(constraintMap, "spacing", 0); + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) + data->_spacing *= _scale; + data->_mixRotate = Json::getFloat(constraintMap, "mixRotate", 1); + data->_mixX = Json::getFloat(constraintMap, "mixX", 1); + data->_mixY = Json::getFloat(constraintMap, "mixY", data->_mixX); + + skeletonData->_pathConstraints[i] = data; + } + } + + /* Physics constraints */ + physics = Json::getItem(root, "physics"); + if (physics) { + Json *constraintMap; + skeletonData->_physicsConstraints.ensureCapacity(physics->_size); + skeletonData->_physicsConstraints.setSize(physics->_size, 0); + for (constraintMap = physics->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *name; + + PhysicsConstraintData *data = new (__FILE__, __LINE__) PhysicsConstraintData( + Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + name = Json::getString(constraintMap, "bone", 0); + data->_bone = skeletonData->findBone(name); + if (!data->_bone) { + delete skeletonData; + setError(root, "Physics bone not found: ", name); + return NULL; + } + + data->_x = Json::getFloat(constraintMap, "x", 0); + data->_y = Json::getFloat(constraintMap, "y", 0); + data->_rotate = Json::getFloat(constraintMap, "rotate", 0); + data->_scaleX = Json::getFloat(constraintMap, "scaleX", 0); + data->_shearX = Json::getFloat(constraintMap, "shearX", 0); + data->_limit = Json::getFloat(constraintMap, "limit", 5000) * _scale; + data->_step = 1.0f / Json::getInt(constraintMap, "fps", 60); + data->_inertia = Json::getFloat(constraintMap, "inertia", 1); + data->_strength = Json::getFloat(constraintMap, "strength", 100); + data->_damping = Json::getFloat(constraintMap, "damping", 1); + data->_massInverse = 1.0f / Json::getFloat(constraintMap, "mass", 1); + data->_wind = Json::getFloat(constraintMap, "wind", 0); + data->_gravity = Json::getFloat(constraintMap, "gravity", 0); + data->_mix = Json::getFloat(constraintMap, "mix", 1); + data->_inertiaGlobal = Json::getBoolean(constraintMap, "inertiaGlobal", false); + data->_strengthGlobal = Json::getBoolean(constraintMap, "strengthGlobal", false); + data->_dampingGlobal = Json::getBoolean(constraintMap, "dampingGlobal", false); + data->_massGlobal = Json::getBoolean(constraintMap, "massGlobal", false); + data->_windGlobal = Json::getBoolean(constraintMap, "windGlobal", false); + data->_gravityGlobal = Json::getBoolean(constraintMap, "gravityGlobal", false); + data->_mixGlobal = Json::getBoolean(constraintMap, "mixGlobal", false); + + skeletonData->_physicsConstraints[i] = data; + } + } + + /* Skins. */ + skins = Json::getItem(root, "skins"); + if (skins) { + Json *skinMap; + skeletonData->_skins.ensureCapacity(skins->_size); + skeletonData->_skins.setSize(skins->_size, 0); + int skinsIndex = 0; + for (skinMap = skins->_child, i = 0; skinMap; skinMap = skinMap->_next, ++i) { + Json *attachmentsMap; + Json *curves; + + Skin *skin = new (__FILE__, __LINE__) Skin(Json::getString(skinMap, "name", "")); + + Json *item = Json::getItem(skinMap, "bones"); + if (item) { + for (item = item->_child; item; item = item->_next) { + BoneData *data = skeletonData->findBone(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin bone not found: "), item->_valueString); + return NULL; + } + skin->getBones().add(data); + } + } + + item = Json::getItem(skinMap, "ik"); + if (item) { + for (item = item->_child; item; item = item->_next) { + IkConstraintData *data = skeletonData->findIkConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin IK constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + item = Json::getItem(skinMap, "transform"); + if (item) { + for (item = item->_child; item; item = item->_next) { + TransformConstraintData *data = skeletonData->findTransformConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin transform constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + item = Json::getItem(skinMap, "path"); + if (item) { + for (item = item->_child; item; item = item->_next) { + PathConstraintData *data = skeletonData->findPathConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin path constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + item = Json::getItem(skinMap, "physics"); + if (item) { + for (item = item->_child; item; item = item->_next) { + PhysicsConstraintData *data = skeletonData->findPhysicsConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin physics constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + skeletonData->_skins[skinsIndex++] = skin; + if (strcmp(Json::getString(skinMap, "name", ""), "default") == 0) { + skeletonData->_defaultSkin = skin; + } + + Json *attachments = Json::getItem(skinMap, "attachments"); + if (attachments) + for (attachmentsMap = attachments->_child; + attachmentsMap; attachmentsMap = attachmentsMap->_next) { + SlotData *slot = skeletonData->findSlot(attachmentsMap->_name); + Json *attachmentMap; + + for (attachmentMap = attachmentsMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) { + Attachment *attachment = NULL; + const char *skinAttachmentName = attachmentMap->_name; + const char *attachmentName = Json::getString(attachmentMap, "name", skinAttachmentName); + const char *attachmentPath = Json::getString(attachmentMap, "path", attachmentName); + const char *color; + Json *entry; + + const char *typeString = Json::getString(attachmentMap, "type", "region"); + AttachmentType type; + if (strcmp(typeString, "region") == 0) type = AttachmentType_Region; + else if (strcmp(typeString, "mesh") == 0) + type = AttachmentType_Mesh; + else if (strcmp(typeString, "linkedmesh") == 0) + type = AttachmentType_Linkedmesh; + else if (strcmp(typeString, "boundingbox") == 0) + type = AttachmentType_Boundingbox; + else if (strcmp(typeString, "path") == 0) + type = AttachmentType_Path; + else if (strcmp(typeString, "clipping") == 0) + type = AttachmentType_Clipping; + else if (strcmp(typeString, "point") == 0) + type = AttachmentType_Point; + else { + delete skeletonData; + setError(root, "Unknown attachment type: ", typeString); + return NULL; + } + + switch (type) { + case AttachmentType_Region: { + Sequence *sequence = readSequence(Json::getItem(attachmentMap, "sequence")); + attachment = _attachmentLoader->newRegionAttachment(*skin, attachmentName, attachmentPath, sequence); + if (!attachment) { + delete skeletonData; + setError(root, "Error reading attachment: ", skinAttachmentName); + return NULL; + } + + RegionAttachment *region = static_cast(attachment); + region->_path = attachmentPath; + + region->_x = Json::getFloat(attachmentMap, "x", 0) * _scale; + region->_y = Json::getFloat(attachmentMap, "y", 0) * _scale; + region->_scaleX = Json::getFloat(attachmentMap, "scaleX", 1); + region->_scaleY = Json::getFloat(attachmentMap, "scaleY", 1); + region->_rotation = Json::getFloat(attachmentMap, "rotation", 0); + region->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; + region->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; + region->_sequence = sequence; + + color = Json::getString(attachmentMap, "color", 0); + if (color) toColor(region->getColor(), color, true); + + if (region->_region != NULL) region->updateRegion(); + _attachmentLoader->configureAttachment(region); + break; + } + case AttachmentType_Mesh: + case AttachmentType_Linkedmesh: { + Sequence *sequence = readSequence(Json::getItem(attachmentMap, "sequence")); + attachment = _attachmentLoader->newMeshAttachment(*skin, attachmentName, attachmentPath, sequence); + + if (!attachment) { + delete skeletonData; + setError(root, "Error reading attachment: ", skinAttachmentName); + return NULL; + } + + MeshAttachment *mesh = static_cast(attachment); + mesh->_path = attachmentPath; + + color = Json::getString(attachmentMap, "color", 0); + if (color) toColor(mesh->getColor(), color, true); + + mesh->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; + mesh->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; + mesh->_sequence = sequence; + + entry = Json::getItem(attachmentMap, "parent"); + if (!entry) { + int verticesLength; + entry = Json::getItem(attachmentMap, "triangles"); + mesh->_triangles.ensureCapacity(entry->_size); + mesh->_triangles.setSize(entry->_size, 0); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + mesh->_triangles[ii] = (unsigned short) entry->_valueInt; + + entry = Json::getItem(attachmentMap, "uvs"); + verticesLength = entry->_size; + mesh->_regionUVs.ensureCapacity(verticesLength); + mesh->_regionUVs.setSize(verticesLength, 0); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + mesh->_regionUVs[ii] = entry->_valueFloat; + + readVertices(attachmentMap, mesh, verticesLength); + + if (mesh->_region != NULL) mesh->updateRegion(); + + mesh->_hullLength = Json::getInt(attachmentMap, "hull", 0); + + entry = Json::getItem(attachmentMap, "edges"); + if (entry) { + mesh->_edges.ensureCapacity(entry->_size); + mesh->_edges.setSize(entry->_size, 0); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + mesh->_edges[ii] = entry->_valueInt; + } + _attachmentLoader->configureAttachment(mesh); + } else { + bool inheritTimelines = Json::getInt(attachmentMap, "timelines", 1) ? true : false; + LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, + String(Json::getString( + attachmentMap, + "skin", 0)), + slot->getIndex(), + String(entry->_valueString), + inheritTimelines); + _linkedMeshes.add(linkedMesh); + } + break; + } + case AttachmentType_Boundingbox: { + attachment = _attachmentLoader->newBoundingBoxAttachment(*skin, attachmentName); + + BoundingBoxAttachment *box = static_cast(attachment); + + int vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; + readVertices(attachmentMap, box, vertexCount); + color = Json::getString(attachmentMap, "color", NULL); + if (color) toColor(box->getColor(), color, true); + _attachmentLoader->configureAttachment(attachment); + break; + } + case AttachmentType_Path: { + attachment = _attachmentLoader->newPathAttachment(*skin, attachmentName); + + PathAttachment *pathAttatchment = static_cast(attachment); + + int vertexCount = 0; + pathAttatchment->_closed = Json::getInt(attachmentMap, "closed", 0) ? true : false; + pathAttatchment->_constantSpeed = Json::getInt(attachmentMap, "constantSpeed", 1) ? true + : false; + vertexCount = Json::getInt(attachmentMap, "vertexCount", 0); + readVertices(attachmentMap, pathAttatchment, vertexCount << 1); + + pathAttatchment->_lengths.ensureCapacity(vertexCount / 3); + pathAttatchment->_lengths.setSize(vertexCount / 3, 0); + + curves = Json::getItem(attachmentMap, "lengths"); + for (curves = curves->_child, ii = 0; curves; curves = curves->_next, ++ii) + pathAttatchment->_lengths[ii] = curves->_valueFloat * _scale; + color = Json::getString(attachmentMap, "color", NULL); + if (color) toColor(pathAttatchment->getColor(), color, true); + _attachmentLoader->configureAttachment(attachment); + break; + } + case AttachmentType_Point: { + attachment = _attachmentLoader->newPointAttachment(*skin, attachmentName); + + PointAttachment *point = static_cast(attachment); + + point->_x = Json::getFloat(attachmentMap, "x", 0) * _scale; + point->_y = Json::getFloat(attachmentMap, "y", 0) * _scale; + point->_rotation = Json::getFloat(attachmentMap, "rotation", 0); + color = Json::getString(attachmentMap, "color", NULL); + if (color) toColor(point->getColor(), color, true); + _attachmentLoader->configureAttachment(attachment); + break; + } + case AttachmentType_Clipping: { + attachment = _attachmentLoader->newClippingAttachment(*skin, attachmentName); + + ClippingAttachment *clip = static_cast(attachment); + + int vertexCount = 0; + const char *end = Json::getString(attachmentMap, "end", 0); + if (end) clip->_endSlot = skeletonData->findSlot(end); + vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; + readVertices(attachmentMap, clip, vertexCount); + color = Json::getString(attachmentMap, "color", NULL); + if (color) toColor(clip->getColor(), color, true); + _attachmentLoader->configureAttachment(attachment); + break; + } + } + + skin->setAttachment(slot->getIndex(), skinAttachmentName, attachment); + } + } + } + } + + /* Linked meshes. */ + int n = (int) _linkedMeshes.size(); + for (i = 0; i < n; ++i) { + LinkedMesh *linkedMesh = _linkedMeshes[i]; + Skin *skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin(linkedMesh->_skin); + if (skin == NULL) { + delete skeletonData; + setError(root, "Skin not found: ", linkedMesh->_skin.buffer()); + return NULL; + } + Attachment *parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); + if (parent == NULL) { + delete skeletonData; + setError(root, "Parent mesh not found: ", linkedMesh->_parent.buffer()); + return NULL; + } + linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritTimeline ? static_cast(parent) + : linkedMesh->_mesh; + linkedMesh->_mesh->setParentMesh(static_cast(parent)); + if (linkedMesh->_mesh->_region != NULL) linkedMesh->_mesh->updateRegion(); + _attachmentLoader->configureAttachment(linkedMesh->_mesh); + } + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + /* Events. */ + events = Json::getItem(root, "events"); + if (events) { + Json *eventMap; + skeletonData->_events.ensureCapacity(events->_size); + skeletonData->_events.setSize(events->_size, 0); + for (eventMap = events->_child, i = 0; eventMap; eventMap = eventMap->_next, ++i) { + EventData *eventData = new (__FILE__, __LINE__) EventData(String(eventMap->_name)); + + eventData->_intValue = Json::getInt(eventMap, "int", 0); + eventData->_floatValue = Json::getFloat(eventMap, "float", 0); + const char *stringValue = Json::getString(eventMap, "string", 0); + eventData->_stringValue = stringValue; + const char *audioPath = Json::getString(eventMap, "audio", 0); + eventData->_audioPath = audioPath; + if (audioPath) { + eventData->_volume = Json::getFloat(eventMap, "volume", 1); + eventData->_balance = Json::getFloat(eventMap, "balance", 0); + } + skeletonData->_events[i] = eventData; + } + } + + /* Animations. */ + animations = Json::getItem(root, "animations"); + if (animations) { + Json *animationMap; + skeletonData->_animations.ensureCapacity(animations->_size); + skeletonData->_animations.setSize(animations->_size, 0); + int animationsIndex = 0; + for (animationMap = animations->_child; animationMap; animationMap = animationMap->_next) { + Animation *animation = readAnimation(animationMap, skeletonData); + if (!animation) { + delete skeletonData; + delete root; + return NULL; + } + skeletonData->_animations[animationsIndex++] = animation; + } + } + + delete root; + + return skeletonData; +} + +Sequence *SkeletonJson::readSequence(Json *item) { + if (item == NULL) return NULL; + Sequence *sequence = new Sequence(Json::getInt(item, "count", 0)); + sequence->_start = Json::getInt(item, "start", 1); + sequence->_digits = Json::getInt(item, "digits", 0); + sequence->_setupIndex = Json::getInt(item, "setupIndex", 0); + return sequence; +} + +void SkeletonJson::setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1, + float cy1, + float cx2, float cy2, float time2, float value2) { + timeline->setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2); +} + +int SkeletonJson::readCurve(Json *curve, CurveTimeline *timeline, int bezier, int frame, int value, float time1, + float time2, + float value1, float value2, float scale) { + if (curve->_type == Json::JSON_STRING && strcmp(curve->_valueString, "stepped") == 0) { + timeline->setStepped(frame); + return bezier; + } + curve = Json::getItem(curve, value << 2); + float cx1 = curve->_valueFloat; + curve = curve->_next; + float cy1 = curve->_valueFloat * scale; + curve = curve->_next; + float cx2 = curve->_valueFloat; + curve = curve->_next; + float cy2 = curve->_valueFloat * scale; + setBezier(timeline, frame, value, bezier, time1, value1, cx1, cy1, cx2, cy2, time2, value2); + return bezier + 1; +} + +Timeline *SkeletonJson::readTimeline(Json *keyMap, CurveTimeline1 *timeline, float defaultValue, float scale) { + float time = Json::getFloat(keyMap, "time", 0); + float value = Json::getFloat(keyMap, "value", defaultValue) * scale; + int bezier = 0; + for (int frame = 0;; frame++) { + timeline->setFrame(frame, time, value); + Json *nextMap = keyMap->_next; + if (!nextMap) break; + float time2 = Json::getFloat(nextMap, "time", 0); + float value2 = Json::getFloat(nextMap, "value", defaultValue) * scale; + Json *curve = Json::getItem(keyMap, "curve"); + if (curve != NULL) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value, value2, scale); + time = time2; + value = value2; + keyMap = nextMap; + } + // timeline.shrink(); // BOZO + return timeline; +} + +Timeline *SkeletonJson::readTimeline(Json *keyMap, CurveTimeline2 *timeline, const char *name1, const char *name2, + float defaultValue, float scale) { + float time = Json::getFloat(keyMap, "time", 0); + float value1 = Json::getFloat(keyMap, name1, defaultValue) * scale; + float value2 = Json::getFloat(keyMap, name2, defaultValue) * scale; + int bezier = 0; + for (int frame = 0;; frame++) { + timeline->setFrame(frame, time, value1, value2); + Json *nextMap = keyMap->_next; + if (!nextMap) break; + float time2 = Json::getFloat(nextMap, "time", 0); + float nvalue1 = Json::getFloat(nextMap, name1, defaultValue) * scale; + float nvalue2 = Json::getFloat(nextMap, name2, defaultValue) * scale; + Json *curve = Json::getItem(keyMap, "curve"); + if (curve != NULL) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + keyMap = nextMap; + } + // timeline.shrink(); // BOZO + return timeline; +} + +int SkeletonJson::findSlotIndex(SkeletonData *skeletonData, const String &slotName, Vector timelines) { + int slotIndex = ContainerUtil::findIndexWithName(skeletonData->getSlots(), slotName); + if (slotIndex == -1) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Slot not found: ", slotName); + } + return slotIndex; +} + +Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) { + Vector timelines; + Json *bones = Json::getItem(root, "bones"); + Json *slots = Json::getItem(root, "slots"); + Json *ik = Json::getItem(root, "ik"); + Json *transform = Json::getItem(root, "transform"); + Json *paths = Json::getItem(root, "path"); + Json *physics = Json::getItem(root, "physics"); + Json *attachments = Json::getItem(root, "attachments"); + Json *drawOrder = Json::getItem(root, "drawOrder"); + Json *events = Json::getItem(root, "events"); + Json *boneMap, *slotMap, *keyMap, *nextMap, *curve; + int frame, bezier; + Color color, color2, newColor, newColor2; + + /** Slot timelines. */ + for (slotMap = slots ? slots->_child : 0; slotMap; slotMap = slotMap->_next) { + int slotIndex = findSlotIndex(skeletonData, slotMap->_name, timelines); + if (slotIndex == -1) return NULL; + + for (Json *timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) { + int frames = timelineMap->_size; + if (strcmp(timelineMap->_name, "attachment") == 0) { + AttachmentTimeline *timeline = new (__FILE__, __LINE__) AttachmentTimeline(frames, slotIndex); + for (keyMap = timelineMap->_child, frame = 0; keyMap; keyMap = keyMap->_next, ++frame) { + timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0), + Json::getItem(keyMap, "name") ? Json::getItem(keyMap, "name")->_valueString : NULL); + } + timelines.add(timeline); + + } else if (strcmp(timelineMap->_name, "rgba") == 0) { + RGBATimeline *timeline = new (__FILE__, __LINE__) RGBATimeline(frames, frames << 2, slotIndex); + keyMap = timelineMap->_child; + float time = Json::getFloat(keyMap, "time", 0); + toColor(color, Json::getString(keyMap, "color", 0), true); + + for (frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b, color.a); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + toColor(newColor, Json::getString(nextMap, "color", 0), true); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (strcmp(timelineMap->_name, "rgb") == 0) { + RGBTimeline *timeline = new (__FILE__, __LINE__) RGBTimeline(frames, frames * 3, slotIndex); + keyMap = timelineMap->_child; + float time = Json::getFloat(keyMap, "time", 0); + toColor(color, Json::getString(keyMap, "color", 0), false); + + for (frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + toColor(newColor, Json::getString(nextMap, "color", 0), false); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (strcmp(timelineMap->_name, "alpha") == 0) { + timelines.add(readTimeline(timelineMap->_child, + new (__FILE__, __LINE__) AlphaTimeline(frames, frames, slotIndex), + 0, 1)); + } else if (strcmp(timelineMap->_name, "rgba2") == 0) { + RGBA2Timeline *timeline = new (__FILE__, __LINE__) RGBA2Timeline(frames, frames * 7, slotIndex); + keyMap = timelineMap->_child; + float time = Json::getFloat(keyMap, "time", 0); + toColor(color, Json::getString(keyMap, "light", 0), true); + toColor(color2, Json::getString(keyMap, "dark", 0), false); + + for (frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + toColor(newColor, Json::getString(nextMap, "light", 0), true); + toColor(newColor2, Json::getString(nextMap, "dark", 0), false); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (strcmp(timelineMap->_name, "rgb2") == 0) { + RGB2Timeline *timeline = new (__FILE__, __LINE__) RGB2Timeline(frames, frames * 6, slotIndex); + keyMap = timelineMap->_child; + float time = Json::getFloat(keyMap, "time", 0); + toColor(color, Json::getString(keyMap, "light", 0), false); + toColor(color2, Json::getString(keyMap, "dark", 0), false); + + for (frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b, color2.r, color2.g, color2.b); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + toColor(newColor, Json::getString(nextMap, "light", 0), false); + toColor(newColor2, Json::getString(nextMap, "dark", 0), false); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.add(timeline); + } else { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Invalid timeline type for a slot: ", timelineMap->_name); + return NULL; + } + } + } + + /** Bone timelines. */ + for (boneMap = bones ? bones->_child : 0; boneMap; boneMap = boneMap->_next) { + int boneIndex = ContainerUtil::findIndexWithName(skeletonData->_bones, boneMap->_name); + if (boneIndex == -1) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Bone not found: ", boneMap->_name); + return NULL; + } + + for (Json *timelineMap = boneMap->_child; timelineMap; timelineMap = timelineMap->_next) { + int frames = timelineMap->_size; + if (frames == 0) continue; + + if (strcmp(timelineMap->_name, "rotate") == 0) { + timelines.add(readTimeline(timelineMap->_child, + new RotateTimeline(frames, frames, boneIndex), 0, + 1)); + } else if (strcmp(timelineMap->_name, "translate") == 0) { + TranslateTimeline *timeline = new TranslateTimeline(frames, frames << 1, + boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, "x", "y", 0, _scale)); + } else if (strcmp(timelineMap->_name, "translatex") == 0) { + TranslateXTimeline *timeline = new TranslateXTimeline(frames, frames, + boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 0, _scale)); + } else if (strcmp(timelineMap->_name, "translatey") == 0) { + TranslateYTimeline *timeline = new TranslateYTimeline(frames, frames, + boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 0, _scale)); + } else if (strcmp(timelineMap->_name, "scale") == 0) { + ScaleTimeline *timeline = new (__FILE__, __LINE__) ScaleTimeline(frames, + frames << 1, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, "x", "y", 1, 1)); + } else if (strcmp(timelineMap->_name, "scalex") == 0) { + ScaleXTimeline *timeline = new (__FILE__, __LINE__) ScaleXTimeline(frames, + frames, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 1, 1)); + } else if (strcmp(timelineMap->_name, "scaley") == 0) { + ScaleYTimeline *timeline = new (__FILE__, __LINE__) ScaleYTimeline(frames, + frames, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 1, 1)); + } else if (strcmp(timelineMap->_name, "shear") == 0) { + ShearTimeline *timeline = new (__FILE__, __LINE__) ShearTimeline(frames, + frames << 1, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, "x", "y", 0, 1)); + } else if (strcmp(timelineMap->_name, "shearx") == 0) { + ShearXTimeline *timeline = new (__FILE__, __LINE__) ShearXTimeline(frames, + frames, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 0, 1)); + } else if (strcmp(timelineMap->_name, "sheary") == 0) { + ShearYTimeline *timeline = new (__FILE__, __LINE__) ShearYTimeline(frames, + frames, boneIndex); + timelines.add(readTimeline(timelineMap->_child, timeline, 0, 1)); + } else if (strcmp(timelineMap->_name, "inherit") == 0) { + InheritTimeline *timeline = new (__FILE__, __LINE__) InheritTimeline(frames, boneIndex); + keyMap = timelineMap->_child; + for (frame = 0;; frame++) { + float time = Json::getFloat(keyMap, "time", 0); + const char *value = Json::getString(keyMap, "inherit", "normal"); + Inherit inherit = Inherit_Normal; + if (strcmp(value, "normal") == 0) inherit = Inherit_Normal; + else if (strcmp(value, "onlyTranslation") == 0) + inherit = Inherit_OnlyTranslation; + else if (strcmp(value, "noRotationOrReflection") == 0) + inherit = Inherit_NoRotationOrReflection; + else if (strcmp(value, "noScale") == 0) + inherit = Inherit_NoScale; + else if (strcmp(value, "noScaleOrReflection") == 0) + inherit = Inherit_NoScaleOrReflection; + timeline->setFrame(frame, time, inherit); + nextMap = keyMap->_next; + if (!nextMap) break; + keyMap = nextMap; + } + timelines.add(timeline); + } else { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Invalid timeline type for a bone: ", timelineMap->_name); + return NULL; + } + } + } + + /** IK constraint timelines. */ + for (Json *constraintMap = ik ? ik->_child : 0; constraintMap; constraintMap = constraintMap->_next) { + keyMap = constraintMap->_child; + if (keyMap == NULL) continue; + + IkConstraintData *constraint = skeletonData->findIkConstraint(constraintMap->_name); + int constraintIndex = skeletonData->_ikConstraints.indexOf(constraint); + IkConstraintTimeline *timeline = new (__FILE__, __LINE__) IkConstraintTimeline(constraintMap->_size, + constraintMap->_size << 1, + constraintIndex); + + float time = Json::getFloat(keyMap, "time", 0); + float mix = Json::getFloat(keyMap, "mix", 1); + float softness = Json::getFloat(keyMap, "softness", 0) * _scale; + + for (frame = 0, bezier = 0;; frame++) { + int bendDirection = Json::getBoolean(keyMap, "bendPositive", true) ? 1 : -1; + timeline->setFrame(frame, time, mix, softness, bendDirection, Json::getBoolean(keyMap, "compress", false), + Json::getBoolean(keyMap, "stretch", false)); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + + float time2 = Json::getFloat(nextMap, "time", 0); + float mix2 = Json::getFloat(nextMap, "mix", 1); + float softness2 = Json::getFloat(nextMap, "softness", 0) * _scale; + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, _scale); + } + + time = time2; + mix = mix2; + softness = softness2; + keyMap = nextMap; + } + + timelines.add(timeline); + } + + /** Transform constraint timelines. */ + for (Json *constraintMap = transform ? transform->_child : 0; constraintMap; constraintMap = constraintMap->_next) { + keyMap = constraintMap->_child; + if (keyMap == NULL) continue; + + TransformConstraintData *constraint = skeletonData->findTransformConstraint(constraintMap->_name); + int constraintIndex = skeletonData->_transformConstraints.indexOf(constraint); + TransformConstraintTimeline *timeline = new (__FILE__, __LINE__) TransformConstraintTimeline( + constraintMap->_size, constraintMap->_size * 6, constraintIndex); + + float time = Json::getFloat(keyMap, "time", 0); + float mixRotate = Json::getFloat(keyMap, "mixRotate", 1); + float mixShearY = Json::getFloat(keyMap, "mixShearY", 1); + float mixX = Json::getFloat(keyMap, "mixX", 1); + float mixY = Json::getFloat(keyMap, "mixY", mixX); + float mixScaleX = Json::getFloat(keyMap, "mixScaleX", 1); + float mixScaleY = Json::getFloat(keyMap, "mixScaleY", mixScaleX); + + for (frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + + float time2 = Json::getFloat(nextMap, "time", 0); + float mixRotate2 = Json::getFloat(nextMap, "mixRotate", 1); + float mixShearY2 = Json::getFloat(nextMap, "mixShearY", 1); + float mixX2 = Json::getFloat(nextMap, "mixX", 1); + float mixY2 = Json::getFloat(nextMap, "mixY", mixX2); + float mixScaleX2 = Json::getFloat(nextMap, "mixScaleX", 1); + float mixScaleY2 = Json::getFloat(nextMap, "mixScaleY", mixScaleX2); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + keyMap = nextMap; + } + + timelines.add(timeline); + } + + /** Path constraint timelines. */ + for (Json *constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) { + PathConstraintData *constraint = skeletonData->findPathConstraint(constraintMap->_name); + if (!constraint) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Path constraint not found: ", constraintMap->_name); + return NULL; + } + int constraintIndex = skeletonData->_pathConstraints.indexOf(constraint); + for (Json *timelineMap = constraintMap->_child; timelineMap; timelineMap = timelineMap->_next) { + keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + const char *timelineName = timelineMap->_name; + int frames = timelineMap->_size; + if (strcmp(timelineName, "position") == 0) { + PathConstraintPositionTimeline *timeline = new (__FILE__, __LINE__) PathConstraintPositionTimeline( + frames, frames, constraintIndex); + timelines.add( + readTimeline(keyMap, timeline, 0, constraint->_positionMode == PositionMode_Fixed ? _scale : 1)); + } else if (strcmp(timelineName, "spacing") == 0) { + CurveTimeline1 *timeline = new PathConstraintSpacingTimeline(frames, frames, + constraintIndex); + timelines.add(readTimeline(keyMap, timeline, 0, + constraint->_spacingMode == SpacingMode_Length || + constraint->_spacingMode == SpacingMode_Fixed + ? _scale + : 1)); + } else if (strcmp(timelineName, "mix") == 0) { + PathConstraintMixTimeline *timeline = new PathConstraintMixTimeline(frames, + frames * 3, constraintIndex); + float time = Json::getFloat(keyMap, "time", 0); + float mixRotate = Json::getFloat(keyMap, "mixRotate", 1); + float mixX = Json::getFloat(keyMap, "mixX", 1); + float mixY = Json::getFloat(keyMap, "mixY", mixX); + for (frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + float mixRotate2 = Json::getFloat(nextMap, "mixRotate", 1); + float mixX2 = Json::getFloat(nextMap, "mixX", 1); + float mixY2 = Json::getFloat(nextMap, "mixY", mixX2); + curve = Json::getItem(keyMap, "curve"); + if (curve != NULL) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + keyMap = nextMap; + } + timelines.add(timeline); + } + } + } + + /** Physics constraint timelines. */ + for (Json *constraintMap = physics ? physics->_child : 0; constraintMap; constraintMap = constraintMap->_next) { + int index = -1; + if (constraintMap->_name && strlen(constraintMap->_name) > 0) { + PhysicsConstraintData *constraint = skeletonData->findPhysicsConstraint(constraintMap->_name); + if (!constraint) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Physics constraint not found: ", constraintMap->_name); + return NULL; + } + index = skeletonData->_physicsConstraints.indexOf(constraint); + } + for (Json *timelineMap = constraintMap->_child; timelineMap; timelineMap = timelineMap->_next) { + keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + const char *timelineName = timelineMap->_name; + int frames = timelineMap->_size; + if (strcmp(timelineName, "reset") == 0) { + PhysicsConstraintResetTimeline *timeline = new (__FILE__, __LINE__) PhysicsConstraintResetTimeline(frames, index); + for (frame = 0; keyMap != nullptr; keyMap = keyMap->_next, frame++) { + timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0)); + } + timelines.add(timeline); + continue; + } + + CurveTimeline1 *timeline = nullptr; + if (strcmp(timelineName, "inertia") == 0) { + timeline = new PhysicsConstraintInertiaTimeline(frames, frames, index); + } else if (strcmp(timelineName, "strength") == 0) { + timeline = new PhysicsConstraintStrengthTimeline(frames, frames, index); + } else if (strcmp(timelineName, "damping") == 0) { + timeline = new PhysicsConstraintDampingTimeline(frames, frames, index); + } else if (strcmp(timelineName, "mass") == 0) { + timeline = new PhysicsConstraintMassTimeline(frames, frames, index); + } else if (strcmp(timelineName, "wind") == 0) { + timeline = new PhysicsConstraintWindTimeline(frames, frames, index); + } else if (strcmp(timelineName, "gravity") == 0) { + timeline = new PhysicsConstraintGravityTimeline(frames, frames, index); + } else if (strcmp(timelineName, "mix") == 0) { + timeline = new PhysicsConstraintMixTimeline(frames, frames, index); + } else { + continue; + } + timelines.add(readTimeline(keyMap, timeline, 0, 1)); + } + } + + /** Attachment timelines. */ + for (Json *attachmenstMap = attachments ? attachments->_child : NULL; attachmenstMap; attachmenstMap = attachmenstMap->_next) { + Skin *skin = skeletonData->findSkin(attachmenstMap->_name); + for (slotMap = attachmenstMap->_child; slotMap; slotMap = slotMap->_next) { + int slotIndex = findSlotIndex(skeletonData, slotMap->_name, timelines); + if (slotIndex == -1) return NULL; + + for (Json *attachmentMap = slotMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) { + Attachment *attachment = skin->getAttachment(slotIndex, attachmentMap->_name); + if (!attachment) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Attachment not found: ", attachmentMap->_name); + return NULL; + } + + for (Json *timelineMap = attachmentMap->_child; timelineMap; timelineMap = timelineMap->_next) { + keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + int frames = timelineMap->_size; + String timelineName = timelineMap->_name; + if (timelineName == "deform") { + VertexAttachment *vertexAttachment = static_cast(attachment); + bool weighted = vertexAttachment->_bones.size() != 0; + Vector &verts = vertexAttachment->_vertices; + int deformLength = weighted ? (int) verts.size() / 3 * 2 : (int) verts.size(); + + DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frames, + frames, slotIndex, vertexAttachment); + float time = Json::getFloat(keyMap, "time", 0); + for (frame = 0, bezier = 0;; frame++) { + Json *vertices = Json::getItem(keyMap, "vertices"); + Vector deformed; + if (!vertices) { + if (weighted) { + deformed.setSize(deformLength, 0); + } else { + deformed.clearAndAddAll(vertexAttachment->_vertices); + } + } else { + deformed.setSize(deformLength, 0); + int v, start = Json::getInt(keyMap, "offset", 0); + Json *vertex; + if (_scale == 1) { + for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { + deformed[v] = vertex->_valueFloat; + } + } else { + for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { + deformed[v] = vertex->_valueFloat * _scale; + } + } + if (!weighted) { + Vector &verticesAttachment = vertexAttachment->_vertices; + for (v = 0; v < deformLength; ++v) { + deformed[v] += verticesAttachment[v]; + } + } + } + timeline->setFrame(frame, time, deformed); + nextMap = keyMap->_next; + if (!nextMap) { + // timeline.shrink(); // BOZO + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1); + } + time = time2; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (timelineName == "sequence") { + SequenceTimeline *timeline = new SequenceTimeline(frames, slotIndex, attachment); + float lastDelay = 0; + for (frame = 0; keyMap != NULL; keyMap = keyMap->_next, frame++) { + float delay = Json::getFloat(keyMap, "delay", lastDelay); + float time = Json::getFloat(keyMap, "time", 0); + String modeString = Json::getString(keyMap, "mode", "hold"); + int index = Json::getInt(keyMap, "index", 0); + SequenceMode mode = SequenceMode::hold; + if (modeString == "once") mode = SequenceMode::once; + if (modeString == "loop") mode = SequenceMode::loop; + if (modeString == "pingpong") mode = SequenceMode::pingpong; + if (modeString == "onceReverse") mode = SequenceMode::onceReverse; + if (modeString == "loopReverse") mode = SequenceMode::loopReverse; + if (modeString == "pingpongReverse") mode = SequenceMode::pingpongReverse; + timeline->setFrame(frame, time, mode, index, delay); + lastDelay = delay; + } + timelines.add(timeline); + } + } + } + } + } + + /** Draw order timeline. */ + if (drawOrder) { + DrawOrderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderTimeline(drawOrder->_size); + + for (keyMap = drawOrder->_child, frame = 0; keyMap; keyMap = keyMap->_next, ++frame) { + int ii; + Vector drawOrder2; + Json *offsets = Json::getItem(keyMap, "offsets"); + if (offsets) { + Json *offsetMap; + Vector unchanged; + unchanged.ensureCapacity(skeletonData->_slots.size() - offsets->_size); + unchanged.setSize(skeletonData->_slots.size() - offsets->_size, 0); + size_t originalIndex = 0, unchangedIndex = 0; + + drawOrder2.ensureCapacity(skeletonData->_slots.size()); + drawOrder2.setSize(skeletonData->_slots.size(), 0); + for (ii = (int) skeletonData->_slots.size() - 1; ii >= 0; --ii) + drawOrder2[ii] = -1; + + for (offsetMap = offsets->_child; offsetMap; offsetMap = offsetMap->_next) { + int slotIndex = findSlotIndex(skeletonData, Json::getString(offsetMap, "slot", 0), timelines); + if (slotIndex == -1) return NULL; + + /* Collect unchanged items. */ + while (originalIndex != (size_t) slotIndex) + unchanged[unchangedIndex++] = (int) originalIndex++; + /* Set changed items. */ + drawOrder2[originalIndex + Json::getInt(offsetMap, "offset", 0)] = (int) originalIndex; + originalIndex++; + } + /* Collect remaining unchanged items. */ + while ((int) originalIndex < (int) skeletonData->_slots.size()) + unchanged[unchangedIndex++] = (int) originalIndex++; + /* Fill in unchanged items. */ + for (ii = (int) skeletonData->_slots.size() - 1; ii >= 0; ii--) + if (drawOrder2[ii] == -1) drawOrder2[ii] = unchanged[--unchangedIndex]; + } + timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0), drawOrder2); + } + timelines.add(timeline); + } + + /** Event timeline. */ + if (events) { + EventTimeline *timeline = new (__FILE__, __LINE__) EventTimeline(events->_size); + + for (keyMap = events->_child, frame = 0; keyMap; keyMap = keyMap->_next, ++frame) { + Event *event; + EventData *eventData = skeletonData->findEvent(Json::getString(keyMap, "name", 0)); + if (!eventData) { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Event not found: ", Json::getString(keyMap, "name", 0)); + return NULL; + } + + event = new (__FILE__, __LINE__) Event(Json::getFloat(keyMap, "time", 0), *eventData); + event->_intValue = Json::getInt(keyMap, "int", eventData->_intValue); + event->_floatValue = Json::getFloat(keyMap, "float", eventData->_floatValue); + event->_stringValue = Json::getString(keyMap, "string", eventData->_stringValue.buffer()); + if (!eventData->_audioPath.isEmpty()) { + event->_volume = Json::getFloat(keyMap, "volume", 1); + event->_balance = Json::getFloat(keyMap, "balance", 0); + } + timeline->setFrame(frame, event); + } + timelines.add(timeline); + } + + float duration = 0; + for (size_t i = 0; i < timelines.size(); i++) + duration = MathUtil::max(duration, timelines[i]->getDuration()); + return new (__FILE__, __LINE__) Animation(String(root->_name), timelines, duration); +} + +void SkeletonJson::readVertices(Json *attachmentMap, VertexAttachment *attachment, size_t verticesLength) { + Json *entry; + size_t i, n, nn, entrySize; + Vector vertices; + + attachment->setWorldVerticesLength(verticesLength); + + entry = Json::getItem(attachmentMap, "vertices"); + entrySize = entry->_size; + vertices.ensureCapacity(entrySize); + vertices.setSize(entrySize, 0); + for (entry = entry->_child, i = 0; entry; entry = entry->_next, ++i) + vertices[i] = entry->_valueFloat; + + if (verticesLength == entrySize) { + if (_scale != 1) { + for (i = 0; i < entrySize; ++i) + vertices[i] *= _scale; + } + + attachment->getVertices().clearAndAddAll(vertices); + return; + } + + Vertices bonesAndWeights; + bonesAndWeights._bones.ensureCapacity(verticesLength * 3); + bonesAndWeights._vertices.ensureCapacity(verticesLength * 3 * 3); + + for (i = 0, n = entrySize; i < n;) { + int boneCount = (int) vertices[i++]; + bonesAndWeights._bones.add(boneCount); + for (nn = i + boneCount * 4; i < nn; i += 4) { + bonesAndWeights._bones.add((int) vertices[i]); + bonesAndWeights._vertices.add(vertices[i + 1] * _scale); + bonesAndWeights._vertices.add(vertices[i + 2] * _scale); + bonesAndWeights._vertices.add(vertices[i + 3]); + } + } + + attachment->getVertices().clearAndAddAll(bonesAndWeights._vertices); + attachment->getBones().clearAndAddAll(bonesAndWeights._bones); +} + +void SkeletonJson::setError(Json *root, const String &value1, const String &value2) { + _error = String(value1).append(value2); + delete root; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonRenderer.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonRenderer.cpp new file mode 100644 index 0000000..3617753 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SkeletonRenderer.cpp @@ -0,0 +1,246 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +SkeletonRenderer::SkeletonRenderer() : _allocator(4096), _worldVertices(), _quadIndices(), _clipping(), _renderCommands() { + _quadIndices.add(0); + _quadIndices.add(1); + _quadIndices.add(2); + _quadIndices.add(2); + _quadIndices.add(3); + _quadIndices.add(0); +} + +SkeletonRenderer::~SkeletonRenderer() { +} + +static RenderCommand *createRenderCommand(BlockAllocator &allocator, int numVertices, int32_t numIndices, BlendMode blendMode, void *texture) { + RenderCommand *cmd = allocator.allocate(1); + cmd->positions = allocator.allocate(numVertices << 1); + cmd->uvs = allocator.allocate(numVertices << 1); + cmd->colors = allocator.allocate(numVertices); + cmd->darkColors = allocator.allocate(numVertices); + cmd->numVertices = numVertices; + cmd->indices = allocator.allocate(numIndices); + cmd->numIndices = numIndices; + cmd->blendMode = blendMode; + cmd->texture = texture; + cmd->next = nullptr; + return cmd; +} + +static RenderCommand *batchSubCommands(BlockAllocator &allocator, Vector &commands, int first, int last, int numVertices, int numIndices) { + RenderCommand *batched = createRenderCommand(allocator, numVertices, numIndices, commands[first]->blendMode, commands[first]->texture); + float *positions = batched->positions; + float *uvs = batched->uvs; + uint32_t *colors = batched->colors; + uint32_t *darkColors = batched->darkColors; + uint16_t *indices = batched->indices; + int indicesOffset = 0; + for (int i = first; i <= last; i++) { + RenderCommand *cmd = commands[i]; + memcpy(positions, cmd->positions, sizeof(float) * 2 * cmd->numVertices); + memcpy(uvs, cmd->uvs, sizeof(float) * 2 * cmd->numVertices); + memcpy(colors, cmd->colors, sizeof(int32_t) * cmd->numVertices); + memcpy(darkColors, cmd->darkColors, sizeof(int32_t) * cmd->numVertices); + for (int ii = 0; ii < cmd->numIndices; ii++) + indices[ii] = cmd->indices[ii] + indicesOffset; + indicesOffset += cmd->numVertices; + positions += 2 * cmd->numVertices; + uvs += 2 * cmd->numVertices; + colors += cmd->numVertices; + darkColors += cmd->numVertices; + indices += cmd->numIndices; + } + return batched; +} + +static RenderCommand *batchCommands(BlockAllocator &allocator, Vector &commands) { + if (commands.size() == 0) return nullptr; + + RenderCommand *root = nullptr; + RenderCommand *last = nullptr; + + RenderCommand *first = commands[0]; + int startIndex = 0; + int i = 1; + int numVertices = first->numVertices; + int numIndices = first->numIndices; + while (i <= (int) commands.size()) { + RenderCommand *cmd = i < (int) commands.size() ? commands[i] : nullptr; + + if (cmd && cmd->numVertices == 0 && cmd->numIndices == 0) { + i++; + continue; + } + + if (cmd != nullptr && cmd->texture == first->texture && + cmd->blendMode == first->blendMode && + cmd->colors[0] == first->colors[0] && + cmd->darkColors[0] == first->darkColors[0] && + numIndices + cmd->numIndices < 0xffff) { + numVertices += cmd->numVertices; + numIndices += cmd->numIndices; + } else { + RenderCommand *batched = batchSubCommands(allocator, commands, startIndex, i - 1, numVertices, numIndices); + if (!last) { + root = last = batched; + } else { + last->next = batched; + last = batched; + } + if (i == (int) commands.size()) break; + first = commands[i]; + startIndex = i; + numVertices = first->numVertices; + numIndices = first->numIndices; + } + i++; + } + return root; +} + +RenderCommand *SkeletonRenderer::render(Skeleton &skeleton) { + _allocator.compress(); + _renderCommands.clear(); + + SkeletonClipping &clipper = _clipping; + + for (unsigned i = 0; i < skeleton.getSlots().size(); ++i) { + Slot &slot = *skeleton.getDrawOrder()[i]; + Attachment *attachment = slot.getAttachment(); + if (!attachment) { + clipper.clipEnd(slot); + continue; + } + + // Early out if the slot color is 0 or the bone is not active + if ((slot.getColor().a == 0 || !slot.getBone().isActive()) && !attachment->getRTTI().isExactly(ClippingAttachment::rtti)) { + clipper.clipEnd(slot); + continue; + } + + Vector *worldVertices = &_worldVertices; + Vector *quadIndices = &_quadIndices; + Vector *vertices = worldVertices; + int32_t verticesCount; + Vector *uvs; + Vector *indices; + int32_t indicesCount; + Color *attachmentColor; + void *texture; + + if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) { + RegionAttachment *regionAttachment = (RegionAttachment *) attachment; + attachmentColor = ®ionAttachment->getColor(); + + // Early out if the slot color is 0 + if (attachmentColor->a == 0) { + clipper.clipEnd(slot); + continue; + } + + worldVertices->setSize(8, 0); + regionAttachment->computeWorldVertices(slot, *worldVertices, 0, 2); + verticesCount = 4; + uvs = ®ionAttachment->getUVs(); + indices = quadIndices; + indicesCount = 6; + texture = regionAttachment->getRegion()->rendererObject; + + } else if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) { + MeshAttachment *mesh = (MeshAttachment *) attachment; + attachmentColor = &mesh->getColor(); + + // Early out if the slot color is 0 + if (attachmentColor->a == 0) { + clipper.clipEnd(slot); + continue; + } + + worldVertices->setSize(mesh->getWorldVerticesLength(), 0); + mesh->computeWorldVertices(slot, 0, mesh->getWorldVerticesLength(), worldVertices->buffer(), 0, 2); + verticesCount = (int32_t) (mesh->getWorldVerticesLength() >> 1); + uvs = &mesh->getUVs(); + indices = &mesh->getTriangles(); + indicesCount = (int32_t) indices->size(); + texture = mesh->getRegion()->rendererObject; + + } else if (attachment->getRTTI().isExactly(ClippingAttachment::rtti)) { + ClippingAttachment *clip = (ClippingAttachment *) slot.getAttachment(); + clipper.clipStart(slot, clip); + continue; + } else + continue; + + uint8_t r = static_cast(skeleton.getColor().r * slot.getColor().r * attachmentColor->r * 255); + uint8_t g = static_cast(skeleton.getColor().g * slot.getColor().g * attachmentColor->g * 255); + uint8_t b = static_cast(skeleton.getColor().b * slot.getColor().b * attachmentColor->b * 255); + uint8_t a = static_cast(skeleton.getColor().a * slot.getColor().a * attachmentColor->a * 255); + uint32_t color = (a << 24) | (r << 16) | (g << 8) | b; + uint32_t darkColor = 0xff000000; + if (slot.hasDarkColor()) { + Color &slotDarkColor = slot.getDarkColor(); + darkColor = 0xff000000 | (static_cast(slotDarkColor.r * 255) << 16) | (static_cast(slotDarkColor.g * 255) << 8) | static_cast(slotDarkColor.b * 255); + } + + if (clipper.isClipping()) { + clipper.clipTriangles(*worldVertices, *indices, *uvs, 2); + vertices = &clipper.getClippedVertices(); + verticesCount = (int32_t) (clipper.getClippedVertices().size() >> 1); + uvs = &clipper.getClippedUVs(); + indices = &clipper.getClippedTriangles(); + indicesCount = (int32_t) (clipper.getClippedTriangles().size()); + } + + RenderCommand *cmd = createRenderCommand(_allocator, verticesCount, indicesCount, slot.getData().getBlendMode(), texture); + _renderCommands.add(cmd); + memcpy(cmd->positions, vertices->buffer(), (verticesCount << 1) * sizeof(float)); + memcpy(cmd->uvs, uvs->buffer(), (verticesCount << 1) * sizeof(float)); + for (int ii = 0; ii < verticesCount; ii++) { + cmd->colors[ii] = color; + cmd->darkColors[ii] = darkColor; + } + memcpy(cmd->indices, indices->buffer(), indices->size() * sizeof(uint16_t)); + clipper.clipEnd(slot); + } + clipper.clipEnd(); + + return batchCommands(_allocator, _renderCommands); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Skin.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Skin.cpp new file mode 100644 index 0000000..582b26a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -0,0 +1,195 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include + +using namespace spine; + +Skin::AttachmentMap::AttachmentMap() { +} + +static void disposeAttachment(Attachment *attachment) { + if (!attachment) return; + attachment->dereference(); + if (attachment->getRefCount() == 0) delete attachment; +} + +void Skin::AttachmentMap::put(size_t slotIndex, const String &attachmentName, Attachment *attachment) { + if (slotIndex >= _buckets.size()) + _buckets.setSize(slotIndex + 1, Vector()); + Vector &bucket = _buckets[slotIndex]; + int existing = findInBucket(bucket, attachmentName); + attachment->reference(); + if (existing >= 0) { + disposeAttachment(bucket[existing]._attachment); + bucket[existing]._attachment = attachment; + } else { + bucket.add(Entry(slotIndex, attachmentName, attachment)); + } +} + +Attachment *Skin::AttachmentMap::get(size_t slotIndex, const String &attachmentName) { + if (slotIndex >= _buckets.size()) return NULL; + int existing = findInBucket(_buckets[slotIndex], attachmentName); + return existing >= 0 ? _buckets[slotIndex][existing]._attachment : NULL; +} + +void Skin::AttachmentMap::remove(size_t slotIndex, const String &attachmentName) { + if (slotIndex >= _buckets.size()) return; + int existing = findInBucket(_buckets[slotIndex], attachmentName); + if (existing >= 0) { + disposeAttachment(_buckets[slotIndex][existing]._attachment); + _buckets[slotIndex].removeAt(existing); + } +} + +int Skin::AttachmentMap::findInBucket(Vector &bucket, const String &attachmentName) { + for (size_t i = 0; i < bucket.size(); i++) + if (bucket[i]._name == attachmentName) return (int) i; + return -1; +} + +Skin::AttachmentMap::Entries Skin::AttachmentMap::getEntries() { + return Skin::AttachmentMap::Entries(_buckets); +} + +Skin::Skin(const String &name) : _name(name), _attachments(), _color(0.99607843f, 0.61960787f, 0.30980393f, 1) { + assert(_name.length() > 0); +} + +Skin::~Skin() { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry entry = entries.next(); + disposeAttachment(entry._attachment); + } +} + +void Skin::setAttachment(size_t slotIndex, const String &name, Attachment *attachment) { + assert(attachment); + _attachments.put(slotIndex, name, attachment); +} + +Attachment *Skin::getAttachment(size_t slotIndex, const String &name) { + return _attachments.get(slotIndex, name); +} + +void Skin::removeAttachment(size_t slotIndex, const String &name) { + _attachments.remove(slotIndex, name); +} + +void Skin::findNamesForSlot(size_t slotIndex, Vector &names) { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == slotIndex) { + names.add(entry._name); + } + } +} + +void Skin::findAttachmentsForSlot(size_t slotIndex, Vector &attachments) { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == slotIndex) attachments.add(entry._attachment); + } +} + +const String &Skin::getName() { + return _name; +} + +Skin::AttachmentMap::Entries Skin::getAttachments() { + return _attachments.getEntries(); +} + +void Skin::attachAll(Skeleton &skeleton, Skin &oldSkin) { + Vector &slots = skeleton.getSlots(); + Skin::AttachmentMap::Entries entries = oldSkin.getAttachments(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + int slotIndex = (int) entry._slotIndex; + Slot *slot = slots[slotIndex]; + + if (slot->getAttachment() == entry._attachment) { + Attachment *attachment = getAttachment(slotIndex, entry._name); + if (attachment) slot->setAttachment(attachment); + } + } +} + +void Skin::addSkin(Skin *other) { + for (size_t i = 0; i < other->getBones().size(); i++) + if (!_bones.contains(other->getBones()[i])) _bones.add(other->getBones()[i]); + + for (size_t i = 0; i < other->getConstraints().size(); i++) + if (!_constraints.contains(other->getConstraints()[i])) _constraints.add(other->getConstraints()[i]); + + AttachmentMap::Entries entries = other->getAttachments(); + while (entries.hasNext()) { + AttachmentMap::Entry &entry = entries.next(); + setAttachment(entry._slotIndex, entry._name, entry._attachment); + } +} + +void Skin::copySkin(Skin *other) { + for (size_t i = 0; i < other->getBones().size(); i++) + if (!_bones.contains(other->getBones()[i])) _bones.add(other->getBones()[i]); + + for (size_t i = 0; i < other->getConstraints().size(); i++) + if (!_constraints.contains(other->getConstraints()[i])) _constraints.add(other->getConstraints()[i]); + + AttachmentMap::Entries entries = other->getAttachments(); + while (entries.hasNext()) { + AttachmentMap::Entry &entry = entries.next(); + if (entry._attachment->getRTTI().isExactly(MeshAttachment::rtti)) + setAttachment(entry._slotIndex, entry._name, + static_cast(entry._attachment)->newLinkedMesh()); + else + setAttachment(entry._slotIndex, entry._name, entry._attachment->copy()); + } +} + +Vector &Skin::getConstraints() { + return _constraints; +} + +Vector &Skin::getBones() { + return _bones; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Slot.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Slot.cpp new file mode 100644 index 0000000..a0079f0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -0,0 +1,129 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +Slot::Slot(SlotData &data, Bone &bone) : _data(data), + _bone(bone), + _skeleton(bone.getSkeleton()), + _color(1, 1, 1, 1), + _darkColor(0, 0, 0, 0), + _hasDarkColor(data.hasDarkColor()), + _attachment(NULL), + _attachmentState(0), + _sequenceIndex(0) { + setToSetupPose(); +} + +void Slot::setToSetupPose() { + _color.set(_data.getColor()); + if (_hasDarkColor) _darkColor.set(_data.getDarkColor()); + + const String &attachmentName = _data.getAttachmentName(); + if (attachmentName.length() > 0) { + _attachment = NULL; + setAttachment(_skeleton.getAttachment(_data.getIndex(), attachmentName)); + } else { + setAttachment(NULL); + } +} + +SlotData &Slot::getData() { + return _data; +} + +Bone &Slot::getBone() { + return _bone; +} + +Skeleton &Slot::getSkeleton() { + return _skeleton; +} + +Color &Slot::getColor() { + return _color; +} + +Color &Slot::getDarkColor() { + return _darkColor; +} + +bool Slot::hasDarkColor() { + return _hasDarkColor; +} + +Attachment *Slot::getAttachment() { + return _attachment; +} + +void Slot::setAttachment(Attachment *inValue) { + if (_attachment == inValue) { + return; + } + + if (!inValue || + !_attachment || + !inValue->getRTTI().instanceOf(VertexAttachment::rtti) || + !_attachment->getRTTI().instanceOf(VertexAttachment::rtti) || + static_cast(inValue)->getTimelineAttachment() != + static_cast(_attachment)->getTimelineAttachment()) { + _deform.clear(); + } + + _attachment = inValue; + _sequenceIndex = -1; +} + +int Slot::getAttachmentState() { + return _attachmentState; +} + +void Slot::setAttachmentState(int state) { + _attachmentState = state; +} + +Vector &Slot::getDeform() { + return _deform; +} + +int Slot::getSequenceIndex() { + return _sequenceIndex; +} + +void Slot::setSequenceIndex(int index) { + _sequenceIndex = index; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SlotData.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SlotData.cpp new file mode 100644 index 0000000..bc9694a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SlotData.cpp @@ -0,0 +1,99 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +SlotData::SlotData(int index, const String &name, BoneData &boneData) : _index(index), + _name(name), + _boneData(boneData), + _color(1, 1, 1, 1), + _darkColor(0, 0, 0, 0), + _hasDarkColor(false), + _attachmentName(), + _blendMode(BlendMode_Normal), + _visible(true) { + assert(_index >= 0); + assert(_name.length() > 0); +} + +int SlotData::getIndex() { + return _index; +} + +const String &SlotData::getName() { + return _name; +} + +BoneData &SlotData::getBoneData() { + return _boneData; +} + +Color &SlotData::getColor() { + return _color; +} + +Color &SlotData::getDarkColor() { + return _darkColor; +} + +bool SlotData::hasDarkColor() { + return _hasDarkColor; +} + +void SlotData::setHasDarkColor(bool inValue) { + _hasDarkColor = inValue; +} + +const String &SlotData::getAttachmentName() { + return _attachmentName; +} + +void SlotData::setAttachmentName(const String &inValue) { + _attachmentName = inValue; +} + +BlendMode SlotData::getBlendMode() { + return _blendMode; +} + +void SlotData::setBlendMode(BlendMode inValue) { + _blendMode = inValue; +} + +bool SlotData::isVisible() { + return _visible; +} + +void SlotData::setVisible(bool inValue) { + this->_visible = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SpineObject.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SpineObject.cpp new file mode 100644 index 0000000..d71bf6e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/SpineObject.cpp @@ -0,0 +1,63 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +using namespace spine; + +void *SpineObject::operator new(size_t sz) { + return SpineExtension::getInstance()->_calloc(sz, __FILE__, __LINE__); +} + +void *SpineObject::operator new(size_t sz, const char *file, int line) { + return SpineExtension::getInstance()->_calloc(sz, file, line); +} + +void *SpineObject::operator new(size_t sz, void *ptr) { + SP_UNUSED(sz); + return ptr; +} + +void SpineObject::operator delete(void *p, const char *file, int line) { + SpineExtension::free(p, file, line); +} + +void SpineObject::operator delete(void *p, void *mem) { + SP_UNUSED(mem); + SpineExtension::free(p, __FILE__, __LINE__); +} + +void SpineObject::operator delete(void *p) { + SpineExtension::free(p, __FILE__, __LINE__); +} + +SpineObject::~SpineObject() { + SpineExtension::beforeFree(this); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp new file mode 100644 index 0000000..4dd2a5f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp @@ -0,0 +1,38 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +namespace spine { + TextureLoader::TextureLoader() { + } + + TextureLoader::~TextureLoader() { + } +}// namespace spine diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Timeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Timeline.cpp new file mode 100644 index 0000000..b8624c0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Timeline.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +namespace spine { + RTTI_IMPL_NOPARENT(Timeline) + + Timeline::Timeline(size_t frameCount, size_t frameEntries) + : _propertyIds(), _frames(), _frameEntries(frameEntries) { + _frames.setSize(frameCount * frameEntries, 0); + } + + Timeline::~Timeline() { + } + + Vector &Timeline::getPropertyIds() { + return _propertyIds; + } + + void Timeline::setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount) { + _propertyIds.clear(); + _propertyIds.ensureCapacity(propertyIdsCount); + for (size_t i = 0; i < propertyIdsCount; i++) { + _propertyIds.add(propertyIds[i]); + } + } + + size_t Timeline::getFrameCount() { + return _frames.size() / _frameEntries; + } + + Vector &Timeline::getFrames() { + return _frames; + } + + size_t Timeline::getFrameEntries() { + return _frameEntries; + } + + float Timeline::getDuration() { + return _frames[_frames.size() - getFrameEntries()]; + } +}// namespace spine diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp new file mode 100644 index 0000000..49ee366 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -0,0 +1,350 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(TransformConstraint, Updatable) + +TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : Updatable(), + _data(data), + _target(skeleton.findBone( + data.getTarget()->getName())), + _mixRotate( + data.getMixRotate()), + _mixX(data.getMixX()), + _mixY(data.getMixY()), + _mixScaleX( + data.getMixScaleX()), + _mixScaleY( + data.getMixScaleY()), + _mixShearY( + data.getMixShearY()), + _active(false) { + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); ++i) { + BoneData *boneData = _data.getBones()[i]; + _bones.add(skeleton.findBone(boneData->getName())); + } +} + +void TransformConstraint::update(Physics) { + if (_mixRotate == 0 && _mixX == 0 && _mixY == 0 && _mixScaleX == 0 && _mixScaleY == 0 && _mixShearY == 0) return; + + if (_data.isLocal()) { + if (_data.isRelative()) + applyRelativeLocal(); + else + applyAbsoluteLocal(); + } else { + if (_data.isRelative()) + applyRelativeWorld(); + else + applyAbsoluteWorld(); + } +} + +int TransformConstraint::getOrder() { + return (int) _data.getOrder(); +} + +TransformConstraintData &TransformConstraint::getData() { + return _data; +} + +Vector &TransformConstraint::getBones() { + return _bones; +} + +Bone *TransformConstraint::getTarget() { + return _target; +} + +void TransformConstraint::setTarget(Bone *inValue) { + _target = inValue; +} + +float TransformConstraint::getMixRotate() { + return _mixRotate; +} + +void TransformConstraint::setMixRotate(float inValue) { + _mixRotate = inValue; +} + +float TransformConstraint::getMixX() { + return _mixX; +} + +void TransformConstraint::setMixX(float inValue) { + _mixX = inValue; +} + +float TransformConstraint::getMixY() { + return _mixY; +} + +void TransformConstraint::setMixY(float inValue) { + _mixY = inValue; +} + +void TransformConstraint::setMixScaleX(float inValue) { + _mixScaleX = inValue; +} + +float TransformConstraint::getMixScaleX() { + return _mixScaleX; +} + +float TransformConstraint::getMixScaleY() { + return _mixScaleY; +} + +void TransformConstraint::setMixScaleY(float inValue) { + _mixScaleY = inValue; +} + +float TransformConstraint::getMixShearY() { + return _mixShearY; +} + +void TransformConstraint::setMixShearY(float inValue) { + _mixShearY = inValue; +} + +void TransformConstraint::applyAbsoluteWorld() { + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; + bool translate = mixX != 0 || mixY != 0; + Bone &target = *_target; + float ta = target._a, tb = target._b, tc = target._c, td = target._d; + float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; + float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; + + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + if (mixRotate != 0) { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + float r = MathUtil::atan2(tc, ta) - MathUtil::atan2(c, a) + offsetRotation; + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r *= mixRotate; + float cos = MathUtil::cos(r), sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + } + + if (translate) { + float tx, ty; + target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); + bone._worldX += (tx - bone._worldX) * mixX; + bone._worldY += (ty - bone._worldY) * mixY; + } + + if (mixScaleX != 0) { + float s = MathUtil::sqrt(bone._a * bone._a + bone._c * bone._c); + if (s != 0) s = (s + (MathUtil::sqrt(ta * ta + tc * tc) - s + _data._offsetScaleX) * mixScaleX) / s; + bone._a *= s; + bone._c *= s; + } + + if (mixScaleY != 0) { + float s = MathUtil::sqrt(bone._b * bone._b + bone._d * bone._d); + if (s != 0) s = (s + (MathUtil::sqrt(tb * tb + td * td) - s + _data._offsetScaleY) * mixScaleY) / s; + bone._b *= s; + bone._d *= s; + } + + if (mixShearY > 0) { + float b = bone._b, d = bone._d; + float by = MathUtil::atan2(d, b); + float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta) - (by - MathUtil::atan2(bone._c, bone._a)); + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r = by + (r + offsetShearY) * mixShearY; + float s = MathUtil::sqrt(b * b + d * d); + bone._b = MathUtil::cos(r) * s; + bone._d = MathUtil::sin(r) * s; + } + + bone.updateAppliedTransform(); + } +} + +void TransformConstraint::applyRelativeWorld() { + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; + bool translate = mixX != 0 || mixY != 0; + Bone &target = *_target; + float ta = target._a, tb = target._b, tc = target._c, td = target._d; + float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; + float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + if (mixRotate != 0) { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + float r = MathUtil::atan2(tc, ta) + offsetRotation; + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + r *= mixRotate; + float cos = MathUtil::cos(r), sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + } + + if (translate) { + float tx, ty; + target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); + bone._worldX += tx * mixX; + bone._worldY += ty * mixY; + } + + if (mixScaleX != 0) { + float s = (MathUtil::sqrt(ta * ta + tc * tc) - 1 + _data._offsetScaleX) * mixScaleX + 1; + bone._a *= s; + bone._c *= s; + } + if (mixScaleY != 0) { + float s = (MathUtil::sqrt(tb * tb + td * td) - 1 + _data._offsetScaleY) * mixScaleY + 1; + bone._b *= s; + bone._d *= s; + } + + if (mixShearY > 0) { + float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta); + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + + float b = bone._b, d = bone._d; + r = MathUtil::atan2(d, b) + (r - MathUtil::Pi / 2 + offsetShearY) * mixShearY; + float s = MathUtil::sqrt(b * b + d * d); + bone._b = MathUtil::cos(r) * s; + bone._d = MathUtil::sin(r) * s; + } + + bone.updateAppliedTransform(); + } +} + +void TransformConstraint::applyAbsoluteLocal() { + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; + Bone &target = *_target; + + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + float rotation = bone._arotation; + if (mixRotate != 0) { + float r = target._arotation - rotation + _data._offsetRotation; + r -= MathUtil::ceil(r / 360 - 0.5) * 360; + rotation += r * mixRotate; + } + + float x = bone._ax, y = bone._ay; + x += (target._ax - x + _data._offsetX) * mixX; + y += (target._ay - y + _data._offsetY) * mixY; + + float scaleX = bone._ascaleX, scaleY = bone._ascaleY; + if (mixScaleX != 0 && scaleX != 0) + scaleX = (scaleX + (target._ascaleX - scaleX + _data._offsetScaleX) * mixScaleX) / scaleX; + if (mixScaleY != 0 && scaleY != 0) + scaleY = (scaleY + (target._ascaleY - scaleY + _data._offsetScaleY) * mixScaleY) / scaleY; + + float shearY = bone._ashearY; + if (mixShearY != 0) { + float r = target._ashearY - shearY + _data._offsetShearY; + r -= MathUtil::ceil(r / 360 - 0.5) * 360; + bone._shearY += r * mixShearY; + } + + bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); + } +} + +void TransformConstraint::applyRelativeLocal() { + float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; + Bone &target = *_target; + + for (size_t i = 0; i < _bones.size(); ++i) { + Bone *item = _bones[i]; + Bone &bone = *item; + + float rotation = bone._arotation + (target._arotation + _data._offsetRotation) * mixRotate; + float x = bone._ax + (target._ax + _data._offsetX) * mixX; + float y = bone._ay + (target._ay + _data._offsetY) * mixY; + float scaleX = bone._ascaleX * (((target._ascaleX - 1 + _data._offsetScaleX) * mixScaleX) + 1); + float scaleY = bone._ascaleY * (((target._ascaleY - 1 + _data._offsetScaleY) * mixScaleY) + 1); + float shearY = bone._ashearY + (target._ashearY + _data._offsetShearY) * mixShearY; + + bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); + } +} + +bool TransformConstraint::isActive() { + return _active; +} + +void TransformConstraint::setActive(bool inValue) { + _active = inValue; +} + +void TransformConstraint::setToSetupPose() { + TransformConstraintData &data = this->_data; + this->_mixRotate = data._mixRotate; + this->_mixX = data._mixX; + this->_mixY = data._mixY; + this->_mixScaleX = data._mixScaleX; + this->_mixScaleY = data._mixScaleY; + this->_mixShearY = data._mixShearY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp new file mode 100644 index 0000000..38a674e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -0,0 +1,180 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +#include + +using namespace spine; + +RTTI_IMPL(TransformConstraintData, ConstraintData) + +TransformConstraintData::TransformConstraintData(const String &name) : ConstraintData(name), + _target(NULL), + _mixRotate(0), + _mixX(0), + _mixY(0), + _mixScaleX(0), + _mixScaleY(0), + _mixShearY(0), + _offsetRotation(0), + _offsetX(0), + _offsetY(0), + _offsetScaleX(0), + _offsetScaleY(0), + _offsetShearY(0), + _relative(false), + _local(false) { +} + +Vector &TransformConstraintData::getBones() { + return _bones; +} + +BoneData *TransformConstraintData::getTarget() { + return _target; +} + +float TransformConstraintData::getMixRotate() { + return _mixRotate; +} + +float TransformConstraintData::getMixX() { + return _mixX; +} + +float TransformConstraintData::getMixY() { + return _mixY; +} + +float TransformConstraintData::getMixScaleX() { + return _mixScaleX; +} + +float TransformConstraintData::getMixScaleY() { + return _mixScaleY; +} + +float TransformConstraintData::getMixShearY() { + return _mixShearY; +} + +float TransformConstraintData::getOffsetRotation() { + return _offsetRotation; +} + +float TransformConstraintData::getOffsetX() { + return _offsetX; +} + +float TransformConstraintData::getOffsetY() { + return _offsetY; +} + +float TransformConstraintData::getOffsetScaleX() { + return _offsetScaleX; +} + +float TransformConstraintData::getOffsetScaleY() { + return _offsetScaleY; +} + +float TransformConstraintData::getOffsetShearY() { + return _offsetShearY; +} + +bool TransformConstraintData::isRelative() { + return _relative; +} + +bool TransformConstraintData::isLocal() { + return _local; +} + +void TransformConstraintData::setTarget(BoneData *target) { + _target = target; +} + +void TransformConstraintData::setMixRotate(float mixRotate) { + _mixRotate = mixRotate; +} + +void TransformConstraintData::setMixX(float mixX) { + _mixX = mixX; +} + +void TransformConstraintData::setMixY(float mixY) { + _mixY = mixY; +} + +void TransformConstraintData::setMixScaleX(float mixScaleX) { + _mixScaleX = mixScaleX; +} + +void TransformConstraintData::setMixScaleY(float mixScaleY) { + _mixScaleY = mixScaleY; +} + +void TransformConstraintData::setMixShearY(float mixShearY) { + _mixShearY = mixShearY; +} + +void TransformConstraintData::setOffsetRotation(float offsetRotation) { + _offsetRotation = offsetRotation; +} + +void TransformConstraintData::setOffsetX(float offsetX) { + _offsetX = offsetX; +} + +void TransformConstraintData::setOffsetY(float offsetY) { + _offsetY = offsetY; +} + +void TransformConstraintData::setOffsetScaleX(float offsetScaleX) { + _offsetScaleX = offsetScaleX; +} + +void TransformConstraintData::setOffsetScaleY(float offsetScaleY) { + _offsetScaleY = offsetScaleY; +} + +void TransformConstraintData::setOffsetShearY(float offsetShearY) { + _offsetShearY = offsetShearY; +} + +void TransformConstraintData::setRelative(bool isRelative) { + _relative = isRelative; +} + +void TransformConstraintData::setLocal(bool isLocal) { + _local = isLocal; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp new file mode 100644 index 0000000..6e41e2e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -0,0 +1,157 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(TransformConstraintTimeline, CurveTimeline) + +TransformConstraintTimeline::TransformConstraintTimeline(size_t frameCount, size_t bezierCount, + int transformConstraintIndex) : CurveTimeline(frameCount, + TransformConstraintTimeline::ENTRIES, + bezierCount), + _constraintIndex( + transformConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_TransformConstraint << 32) | transformConstraintIndex}; + setPropertyIds(ids, 1); +} + +void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, + float alpha, MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + TransformConstraint *constraintP = skeleton._transformConstraints[_constraintIndex]; + TransformConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + + TransformConstraintData &data = constraint._data; + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + constraint._mixRotate = data._mixRotate; + constraint._mixX = data._mixX; + constraint._mixY = data._mixY; + constraint._mixScaleX = data._mixScaleX; + constraint._mixScaleY = data._mixScaleY; + constraint._mixShearY = data._mixShearY; + return; + case MixBlend_First: + constraint._mixRotate += (data._mixRotate - constraint._mixRotate) * alpha; + constraint._mixX += (data._mixX - constraint._mixX) * alpha; + constraint._mixY += (data._mixY - constraint._mixY) * alpha; + constraint._mixScaleX += (data._mixScaleX - constraint._mixScaleX) * alpha; + constraint._mixScaleY += (data._mixScaleY - constraint._mixScaleY) * alpha; + constraint._mixShearY += (data._mixShearY - constraint._mixShearY) * alpha; + return; + default: + return; + } + } + + float rotate, x, y, scaleX, scaleY, shearY; + int i = Animation::search(_frames, time, TransformConstraintTimeline::ENTRIES); + int curveType = (int) _curves[i / TransformConstraintTimeline::ENTRIES]; + switch (curveType) { + case TransformConstraintTimeline::LINEAR: { + float before = _frames[i]; + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + scaleX = _frames[i + SCALEX]; + scaleY = _frames[i + SCALEY]; + shearY = _frames[i + SHEARY]; + float t = (time - before) / (_frames[i + ENTRIES] - before); + rotate += (_frames[i + ENTRIES + ROTATE] - rotate) * t; + x += (_frames[i + ENTRIES + X] - x) * t; + y += (_frames[i + ENTRIES + Y] - y) * t; + scaleX += (_frames[i + ENTRIES + SCALEX] - scaleX) * t; + scaleY += (_frames[i + ENTRIES + SCALEY] - scaleY) * t; + shearY += (_frames[i + ENTRIES + SHEARY] - shearY) * t; + break; + } + case TransformConstraintTimeline::STEPPED: { + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + scaleX = _frames[i + SCALEX]; + scaleY = _frames[i + SCALEY]; + shearY = _frames[i + SHEARY]; + break; + } + default: { + rotate = getBezierValue(time, i, ROTATE, curveType - BEZIER); + x = getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER); + y = getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER); + scaleX = getBezierValue(time, i, SCALEX, curveType + BEZIER_SIZE * 3 - BEZIER); + scaleY = getBezierValue(time, i, SCALEY, curveType + BEZIER_SIZE * 4 - BEZIER); + shearY = getBezierValue(time, i, SHEARY, curveType + BEZIER_SIZE * 5 - BEZIER); + } + } + + if (blend == MixBlend_Setup) { + constraint._mixRotate = data._mixRotate + (rotate - data._mixRotate) * alpha; + constraint._mixX = data._mixX + (x - data._mixX) * alpha; + constraint._mixY = data._mixY + (y - data._mixY) * alpha; + constraint._mixScaleX = data._mixScaleX + (scaleX - data._mixScaleX) * alpha; + constraint._mixScaleY = data._mixScaleY + (scaleY - data._mixScaleY) * alpha; + constraint._mixShearY = data._mixShearY + (shearY - data._mixShearY) * alpha; + } else { + constraint._mixRotate += (rotate - constraint._mixRotate) * alpha; + constraint._mixX += (x - constraint._mixX) * alpha; + constraint._mixY += (y - constraint._mixY) * alpha; + constraint._mixScaleX += (scaleX - constraint._mixScaleX) * alpha; + constraint._mixScaleY += (scaleY - constraint._mixScaleY) * alpha; + constraint._mixShearY += (shearY - constraint._mixShearY) * alpha; + } +} + +void TransformConstraintTimeline::setFrame(size_t frame, float time, float mixRotate, float mixX, float mixY, + float mixScaleX, float mixScaleY, float mixShearY) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + ROTATE] = mixRotate; + _frames[frame + X] = mixX; + _frames[frame + Y] = mixY; + _frames[frame + SCALEX] = mixScaleX; + _frames[frame + SCALEY] = mixScaleY; + _frames[frame + SHEARY] = mixShearY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp new file mode 100644 index 0000000..1299795 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -0,0 +1,162 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(TranslateTimeline, CurveTimeline2) + +TranslateTimeline::TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, + bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_X << 32) | boneIndex, + ((PropertyId) Property_Y << 32) | boneIndex}; + setPropertyIds(ids, 2); +} + +TranslateTimeline::~TranslateTimeline() { +} + +void TranslateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->_active) return; + + if (time < _frames[0]) { + switch (blend) { + case MixBlend_Setup: + bone->_x = bone->_data._x; + bone->_y = bone->_data._y; + return; + case MixBlend_First: + bone->_x += (bone->_data._x - bone->_x) * alpha; + bone->_y += (bone->_data._y - bone->_y) * alpha; + default: { + } + } + return; + } + + float x = 0, y = 0; + int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES); + int curveType = (int) _curves[i / CurveTimeline2::ENTRIES]; + switch (curveType) { + case CurveTimeline::LINEAR: { + float before = _frames[i]; + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before); + x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t; + y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t; + break; + } + case CurveTimeline::STEPPED: { + x = _frames[i + CurveTimeline2::VALUE1]; + y = _frames[i + CurveTimeline2::VALUE2]; + break; + } + default: { + x = getBezierValue(time, i, CurveTimeline2::VALUE1, curveType - CurveTimeline::BEZIER); + y = getBezierValue(time, i, CurveTimeline2::VALUE2, + curveType + CurveTimeline::BEZIER_SIZE - CurveTimeline::BEZIER); + } + } + + switch (blend) { + case MixBlend_Setup: + bone->_x = bone->_data._x + x * alpha; + bone->_y = bone->_data._y + y * alpha; + break; + case MixBlend_First: + case MixBlend_Replace: + bone->_x += (bone->_data._x + x - bone->_x) * alpha; + bone->_y += (bone->_data._y + y - bone->_y) * alpha; + break; + case MixBlend_Add: + bone->_x += x * alpha; + bone->_y += y * alpha; + } +} + +RTTI_IMPL(TranslateXTimeline, CurveTimeline1) + +TranslateXTimeline::TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1( + frameCount, bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_X << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +TranslateXTimeline::~TranslateXTimeline() { +} + +void TranslateXTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (bone->_active) bone->_x = getRelativeValue(time, alpha, blend, bone->_x, bone->_data._x); +} + +RTTI_IMPL(TranslateYTimeline, CurveTimeline1) + +TranslateYTimeline::TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1( + frameCount, bezierCount), + _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_Y << 32) | boneIndex}; + setPropertyIds(ids, 1); +} + +TranslateYTimeline::~TranslateYTimeline() { +} + +void TranslateYTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction) { + SP_UNUSED(lastTime); + SP_UNUSED(pEvents); + SP_UNUSED(direction); + + Bone *bone = skeleton._bones[_boneIndex]; + if (bone->_active) bone->_y = getRelativeValue(time, alpha, blend, bone->_y, bone->_data._y); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Triangulator.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Triangulator.cpp new file mode 100644 index 0000000..336c6f5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Triangulator.cpp @@ -0,0 +1,285 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +Triangulator::~Triangulator() { + ContainerUtil::cleanUpVectorOfPointers(_convexPolygons); + ContainerUtil::cleanUpVectorOfPointers(_convexPolygonsIndices); +} + +Vector &Triangulator::triangulate(Vector &vertices) { + size_t vertexCount = vertices.size() >> 1; + + Vector &indices = _indices; + indices.clear(); + indices.ensureCapacity(vertexCount); + indices.setSize(vertexCount, 0); + for (int i = 0; i < (int) vertexCount; ++i) { + indices[i] = i; + } + + Vector &isConcaveArray = _isConcaveArray; + isConcaveArray.ensureCapacity(vertexCount); + isConcaveArray.setSize(vertexCount, 0); + for (int i = 0, n = (int) vertexCount; i < n; ++i) { + isConcaveArray[i] = isConcave(i, (int) vertexCount, vertices, indices); + } + + Vector &triangles = _triangles; + triangles.clear(); + triangles.ensureCapacity(MathUtil::max((int) 0, (int) vertexCount - 2) << 2); + + while (vertexCount > 3) { + // Find ear tip. + size_t previous = vertexCount - 1, i = 0, next = 1; + + // outer: + while (true) { + if (!isConcaveArray[i]) { + int p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + float p1x = vertices[p1], p1y = vertices[p1 + 1]; + float p2x = vertices[p2], p2y = vertices[p2 + 1]; + float p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (size_t ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcaveArray[ii]) continue; + + int v = indices[ii] << 1; + float &vx = vertices[v], vy = vertices[v + 1]; + if (positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (positiveArea(p2x, p2y, p3x, p3y, vx, vy)) { + goto break_outer;// break outer; + } + } + } + } + break; + } + break_outer: + + if (next == 0) { + do { + if (!isConcaveArray[i]) break; + i--; + } while (i > 0); + break; + } + + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + + // Cut ear tip. + triangles.add(indices[(vertexCount + i - 1) % vertexCount]); + triangles.add(indices[i]); + triangles.add(indices[(i + 1) % vertexCount]); + indices.removeAt(i); + isConcaveArray.removeAt(i); + vertexCount--; + + int previousIndex = (int) ((vertexCount + i - 1) % vertexCount); + int nextIndex = (int) (i == vertexCount ? 0 : i); + isConcaveArray[previousIndex] = isConcave(previousIndex, (int) vertexCount, vertices, indices); + isConcaveArray[nextIndex] = isConcave(nextIndex, (int) vertexCount, vertices, indices); + } + + if (vertexCount == 3) { + triangles.add(indices[2]); + triangles.add(indices[0]); + triangles.add(indices[1]); + } + + return triangles; +} + +Vector *> &Triangulator::decompose(Vector &vertices, Vector &triangles) { + Vector *> &convexPolygons = _convexPolygons; + for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) + _polygonPool.free(convexPolygons[i]); + convexPolygons.clear(); + + Vector *> &convexPolygonsIndices = _convexPolygonsIndices; + for (size_t i = 0, n = convexPolygonsIndices.size(); i < n; ++i) + _polygonIndicesPool.free(convexPolygonsIndices[i]); + convexPolygonsIndices.clear(); + + Vector *polygonIndices = _polygonIndicesPool.obtain(); + polygonIndices->clear(); + + Vector *polygon = _polygonPool.obtain(); + polygon->clear(); + + // Merge subsequent triangles if they form a triangle fan. + int fanBaseIndex = -1, lastwinding = 0; + for (size_t i = 0, n = triangles.size(); i < n; i += 3) { + int t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + float x1 = vertices[t1], y1 = vertices[t1 + 1]; + float x2 = vertices[t2], y2 = vertices[t2 + 1]; + float x3 = vertices[t3], y3 = vertices[t3 + 1]; + + // If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan). + bool merged = false; + if (fanBaseIndex == t1) { + size_t o = polygon->size() - 4; + Vector &p = *polygon; + int winding1 = winding(p[o], p[o + 1], p[o + 2], p[o + 3], x3, y3); + int winding2 = winding(x3, y3, p[0], p[1], p[2], p[3]); + if (winding1 == lastwinding && winding2 == lastwinding) { + polygon->add(x3); + polygon->add(y3); + polygonIndices->add(t3); + merged = true; + } + } + + // Otherwise make this triangle the new base. + if (!merged) { + if (polygon->size() > 0) { + convexPolygons.add(polygon); + convexPolygonsIndices.add(polygonIndices); + } else { + _polygonPool.free(polygon); + _polygonIndicesPool.free(polygonIndices); + } + + polygon = _polygonPool.obtain(); + polygon->clear(); + polygon->add(x1); + polygon->add(y1); + polygon->add(x2); + polygon->add(y2); + polygon->add(x3); + polygon->add(y3); + polygonIndices = _polygonIndicesPool.obtain(); + polygonIndices->clear(); + polygonIndices->add(t1); + polygonIndices->add(t2); + polygonIndices->add(t3); + lastwinding = winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + + if (polygon->size() > 0) { + convexPolygons.add(polygon); + convexPolygonsIndices.add(polygonIndices); + } + + // Go through the list of polygons and try to merge the remaining triangles with the found triangle fans. + for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) { + polygonIndices = convexPolygonsIndices[i]; + + if (polygonIndices->size() == 0) continue; + int firstIndex = (*polygonIndices)[0]; + int lastIndex = (*polygonIndices)[polygonIndices->size() - 1]; + + polygon = convexPolygons[i]; + size_t o = polygon->size() - 4; + Vector &p = *polygon; + float prevPrevX = p[o], prevPrevY = p[o + 1]; + float prevX = p[o + 2], prevY = p[o + 3]; + float firstX = p[0], firstY = p[1]; + float secondX = p[2], secondY = p[3]; + int winding0 = winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + + for (size_t ii = 0; ii < n; ++ii) { + if (ii == i) continue; + + Vector *otherIndicesP = convexPolygonsIndices[ii]; + Vector &otherIndices = *otherIndicesP; + + if (otherIndices.size() != 3) continue; + + int otherFirstIndex = otherIndices[0]; + int otherSecondIndex = otherIndices[1]; + int otherLastIndex = otherIndices[2]; + + Vector *otherPolyP = convexPolygons[ii]; + Vector &otherPoly = *otherPolyP; + + float x3 = otherPoly[otherPoly.size() - 2], y3 = otherPoly[otherPoly.size() - 1]; + + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue; + + int winding1 = winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + int winding2 = winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding0 && winding2 == winding0) { + otherPoly.clear(); + otherIndices.clear(); + polygon->add(x3); + polygon->add(y3); + polygonIndices->add(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + + // Remove empty polygons that resulted from the merge step above. + for (int i = (int) convexPolygons.size() - 1; i >= 0; --i) { + polygon = convexPolygons[i]; + if (polygon->size() == 0) { + convexPolygons.removeAt(i); + _polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.removeAt(i); + _polygonIndicesPool.free(polygonIndices); + } + } + + return convexPolygons; +} + +bool Triangulator::isConcave(int index, int vertexCount, Vector &vertices, Vector &indices) { + int previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + int current = indices[index] << 1; + int next = indices[(index + 1) % vertexCount] << 1; + + return !positiveArea(vertices[previous], vertices[previous + 1], + vertices[current], vertices[current + 1], + vertices[next], vertices[next + 1]); +} + +bool Triangulator::positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; +} + +int Triangulator::winding(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) { + float px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Updatable.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Updatable.cpp new file mode 100644 index 0000000..8e874a2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/Updatable.cpp @@ -0,0 +1,40 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(Updatable) + +Updatable::Updatable() { +} + +Updatable::~Updatable() { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp new file mode 100644 index 0000000..a84f9a7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.2/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -0,0 +1,167 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL(VertexAttachment, Attachment) + +VertexAttachment::VertexAttachment(const String &name) : Attachment(name), _worldVerticesLength(0), + _timelineAttachment(this), _id(getNextID()) { +} + +VertexAttachment::~VertexAttachment() { +} + +void VertexAttachment::computeWorldVertices(Slot &slot, Vector &worldVertices) { + computeWorldVertices(slot, 0, _worldVerticesLength, worldVertices, 0); +} + +void VertexAttachment::computeWorldVertices(Slot &slot, float *worldVertices) { + computeWorldVertices(slot, 0, _worldVerticesLength, worldVertices, 0); +} + +void VertexAttachment::computeWorldVertices(Slot &slot, size_t start, size_t count, Vector &worldVertices, + size_t offset, size_t stride) { + computeWorldVertices(slot, start, count, worldVertices.buffer(), offset, stride); +} + +void VertexAttachment::computeWorldVertices(Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride) { + count = offset + (count >> 1) * stride; + Skeleton &skeleton = slot._bone._skeleton; + Vector *deformArray = &slot.getDeform(); + Vector *vertices = &_vertices; + Vector &bones = _bones; + if (bones.size() == 0) { + if (deformArray->size() > 0) vertices = deformArray; + + Bone &bone = slot._bone; + float x = bone._worldX; + float y = bone._worldY; + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + for (size_t vv = start, w = offset; w < count; vv += 2, w += stride) { + float vx = (*vertices)[vv]; + float vy = (*vertices)[vv + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + + int v = 0, skip = 0; + for (size_t i = 0; i < start; i += 2) { + int n = (int) bones[v]; + v += n + 1; + skip += n; + } + + Vector &skeletonBones = skeleton.getBones(); + if (deformArray->size() == 0) { + for (size_t w = offset, b = skip * 3; w < count; w += stride) { + float wx = 0, wy = 0; + int n = (int) bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + Bone *boneP = skeletonBones[bones[v]]; + Bone &bone = *boneP; + float vx = (*vertices)[b]; + float vy = (*vertices)[b + 1]; + float weight = (*vertices)[b + 2]; + wx += (vx * bone._a + vy * bone._b + bone._worldX) * weight; + wy += (vx * bone._c + vy * bone._d + bone._worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } else { + for (size_t w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + float wx = 0, wy = 0; + int n = (int) bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + Bone *boneP = skeletonBones[bones[v]]; + Bone &bone = *boneP; + float vx = (*vertices)[b] + (*deformArray)[f]; + float vy = (*vertices)[b + 1] + (*deformArray)[f + 1]; + float weight = (*vertices)[b + 2]; + wx += (vx * bone._a + vy * bone._b + bone._worldX) * weight; + wy += (vx * bone._c + vy * bone._d + bone._worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } +} + +int VertexAttachment::getId() { + return _id; +} + +Vector &VertexAttachment::getBones() { + return _bones; +} + +Vector &VertexAttachment::getVertices() { + return _vertices; +} + +size_t VertexAttachment::getWorldVerticesLength() { + return _worldVerticesLength; +} + +void VertexAttachment::setWorldVerticesLength(size_t inValue) { + _worldVerticesLength = inValue; +} + +Attachment *VertexAttachment::getTimelineAttachment() { + return _timelineAttachment; +} + +void VertexAttachment::setTimelineAttachment(Attachment *attachment) { + _timelineAttachment = attachment; +} + +int VertexAttachment::getNextID() { + static int nextID = 0; + return nextID++; +} + +void VertexAttachment::copyTo(VertexAttachment *other) { + other->_bones.clearAndAddAll(this->_bones); + other->_vertices.clearAndAddAll(this->_vertices); + other->_worldVerticesLength = this->_worldVerticesLength; + other->_timelineAttachment = this->_timelineAttachment; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3 b/DateToSpine/third_party/spine-runtimes/4.3 deleted file mode 160000 index 4309c05..0000000 --- a/DateToSpine/third_party/spine-runtimes/4.3 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4309c05c287d3f15da778e68f5d2a483fe10a6a3 diff --git a/DateToSpine/third_party/spine-runtimes/4.3/CHANGELOG.md b/DateToSpine/third_party/spine-runtimes/4.3/CHANGELOG.md new file mode 100644 index 0000000..7b962c8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/CHANGELOG.md @@ -0,0 +1,3168 @@ +# 4.3 + +## C + +- **Additions** + - Added generated slider data `max` APIs. + - Added generated physics constraint `ScaleYMode` APIs. + - Added generated `Interpolation` and `TrackEntry` mix interpolation APIs for non-linear animation mixing. + - Added `spine_slider` and `spine_slider_data` types for slider constraints + - Regenerated C bindings for the AnimationState additive/hold rework and Skin placeholder name rename in spine-cpp. + - Regenerated C bindings for the updated clipping runtime, including convex and inverse clipping support. + - Regenerated linked mesh APIs so source meshes can be resolved from different slots, matching spine-cpp. + - Added generated attachment timeline slot APIs, including `spine_attachment_get_timeline_slots()`, `spine_attachment_set_timeline_slots()`, and `spine_attachment_is_timeline_active()`. + - Added generated animation color and bone icon size/rotation APIs. + +- **Bug fixes** + - Fixed draw order timelines not mixing out to the setup pose. + - Fixed slider sorting crashes when slider animations key slot or constraint timelines. + - Fixed bones that don't inherit rotation when parent scale is near zero. + - Fixed `BonePose::updateLocalTransform()` for `noScale` and `noScaleOrReflection` inheritance. + - Fixed `ScaleYMode_Volume` to avoid extreme scaleY values for very small scaleX factors. + - Fixed attachment timelines so hidden setup-pose attachments remain hidden while mixing out, preserving deform behavior. + - Fixed `Skeleton::updateWorldTransform()` to avoid copying draw order unless it is constrained. + - Fixed constraints so modifying a constrained bone's world transform preserves descendant bone transforms from earlier constraints. + - Fixed one-bone IK inheritance calculations in Y-down coordinate systems. + - Improved clipping performance through the updated spine-cpp clipping runtime. + +- **Breaking changes** + - Removed generated `spine_bone_pose_reset_world()` because resetWorld is an internal implementation detail. + - Attachment loader APIs now receive both the skin `placeholder` and resolved attachment `name`. + - `spine_animation_state_get_current()` renamed to `spine_animation_state_get_track()`. + - Generated mesh attachment APIs now use `source_mesh` naming instead of `parent_mesh` to match spine-cpp, eg `spine_mesh_attachment_get_source_mesh()` / `spine_mesh_attachment_set_source_mesh()`. + - `spine_track_entry_get_mix_blend()` / `spine_track_entry_set_mix_blend()` removed. Use `spine_track_entry_get_additive()` / `spine_track_entry_set_additive()` instead. + - `spine_track_entry_get_hold_previous()` / `spine_track_entry_set_hold_previous()` removed. + - `spine_skin_entry_get_name()` renamed to `spine_skin_entry_get_placeholder_name()`. + - Timeline `apply()` signature changed: `spine_mix_blend` and `spine_mix_direction` parameters replaced with `bool fromSetup, bool add, bool out`. + - `spine_animation_apply()` signature changed to match. + - `spine_curve_timeline1_get_absolute_value()`, `spine_curve_timeline1_get_relative_value()`, `spine_curve_timeline1_get_scale_value()` signatures changed. + - Added `spine_slider_timeline` and `spine_slider_mix_timeline` for animating sliders + - Added new pose system with `spine_bone_local`, `spine_bone_pose`, and related types + - Added `spine_pose`, `spine_posed`, and `spine_posed_active` base types + - Regenerated the C API for the sequence attachment refactor in spine-cpp. `spine_region_attachment` and `spine_mesh_attachment` now mirror the new non-null `Sequence` model exposed by the C++ runtime. + - IK constraint data now uses `spine_scale_y` instead of the old `uniform` boolean, matching spine-cpp. + - `spine_bone_pose_modify_world()` now takes a `spine_skeleton` instead of an update counter. + - `spine_ik_constraint_data_get_scale_y()` / `spine_ik_constraint_data_set_scale_y()` and `spine_scale_y` renamed to `spine_ik_constraint_data_get_scale_y_mode()` / `spine_ik_constraint_data_set_scale_y_mode()` and `spine_scale_y_mode`. + +- **Breaking changes** + - **IMPORTANT**: The C runtime has been completely rewritten as an auto-generated wrapper around the C++ runtime. This is a major breaking change. Users must update their code to use the new API. See https://esotericsoftware.com/spine-c + - All types, functions, and headers have been restructured + - The new runtime provides full feature parity with C++ through automatic code generation, has nullability annotations and documentation, and supports lightweight RTTI, allowing language specific wrappers to be built around it that expose the full type hierarchy idiomatically. See spine-ios and spine-flutter for examples. + - Sequence attachments now follow the spine-cpp sequence refactor. Region and mesh attachments no longer use the old mutable region/UV update path. + - Bone setup and unconstrained pose APIs now use `spine_bone_pose` instead of `spine_bone_local`. Generated bindings such as `spine_bone_data_get_setup_pose()` and `spine_bone_get_pose()` now return `spine_bone_pose`. + - Renamed setup pose functions: + - `spSkeleton_setToSetupPose()` → `spine_skeleton_setup_pose()` + - `spSkeleton_setBonesToSetupPose()` → `spine_skeleton_setup_pose_bones()` + - `spSkeleton_setSlotsToSetupPose()` → `spine_skeleton_setup_pose_slots()` + - `spine_event_data` no longer stores event payload values directly. Use `spine_event_data_get_setup_pose()` and the returned `spine_event` for setup int, float, string, volume, and balance values. + - `spine_animation_create()` now takes only the animation name. `spine_animation_set_timelines()` now also requires the animation's bone indices. + +### SFML + +- **Restructuring** + - Reorganized directory structure - merged with C++ SFML into unified structure + +- **Breaking changes** + - Updated to use new C runtime API + +### SDL + +- **Additions** + - Added CMakePresets.json for modern CMake configuration + - Updated examples with improved rendering + +- **Restructuring** + - Simplified build system with build.sh script + +- **Breaking changes** + - Updated to use new C runtime API + - `spSkeletonDrawable_update()` now takes additional `spine_physics` parameter + +### GLFW + +- **Additions** + - Added CMakePresets.json for modern CMake configuration + - Added physics example (physics.cpp) + - Added IK following example (ik-following.cpp) + - Added dragon sequence examples for binary and JSON loading in both C++ and C: + - `dragon.cpp` + - `dragon-json.cpp` + - `dragon-c.cpp` + - `dragon-json-c.cpp` + - Added C mirrors for the physics and IK following examples: + - `physics-c.cpp` + - `ik-following-c.cpp` + +- **Restructuring** + - Renamed main-cpp-lite.cpp to main-c.cpp + - Simplified build system with build.sh script + - Fixed the GLFW CMake data copy step to copy shared example assets once, avoiding parallel `copy_directory` races under ninja + +- **Breaking changes** + - Updated to use new C runtime API + +## C++ + +- **Additions** + - Added `SliderData::getMax()` / `setMax()` for nonessential bone-driven slider metadata. + - Added `PhysicsConstraintData::getScaleYMode()` / `setScaleYMode()` to control how physics scaleX affects scaleY. + - Added `Interpolation` and `TrackEntry::getMixInterpolation()` / `setMixInterpolation()` for non-linear animation mixing. + - Added `Slider` and `SliderData` classes for slider constraints + - Linked meshes can now inherit deform and sequence timelines from source meshes in different slots. + - Added `Attachment::getTimelineSlots()`, `Attachment::setTimelineSlots()`, and `Attachment::isTimelineActive()` for attachment timeline propagation across linked meshes. + - Added `SliderTimeline` and `SliderMixTimeline` for animating sliders + - Added new pose system with `BoneLocal`, `BonePose`, and related classes for improved transform handling + - Added `Pose`, `Posed`, and `PosedActive` base classes for unified pose management + - Added `ConstraintTimeline` interface for unified constraint timeline indexing + - Added `Animation::getBones()` to get bone indices used by an animation + - Added template method `SkeletonData::findConstraint()` for type-safe constraint queries + - Added `SkeletonRenderer` class with `RenderCommand` for batched rendering + - Added `HasRendererObject` interface for attachments with renderer-specific data + - Ported the latest parser fixes from spine-libgdx, including the 4.3 path constraint flag fix and the weighted mesh binary vertex allocation/count fix. + - Ported the latest additive timeline updates and alpha/RGB timeline flicker fixes from spine-libgdx. + - Ported the AnimationState additive/hold rework from spine-libgdx. `MixBlend` and `MixDirection` are no longer used by timelines. The new system uses `bool fromSetup, bool add, bool out` parameters and a bitmask-based hold system that replaces `holdPrevious` and `interruptAlpha`. + - Added `Timeline::getAdditive()` and `Timeline::getInstant()` to query timeline blending capabilities. + - Added `TrackEntry::getAdditive()` / `TrackEntry::setAdditive()` to control additive blending per track entry. + - Ported the Skin placeholder name rename from spine-libgdx. `Skin::AttachmentMap::Entry::_name` renamed to `_placeholderName`. + - Fixed `SkeletonBinary::readLong()` sign extension bug that truncated 64-bit hash values to 32 bits. + - Ported the sequence attachment refactor from spine-libgdx. `Sequence` now precomputes per-frame regions, UVs, and region offsets, and `RegionAttachment` / `MeshAttachment` now mirror the libgdx implementation. + - Ported the latest clipping runtime changes from spine-libgdx, including convex and inverse clipping support and the inverse clipping crash fix. + - Added `ClippingAttachment::getConvex()` / `setConvex()` and `getInverse()` / `setInverse()`. + - Added `Animation::getColor()` and `BoneData` icon size/rotation accessors for nonessential editor data. + +- **Bug fixes** + - Fixed physics constraint rotation, shear, and scale forces using the wrong Y direction in Y-down runtimes. + - Fixed draw order timelines not mixing out to the setup pose. + - Fixed slider sorting crashes when slider animations key slot or constraint timelines. + - Fixed `SliderData` leaking its `FromProperty` by adding a destructor that frees `_property` and its `ToProperty` children, matching `TransformConstraintData`. + - Fixed bones that don't inherit rotation when parent scale is near zero. + - Fixed `BonePose::updateLocalTransform()` for `noScale` and `noScaleOrReflection` inheritance, plus related IK epsilon handling. + - Fixed `ScaleYMode_Volume` to avoid extreme scaleY values for very small scaleX factors. + - Fixed `InheritTimeline` so inherit keys are applied to the keyed bone instead of an uninitialized bone index. + - Fixed `AnimationState` attachment timeline handling so deforms are applied correctly when an attachment is hidden in the setup pose. + - Fixed `Skeleton::updateWorldTransform()` to avoid copying draw order unless it is constrained. + - Fixed constraints so modifying a constrained bone's world transform preserves descendant bone transforms from earlier constraints. + - Fixed one-bone IK inheritance calculations in Y-down coordinate systems. + - Improved clipping performance by computing barycentric data lazily and reusing edge side tests. + +- **Breaking changes** + - `MathUtil::Epsilon2` renamed to `MathUtil::EpsilonSq`. + - `BonePose::modifyWorld()` now takes a `Skeleton &` instead of an update counter. + - `BonePose::resetWorld()` is now private. + - `AttachmentLoader` methods now receive both the skin `placeholder` and resolved attachment `name`. `Skin::AttachmentMap::Entry::_placeholderName` renamed to `_placeholder`. + - `AnimationState::getCurrent()` renamed to `AnimationState::getTrack()`. + - `MeshAttachment::getParentMesh()` / `setParentMesh()` renamed to `getSourceMesh()` / `setSourceMesh()`. + - Headers reorganized from `spine-cpp/spine-cpp/include/spine/` to `spine-cpp/include/spine/` + - Timeline `apply()` signature changed: `MixBlend blend, MixDirection direction` replaced with `bool fromSetup, bool add, bool out`. All timeline subclasses updated. + - `Animation::apply()` signature changed to match the new timeline parameters. + - `CurveTimeline1::getRelativeValue()`, `getAbsoluteValue()`, and `getScaleValue()` signatures changed from `MixBlend`/`MixDirection` to `bool fromSetup, bool add, bool out`. + - `TrackEntry::getHoldPrevious()` / `setHoldPrevious()` removed. Use `TrackEntry::getAdditive()` / `setAdditive()` instead for additive blending. + - `TrackEntry::getMixBlend()` / `setMixBlend()` removed. + - `TrackEntry::_interruptAlpha` removed. + - `Skin::AttachmentMap::Entry::_name` renamed to `_placeholderName`. All `Skin` methods use `placeholderName` parameter names instead of `name`/`attachmentName`. + - `AnimationState` hold constants changed: `HoldSubsequent` and `HoldMix` removed, replaced with bitmask system (`Subsequent=0, First=1, Hold=2, HoldFirst=3`). + - `Bone` now extends `PosedActive` with separate pose, constrained, and applied states + - `IkConstraintData::getUniform()` / `setUniform()` replaced by `getScaleY()` / `setScaleY()` and `ScaleY` (`none`, `uniform`, `volume`). + - `IkConstraintData::getScaleY()` / `setScaleY()` and `ScaleY` renamed to `getScaleYMode()` / `setScaleYMode()` and `ScaleYMode`. + - `BoneData::getSetupPose()` and `Bone::getPose()` now use `BonePose` instead of `BoneLocal`. Bone timelines and parser setup pose data were updated to match the spine-libgdx `BoneLocal` removal. + - Renamed timeline constraint index methods to use unified `getConstraintIndex()` + - Changed timeline class hierarchy with new base classes `BoneTimeline`, `SlotCurveTimeline`, and `ConstraintTimeline` + - Sequence attachments now use the new non-null `Sequence` model. `RegionAttachment` and `MeshAttachment` were refactored to match spine-libgdx and no longer use the old lazy mutable region update path. + - Renamed setup pose methods: + |||| + |-----|-|-----| + | `Skeleton::setToSetupPose()` |→| `Skeleton::setupPose()` | + | `Skeleton::setBonesToSetupPose()` |→| `Skeleton::setupPoseBones()` | + | `Skeleton::setSlotsToSetupPose()` |→| `Skeleton::setupPoseSlots()` | + | Bone::setToSetupPose() |→| Bone::setupPose() | + | Slot::setToSetupPose() |→| Slot::setupPose() | + | IkConstraint::setToSetupPose() |→| IkConstraint::setupPose() | + - `EventData` now stores shared payload defaults in `EventData::getSetupPose()` instead of directly on `EventData`. Use the returned `Event` for setup int, float, string, volume, and balance values. + - `Animation` now constructs with only a name. Call `setTimelines(timelines, bones)` and `setDuration()` after loading timelines. + | TransformConstraint::setToSetupPose() |→| TransformConstraint::setupPose() | + | PathConstraint::setToSetupPose() |→| PathConstraint::setupPose() | + | PhysicsConstraint::setToSetupPose() |→| PhysicsConstraint::setupPose() | + - `Bone` local transform properties moved to `bone.getPose()`: + |||| + |-----|-|-----| + | bone.getX() |→| bone.getPose().getX() | + | bone.getY() |→| bone.getPose().getY() | + | bone.getRotation() |→| bone.getPose().getRotation() | + | bone.getScaleX() |→| bone.getPose().getScaleX() | + | bone.getScaleY() |→| bone.getPose().getScaleY() | + | bone.getShearX() |→| bone.getPose().getShearX() | + | bone.getShearY() |→| bone.getPose().getShearY() | + - `Bone` world and applied transform properties moved to `bone.getAppliedPose()`: + |||| + |-----|-|-----| + | bone.getWorldX() |→| bone.getAppliedPose().getWorldX() | + | bone.getWorldY() |→| bone.getAppliedPose().getWorldY() | + | bone.getWorldRotationX()|→| bone.getAppliedPose().getWorldRotationX()| + | bone.getWorldRotationY()|→| bone.getAppliedPose().getWorldRotationY()| + | bone.getWorldScaleX() |→| bone.getAppliedPose().getWorldScaleX() | + | bone.getWorldScaleY() |→| bone.getAppliedPose().getWorldScaleY() | + | bone.getA() |→| bone.getAppliedPose().getA() | + | bone.getB() |→| bone.getAppliedPose().getB() | + | bone.getC() |→| bone.getAppliedPose().getC() | + | bone.getD() |→| bone.getAppliedPose().getD() | + - `Slot` properties moved to `slot.getPose()`: + |||| + |-----|-|-----| + | slot.getColor() |→| slot.getPose().getColor() | + | slot.getDarkColor() |→| slot.getPose().getDarkColor() | + | slot.getAttachment() |→| slot.getPose().getAttachment() | + | slot.getHasSecondColor() |→| slot.getPose().getHasSecondColor() | + | slot.getDeform() |→| slot.getPose().getDeform() | + - `IkConstraint` properties moved to `ikConstraint.getPose()`: + |||| + |-----|-|-----| + | ikConstraint.getMix() |→| ikConstraint.getPose().getMix() | + | ikConstraint.getSoftness() |→| ikConstraint.getPose().getSoftness() | + | ikConstraint.getBendDirection() |→| ikConstraint.getPose().getBendDirection() | + | ikConstraint.getCompress() |→| ikConstraint.getPose().getCompress() | + | ikConstraint.getStretch() |→| ikConstraint.getPose().getStretch() | + - `TransformConstraint` properties moved to `transformConstraint.getPose()`: + |||| + |-----|-|-----| + | transformConstraint.getMixRotate() |→| transformConstraint.getPose().getMixRotate() | + | transformConstraint.getMixX() |→| transformConstraint.getPose().getMixX() | + | transformConstraint.getMixY() |→| transformConstraint.getPose().getMixY() | + | transformConstraint.getMixScaleX() |→| transformConstraint.getPose().getMixScaleX() | + | transformConstraint.getMixScaleY() |→| transformConstraint.getPose().getMixScaleY() | + | transformConstraint.getMixShearY() |→| transformConstraint.getPose().getMixShearY() | + - `PathConstraint` properties moved to `pathConstraint.getPose()`: + |||| + |-----|-|-----| + | pathConstraint.getPosition() |→| pathConstraint.getPose().getPosition() | + | pathConstraint.getSpacing() |→| pathConstraint.getPose().getSpacing() | + | pathConstraint.getMixRotate() |→| pathConstraint.getPose().getMixRotate() | + | pathConstraint.getMixX() |→| pathConstraint.getPose().getMixX() | + | pathConstraint.getMixY() |→| pathConstraint.getPose().getMixY() | + - `PhysicsConstraint` properties moved to `physicsConstraint.getPose()`: + |||| + |-----|-|-----| + | physicsConstraint.getMix() |→| physicsConstraint.getPose().getMix() | + | physicsConstraint.getGravity() |→| physicsConstraint.getPose().getGravity() | + | physicsConstraint.getStrength() |→| physicsConstraint.getPose().getStrength() | + | physicsConstraint.getDamping() |→| physicsConstraint.getPose().getDamping() | + | physicsConstraint.getMassInverse() |→| physicsConstraint.getPose().getMassInverse() | + | physicsConstraint.getWind() |→| physicsConstraint.getPose().getWind() | + - `ConstraintData` properties moved to `constraintData.getSetupPose()`: + |||| + |-----|-|-----| + | ikConstraintData.getMix() |→| ikConstraintData.getSetupPose().getMix() | + | ...| |...| + - `SkeletonData` now provides a single `ConstraintData` list `getConstraints()` instead of separate lists per constraint type: + |||| + |-----|-|-----| + | skeletonData.getIkConstraints() |→| Filter skeletonData.getConstraints() for IkConstraintData instances | + | skeletonData.getTransformConstraints() |→| Filter skeletonData.getConstraints() for TransformConstraintData instances | + | skeletonData.getPathConstraints() |→| Filter skeletonData.getConstraints() for PathConstraintData instances | + | skeletonData.getPhysicsConstraints() |→| Filter skeletonData.getConstraints() for PhysicsConstraintData instances | + - `SkeletonData` now provides unified `findConstraint()` template method: + |||| + |-----|-|-----| + | skeletonData.findIkConstraint(name) |→| skeletonData.findConstraint(name) | + | skeletonData.findTransformConstraint(name) |→| skeletonData.findConstraint(name) | + | skeletonData.findPathConstraint(name) |→| skeletonData.findConstraint(name) | + | skeletonData.findPhysicsConstraint(name) |→| skeletonData.findConstraint(name) | + - `Physics` enum moved from nested `Skeleton::Physics` to standalone `spine::Physics` + - `updateWorldTransform(Skeleton::Physics::update)` → `updateWorldTransform(spine::Physics::update)` + - Timeline `apply()` methods now take an additional `appliedPose` parameter + - Attachment `computeWorldVertices()` methods now take an additional `skeleton` parameter + - Renamed timeline constraint index methods to use unified `getConstraintIndex()` + - API changes to match reference runtime naming conventions: + - `addAnimationWith()` → `addAnimation()` + - `setAnimationWith()` → `setAnimation()` + - `setMixWith()` → `setMix()` + - `setSkinByName()` → `setSkin()` + - `getAttachmentByName()` → `getAttachment()` + +### Cocos2d-x +- The runtime has been removed, as Cocos2d-x has not been maintained in years, and the latest version no longer compiles out of the box on macOS, iOS, and other platforms. + +### SFML + +- **Restructuring** + - Reorganized directory structure - merged C and C++ examples into a single structure + - Moved from `spine-sfml/c/` and `spine-sfml/cpp/` to unified `spine-sfml/` structure + - Added CMakePresets.json for modern CMake configuration + - Simplified example structure with single main.cpp + +- **Breaking changes** + - Updated to use new C++ runtime with all breaking changes above + +### UE + +- **Additions** + - Added Blueprint APIs for `TrackEntry` mix interpolation. + - Added convex and inverse clipping support through the updated spine-cpp clipping runtime. + +- **Bug fixes** + - Fixed `SpineBoneDriverComponent` failing to drive bones affected by constraints. + - Fixed constraints so modifying a constrained bone's world transform preserves descendant bone transforms from earlier constraints. + - Fixed one-bone IK inheritance calculations in Y-down coordinate systems. + +- **Breaking changes** + - Custom C++ `AttachmentLoader` implementations now receive both the skin `placeholder` and resolved attachment `name`. + - `USpineSkeletonAnimationComponent::GetCurrent()` renamed to `GetTrack()`. + - `USpineWidget::GetCurrent()` renamed to `GetTrack()`. + - Updated to use new C++ runtime with all breaking changes above + +### Godot + +- **Additions** + - Added `SpineSliderData.get_max()` / `set_max()` for nonessential bone-driven slider metadata. + - Added `SpinePhysicsConstraintData.get_scale_y_mode()` / `set_scale_y_mode()`. + - Added `SpineTrackEntry` mix interpolation APIs and `SpineConstant.MixInterpolation`. + - Added convex and inverse clipping support through the updated spine-cpp clipping runtime. + - Added `SpineSlider` and `SpineSliderData` classes for slider constraints + - Added `SpineTrackEntry.get_additive()` / `set_additive()` for additive blending per track entry. + +- **Bug fixes** + - Fixed `SpineSkeletonDataResource` constraint getters returning null entries and dropping constraints when multiple constraint types are present. + - Fixed physics constraint rotation pointing opposite to translation under gravity and vertical wind. + - Fixed Godot wrapper crashes from invalid skin attachment lookups, wrong constraint type filtering, stale cached bone/slot wrappers after skeleton rebuilds, dangling `SpineSlotNode` connections after unparenting, and stale Godot 3 wrapper signal connections. + - Fixed `SpineSprite` debug drawing and global bone transform helpers to work when a skeleton exists without an animation state. + - Fixed draw order timelines not mixing out to the setup pose. + - Fixed editor crashes when assigning skeleton data with slider animations that key slots or constraints. + - Fixed attachment timelines so hidden setup-pose attachments remain hidden while mixing out, preserving deform behavior. + - Fixed constraints so modifying a constrained bone's world transform preserves descendant bone transforms from earlier constraints. + - Fixed one-bone IK inheritance calculations in Y-down coordinate systems. + - Fixed `SpineAnimationTrack` editor preview paths for nested `AnimationPlayer` roots, and prevented inactive tracks from clearing `SpineSprite` preview animations. + - Fixed GDExtension animation mix editing in the Godot inspector. + - Fixed `SpineBoneNode` and `SpineSlotNode` transforms when bones use negative scale or shear, and applied `SpineBoneNode` Drive mode before world transforms are computed. + - Fixed `SpineSlotNode` and global bone transforms exposing the runtime Y-down coordinate conversion as negative Godot Node2D Y scale. + - Fixed Godot 4.7 GDExtension resource loading for raw `.skel`, `.spine-json`, and `.atlas` Spine asset files. + - Updated Godot 4.x CI builds to Godot 4.6.2. + - Fixed Godot 4.6 Windows editor CI builds by installing Direct3D 12 SDK dependencies before building Godot. + - Fixed Godot 4.6 GDExtension builds with the latest `godot-cpp` by including the required `Ref` support header in `SpineCommon.h`, updated `SpineEventData` for the `EventData.setupPose` API change, and refreshed vendored `spine-cpp` sources during clean setup. + - Fixed Godot 4.7 module and GDExtension build compatibility. + - Fixed Godot 4.7 Windows module CI builds by updating the Godot 4.x SCons dependency. + - Fixed Godot 3.6 Windows CI builds by not generating Visual Studio project files when building with MinGW. + - Fixed Godot 3.x builds by avoiding the Godot 4-only `Transform2D(Vector2, Vector2, Vector2)` constructor. + +- **Breaking changes (since previous 4.3 beta)** + - `SpineSkin` attachment method argument names now use `placeholder` instead of `name`. + - `SpineTrackEntry.get_hold_previous()` / `set_hold_previous()` removed. + - `SpineTrackEntry.get_mix_blend()` / `set_mix_blend()` removed. Use `get_additive()` / `set_additive()` for additive blending. + - `SpineConstant.MixBlend` and `SpineConstant.MixDirection` enums removed. + - `SpineTimeline.apply()` signature changed: `blend` and `direction` parameters replaced with `from_setup`, `add`, `out`. + - `SpineAnimation.apply()` signature changed to match. + - `SpineAnimationTrack` property `hold_previous` replaced with `additive`, property `mix_blend` removed. + - Added `SpineBoneLocal` and `SpineBonePose` classes for new pose system + - Added pose classes for constraints: `SpineIkConstraintPose`, `SpinePathConstraintPose`, `SpinePhysicsConstraintPose`, `SpineSliderPose`, `SpineTransformConstraintPose` + - `SpineIkConstraintData.get_scale_y()` / `set_scale_y()` and `SpineConstant.ScaleY` renamed to `get_scale_y_mode()` / `set_scale_y_mode()` and `SpineConstant.ScaleYMode`. + +- **Breaking changes** + - `SpineAnimationState.get_current()` renamed to `SpineAnimationState.get_track()` in the GDScript API. + - Updated to use new C++ pose system internally + - `SpineBone.get_pose()` and `SpineBoneData.get_setup_pose()` now return `SpineBonePose` to match the updated spine-cpp bone pose API. + - Removed from `SpineBone`: `update_world_transform()`, `set_to_setup_pose()`, `get_world_to_local_rotation_x()`, `get_world_to_local_rotation_y()` + - Removed direct property access from `SpineBone`: `get_x()`, `set_x()`, `get_y()`, `set_y()`, `get_rotation()`, `set_rotation()`, etc. - use pose objects instead + - `SpineAnimation.apply()` now takes an additional `appliedPose` parameter + - Note: `SpineSkeleton` still maintains `set_to_setup_pose()`, `set_bones_to_setup_pose()`, `set_slots_to_setup_pose()` for compatibility + +## C# + +- **Additions** + - Added `Slider` and `SliderData` classes for slider constraints + - Added `SliderTimeline` and `SliderMixTimeline` for animating sliders + - Added new pose system with `BonePose` and related classes + - Added `IPose`, `Posed`, and `PosedActive` base classes for unified pose management + - Added `IConstraintTimeline` interface for unified constraint timeline indexing + - Added `Animation.Bones` property to get bone indices used by an animation + - Added `Skeleton` properties `GravityX`, `GravityY`, `WindX`, `WindY` to allow rotating physics force directions + - Added `Color32F` class used in new `.GetColor()` and `.SetColor()` methods replacing `.R` `.G` `.B` `.A` properties + - Linked meshes can now inherit deform and sequence timelines from source meshes in different slots + - Added `Attachment.TimelineSlots` and `Attachment.IsTimelineActive()` for attachment timeline propagation across linked meshes + - Added `DrawOrderFolderTimeline` for animating draw order folders + - Added `ClippingAttachment.Convex` and `ClippingAttachment.Inverse` + - Added `IkConstraintData.ScaleYMode` enum and `IkConstraintData.ScaleY` to control how IK compress/stretch changes `BonePose.ScaleY`, including volume preservation + - Added `allowMissingRegions` parameter to `AtlasAttachmentLoader` constructor to support skeletons exported with per-skin atlases + - `TrackEntry.Reverse` animations now fire events. Previously events were not fired when an animation was played in reverse. + - Added `TrackEntry.MixInterpolation` for customizable non-linear mixing. Defaults to `Interpolation.Linear` to maintain existing behaviour. + +- **Breaking changes** + - Color properties `.R` `.G` `.B` `.A` are replaced by `.GetColor()` and `.SetColor()` + - Dark color properties `.R2` `.G2` `.B2` are replaced by `.GetDarkColor()` and `.SetDarkColor()` + - `Bone` now extends `PosedActive` with separate pose, constrained, and applied states + - `Bone` local transform properties moved to `Bone.Pose`: + |||| + |---------------|-|-------------| + | Bone.X |→| Bone.Pose.X | + | Bone.Y |→| Bone.Pose.Y | + | Bone.Rotation |→| Bone.Pose.Rotation | + | Bone.ScaleX |→| Bone.Pose.ScaleX | + | Bone.ScaleY |→| Bone.Pose.ScaleY | + | Bone.ShearX |→| Bone.Pose.ShearX | + | Bone.ShearY |→| Bone.Pose.ShearY | + - `Bone` world and applied transform properties moved to `Bone.AppliedPose`: + |||| + |---------------------|-|--------------------| + | Bone.AX |→| Bone.AppliedPose.X | + | Bone.AY |→| Bone.AppliedPose.Y | + | Bone.ARotation |→| Bone.AppliedPose.Rotation | + | Bone.AScaleX |→| Bone.AppliedPose.ScaleX | + | Bone.AScaleY |→| Bone.AppliedPose.ScaleY | + | Bone.AShearX |→| Bone.AppliedPose.ShearX | + | Bone.AShearY |→| Bone.AppliedPose.ShearY | + | Bone.WorldX |→| Bone.AppliedPose.WorldX | + | Bone.WorldY |→| Bone.AppliedPose.WorldY | + | Bone.WorldRotationX |→| Bone.AppliedPose.WorldRotationX | + | Bone.WorldRotationY |→| Bone.AppliedPose.WorldRotationY | + - `Bone` no longer provides a `Bone.Skeleton` property, constructor no longer takes a `skeleton` parameter + - `Slot` properties moved to `SlotPose`, i.e. `Slot.AppliedPose`: + |||| + |-----------------------|-|-----------------------------| + | Slot.Attachment |→| Slot.AppliedPose.Attachment | + | Slot.R .G .B .A |→| Slot.AppliedPose.GetColor() and Slot.AppliedPose.SetColor() | + | Slot.R2 .G2 .B2 |→| Slot.AppliedPose.GetDarkColor() and Slot.AppliedPose.SetDarkColor() | + | Slot.HasSecondColor |→| Slot.AppliedPose.HasDarkColor | + | Slot.Deform |→| Slot.AppliedPose.Deform | + | Slot.SequenceIndex |→| Slot.AppliedPose.SequenceIndex | + - `Constraint` properties moved to `Constraint.Pose`: + |||| + |-----------------------------|-|-----------------------| + | IkConstraint.Mix |→| IkConstraint.Pose.Mix | + | IkConstraint.Softness |→| IkConstraint.Pose.Softness | + | IkConstraint.BendDirection |→| IkConstraint.Pose.BendDirection | + | IkConstraint.Compress |→| IkConstraint.Pose.Compress | + | IkConstraint.Stretch |→| IkConstraint.Pose.Stretch | + + |||| + |-------------------------------|-|------------------------------------| + | TransformConstraint.MixRotate |→| TransformConstraint.Pose.MixRotate | + | TransformConstraint.MixX |→| TransformConstraint.Pose.MixX | + | TransformConstraint.MixY |→| TransformConstraint.Pose.MixY | + | TransformConstraint.MixScaleX |→| TransformConstraint.Pose.MixScaleX | + | TransformConstraint.MixScaleY |→| TransformConstraint.Pose.MixScaleY | + | TransformConstraint.MixShearY |→| TransformConstraint.Pose.MixShearY | + + |||| + |---------------------------|-|------------------------------| + | PathConstraint.Position |→| PathConstraint.Pose.Position | + | PathConstraint.Spacing |→| PathConstraint.Pose.Spacing | + | PathConstraint.MixRotate |→| PathConstraint.Pose.MixRotate | + | PathConstraint.MixX |→| PathConstraint.Pose.MixX | + | PathConstraint.MixY |→| PathConstraint.Pose.MixY | + + |||| + |-------------------------------|-|----------------------------| + | PhysicsConstraint.Mix |→| PhysicsConstraint.Pose.Mix | + | PhysicsConstraint.Gravity |→| PhysicsConstraint.Pose.Gravity | + | PhysicsConstraint.Strength |→| PhysicsConstraint.Pose.Strength | + | PhysicsConstraint.Damping |→| PhysicsConstraint.Pose.Damping | + | PhysicsConstraint.MassInverse |→| PhysicsConstraint.Pose.MassInverse | + | PhysicsConstraint.Wind |→| PhysicsConstraint.Pose.Wind | + - `ConstraintData` properties moved to `ConstraintData.GetSetupPose()` + |||| + |-----|-|-----| + | IkConstraintData.Mix |→| IkConstraintData.GetSetupPose().Mix | + | ...| |...| + + - `SkeletonData` now provides a single `IConstraintData` list `SkeletonData.Constraints` instead of separate lists per constraint type + |||| + |-----|-|-----| + | SkeletonData.IkConstraints |→| SkeletonData.Constraints.OfType\() | + | SkeletonData.TransformConstraints |→| SkeletonData.Constraints.OfType\() | + | SkeletonData.PathConstraints |→| SkeletonData.Constraints.OfType\() | + | SkeletonData.PhysicsConstraints |→| SkeletonData.Constraints.OfType\() | + - `SkeletonData` now provides `SkeletonData.FindConstraint()` instead of single find methods per constraint type + |||| + |-----|-|-----| + | SkeletonData.FindIkConstraint |→| SkeletonData.FindConstraint\() | + | SkeletonData.FindTransformConstraint |→| SkeletonData.FindConstraint\() | + | SkeletonData.FindPathConstraint |→| SkeletonData.FindConstraint\() | + | SkeletonData.FindPhysicsConstraint |→| SkeletonData.FindConstraint\() | + - Renamed setup pose methods: + |||| + |-----|-|-----| + | `Skeleton.SetToSetupPose()` |→| `Skeleton.SetupPose()` | + | `Skeleton.SetBonesToSetupPose()` |→| `Skeleton.SetupPoseBones()` | + | `Skeleton.SetSlotsToSetupPose()` |→| `Skeleton.SetupPoseSlots()` | + | Bone.SetToSetupPose() |→| Bone.SetupPose() | + | Slot.SetToSetupPose() |→| Slot.SetupPose() | + | IkConstraint.SetToSetupPose() |→| IkConstraint.SetupPose() | + - `Skeleton.Physics` was moved to `Physics` directly in `Spine` namespace + - `UpdateWorldTransform(Skeleton.Physics.Update)` → `UpdateWorldTransform(Spine.Physics.Update)` + - Timeline `Apply()` methods now take an additional `appliedPose` parameter + - Attachment `ComputeWorldVertices()` methods now take an additional `skeleton` parameter + - Renamed timeline constraint index methods to use unified `ConstraintIndex` property + - Reorganized timeline class hierarchy with new base classes + - Removed `AtlasAttachmentLoader` method `AtlasRegion FindRegion(string name)` from public interface. Added `protected AtlasRegion FindRegion(string name, string path)` instead which may be overridden instead when deriving your own subclass. + - Removed `TrackEntry.HoldPrevious` and `TrackEntry.InterruptAlpha`. New `AnimationState` hold system automatically calculates the required state values. + - Removed `BoneLocal` class. `BonePose` now directly implements `IPose` and contains all local pose fields. Replace any use of `BoneLocal` → `BonePose`. + - `EventData` no longer stores `Int`, `Float`, `String`, `Volume`, and `Balance` properties directly. Use `EventData.SetupPose` to access the setup pose `Event` which provides these properties instead. + |||| + |-----|-|-----| + | `EventData.Int` |→| `EventData.SetupPose.Int` | + | `EventData.Float` |→| `EventData.SetupPose.Float` | + | `EventData.String` |→| `EventData.SetupPose.String` | + | `EventData.Volume` |→| `EventData.SetupPose.Volume` | + | `EventData.Balance` |→| `EventData.SetupPose.Balance` | + - `Timeline.PropertyIds` type changed from `string[]` to `ulong[]`. `Animation.HasTimeline()` parameter and Timeline constructors changed accordingly. + - `Skeleton.DrawOrder` type changed from `ExposedList` to `DrawOrder` class. Use `Skeleton.DrawOrder.AppliedPose` for rendering and `Skeleton.DrawOrder.Pose` for changing the draw order. + - `IkConstraintData.Uniform` replaced by `IkConstraintData.ScaleY`. `IkConstraint.Apply()` methods now take `ScaleY` instead of a `bool uniform` parameter. + - `MeshAttachment.ParentMesh` renamed to `MeshAttachment.SourceMesh` + - `AttachmentLoader` methods `NewRegionAttachment`, `NewMeshAttachment`, `NewBoundingBoxAttachment`, `NewClippingAttachment`, `NewPathAttachment`, and `NewPointAttachment` now take an additional `string placeholder` parameter. Update any custom `AttachmentLoader` implementations accordingly. + - Renamed `Skin.SkinEntry.Name` to `Skin.SkinEntry.Placeholder` to better match Spine editor terminology. Was intermediately renamed to `PlaceholderName` which was then changed to `Placeholder`. + - `MathUtils.IInterpolation` class is replaced by new `Interpolation` class, see *Additions* above. + - `AnimationState.SetCurrent()` renamed to `AnimationState.SetTrack()`; `AnimationState.GetCurrent()` renamed to `AnimationState.GetTrack()`. + |||| + |-----|-|-----| + | `AnimationState.SetCurrent()` |→| `AnimationState.SetTrack()` | + | `AnimationState.GetCurrent()` |→| `AnimationState.GetTrack()` | + - Ported the AnimationState additive/hold rework from spine-libgdx. `MixBlend`, `MixDirection`, `holdPrevious`, and `interruptAlpha` are no longer used. Timeline mixing now uses `MixFrom`, `add`, and `mixOut` parameters, with hold state calculated automatically. + - `Animation.Apply()` and `Timeline.Apply()` now take a `MixFrom` value instead of the previous boolean `fromSetup` argument. Replace `true` with `MixFrom.Setup` and `false` with `MixFrom.Current`. If you upgraded to an intermediate 4.3 runtime that still used `fromSetup`, update those call sites again. + +### Unity + +- **Officially supported Unity versions are 2017.1-6000.4**. + +- **Breaking changes** + - Updated to use new C# runtime with all breaking changes above + - **MAJOR ARCHITECTURE CHANGE: Main skeleton components have been split into separate rendering and animation components.** Components will be automatically upgraded when scenes/prefabs are opened in the Unity Editor. See the `Documentation/4.3-split-component-upgrade-guide.md` document for detailed migration instructions. The major changes are: + - `SkeletonAnimation` is now split into `SkeletonAnimation` + `SkeletonRenderer` components + - `SkeletonMecanim` is now split into `SkeletonMecanim` + `SkeletonRenderer` components + - `SkeletonGraphic` is now split into `SkeletonAnimation` + `SkeletonGraphic` components + - Example skeletons in Spine Examples are now using straight alpha textures and materials for better compatibility with Linear colorspace. + - `Skeleton.Physics` was moved to `Physics` directly in `Spine` namespace, thus might clash with `UnityEngine.Physics`. + - Spine Physics: `UpdateWorldTransform(Skeleton.Physics.Update)` → `UpdateWorldTransform(Spine.Physics.Update)` + - UnityEngine Physics: `Physics.gravity` → `UnityEngine.Physics.gravity`. + - `SkeletonRenderer`: `maskInteraction` → `MaskInteraction`. + - Removed rather useless old menu entries `GameObject - Spine - SkeletonRenderer` and the like which are spawning e.g. a GameObject with an empty `SkeletonRenderer` component without `SkeletonDataAsset` assigned and thus also not initialized properly. + - Removed `attachment.GetRemappedClone()` extension methods. Replace `attachment.GetRemappedClone(parameters)` with `attachment.Copy(); attachment.SetRegion(parameters)`. Removed `AttachmentCloneExtensions` class, `SetRegion` methods are now in `AttachmentRegionExtensions`. + - Renamed `ToAtlasRegionPMAClone` to `ToAtlasRegionWithNewPMATexture`. + - Renamed `ToRegionAttachmentPMAClone` to `ToRegionAttachmentWithNewPMATexture`. + - Removed support for long abandoned thirdparty asset "2D Toolkit" (TK2D) by Unikron Software. + - Removed Spine Timeline `Spine Animation State Clip` property `Hold Previous`. New `AnimationState` hold system automatically calculates the required state values. + - Removed intermediately added (4.3-beta branch only) `SkeletonAnimation` callbacks `MainThreadStart`, `MainThreadInterrupt`, `MainThreadEnd`, `MainThreadDispose`, `MainThreadComplete` and `MainThreadEvent`. Instead `SkeletonAnimation.AnimationState` and `TrackEntry` events are now automatically processed on the main thread. There is no longer a change of user code required for these events, and `TrackEntry` events can be utilized directly even with threaded animation enabled. + - `SkeletonGraphic` property `CustomSlotMaterials` now properly assigns the override material directly instead of assigning the texture of the override material, which was of little use. + +- **Changes of default values** + - Changed default atlas texture workflow from PMA to straight alpha textures. This move was done because straight alpha textures are compatible with both Gamma and Linear color space, with the latter being the default for quite some time now in Unity. Note that `PMA Vertex Color` is unaffected and shall be enabled as usual to allow for single-pass additive rendering. + +- **Additions** + - Added Spine Preferences `Switch Texture Workflow` functionality to quickly switch to the respective PMA or straight-alpha texture and material presets. + - Added a workflow mismatch dialog showing whenever problematic PMA vs. straight alpha settings are detected at a newly imported `.atlas.txt` file. Invalid settings include the atlas being PMA and project using Linear color space, and a mismatch of Auto-Import presets set to straight alpha compared to the atlas being PMA and vice versa. The dialog offers an option to automatically fix the problematic setting on the import side and links website documentation for export settings. This dialog can be disabled and re-enabled via Spine preferences. + - Added threading support for all skeleton rendering and animation components, disabled by default. Threading can be activated per component or globally via Edit → Preferences → Spine → Threading Defaults. Two threading options are available: + - `Threaded MeshGeneration`: Default value for SkeletonRenderer and SkeletonGraphic threaded mesh generation + - `Threaded Animation`: Default value for SkeletonAnimation and SkeletonMecanim threaded animation updates + - Even when threading is enabled, the threading system defaults to `SkeletonRenderer` and `SkeletonAnimation` user callbacks like `UpdateWorld` (not including `AnimationState` callbacks) being issued on the main thread to support existing user code. Can be configured via `SkeletonUpdateSystem.Instance.MainThreadUpdateCallbacks = false` to perform callbacks on worker threads if parallel execution is supported and desired by the user code. `OnPostProcessVertices` is an exception, as it it's deliberately left on worker threads so that parallellization can be utilized. Note that most Unity API calls are restricted to the main thread. + - Added `SkeletonUpdateSystem.Instance.GroupRenderersBySkeletonType` and `GroupAnimationBySkeletonType` properties. Defaults to disabled. Later when smart partitioning is implemented, enabling this parameter might slightly improve cache locality. Until then having it enabled combined with different skeleton complexity would lead to worse load balancing. + - Added previously missing editor drag & drop skeleton instantiation option *SkeletonGraphic (UI) Mecanim* combining components `SkeletonGraphic` and `SkeletonMecanim`. + - Added define `SPINE_DISABLE_THREADING` to disable threaded animation and mesh generation entirely, removing the respective code. This define can be set as `Scripting Define Symbols` globally or for selective build profiles where desired. + - Added automatic load balancing (work stealing) for improved performance when using threaded animation and mesh generation, enabled by default. Load balancing can be disabled via a new Spine preferences parameter `Threading Defaults - Load Balancing` setting a build define accordingly. + Additional configuration parameters `SkeletonUpdateSystem.UpdateChunksPerThread` and `LateUpdateChunksPerThread` are available to fine-tune the chunk count for load balancing. A minimum of 8 chunks is recommended with load balancing enabled. Higher values add higher overhead with potentially detrimental effect on performance. + - Spine UI Toolkit UPM package now supports rendering back-face triangles. Enable `Flip Back Faces` to automatically fix back-face geometry in an additional pass (defaults to enabled). Disable the setting to save additional processing overhead. + - Spine UI Toolkit UPM package now supports PMA atlas textures. At the `SpineVisualElement` expand `Blend Mode Materials` and hit `Detect Materials` to automatically assign the proper PMA or straight alpha material at `Normal Material`. Unity minimum version increased to 6000.3 which added support for UI Toolkit materials. + - Spine UI Toolkit UPM package now supports all Spine blend modes via blend mode materials and multiple materials per skeleton. Enable `Multiple Materials` (enabled by default), expand `Blend Mode Materials` and hit `Detect Materials` to automatically assign the correct PMA or straight alpha blend mode materials. + - Every Spine URP shader now has an `Outline` option to switch to the respective Outline shader variant. Uses multi-pass support of newer URP versions. Requires spine-unity core package version 4.3.44 or newer due to required modifications in custom Sprite Shader GUI. + - Added new variants of `GetRepackedSkin` and `GetRepackedAttachments` supporting blend modes. These new variants take a packing configuration input struct `RepackAttachmentsSettings` which provides optional `additiveMaterialSource`, `multiplyMaterialSource` and `screenMaterialSource` properties, enabling blend mode repacking when any is non-null. Create your `RepackAttachmentsSettings` from default settings via `RepackAttachmentsSettings.Default` and then customize settings as needed. Blend mode materials can be set at once using `UseSourceMaterialsFrom(SkeletonDataAsset)` or `UseBlendModeMaterialsFrom(SkeletonDataAsset)`. Uses new `RepackAttachmentsOutput` struct providing `DestroyGeneratedAssets` to easily destroy any previously generated assets. + - Updated example scenes to demonstrate new `GetRepackedSkin` variant usage. + - AnimationReferenceAsset: Added animation selector drop-down popup next to object assignment field for easy initial assignment and animation switching. Shows red warning color if the assigned AnimationReferenceAsset's SkeletonDataAsset does not match the one at the GameObjects `SkeletonAnimation` component. A mismatch may be intentional for a special split SkeletonDataAsset setup. Warning color can be disabled in `Edit - Preferences - Spine`, `Warnings - SkeletonDataAsset Mismatch Warning`. + - AnimationReferenceAssets: The `SkeletonDataAsset` Inspector now generates the set of AnimationReferenceAssets as nested assets below a single asset `_AnimationReferences.asset` to avoid cluttering the project with hundreds of asset files. This also makes searching the project for a suitable `AnimationReferenceAsset` of a given `SkeletonDataAsset` much faster. Use of existing old individual assets is still supported alongside nested new ones. If you require the old way of creating assets in your project, add `SPINE_INDIVIDUAL_ANIMATION_REFERENCE_ASSETS` to your project's Scripting Define Symbols. + - AnimationReferenceAssets: Added Spine Preferences setting `Editor Instantiation` - `Warnings - SkeletonDataAsset Mismatch Warning` to disable the warning color when a different SkeletonDataAsset is detected at the `AnimationReferenceAsset` than at the `SkeletonRenderer` component at the same GameObject or any parent GameObject. Might be valid setup for special AnimationReferenceAsset re-use for identical skeletons. + - `SkeletonGraphic` now allows using separate additive Materials despite having `PMA Vertex Colors` enabled (as required for Spine shaders) via the new `Blend Modes` - `Force Additive Material` property in the `Advanced` Inspector section. + - `SkeletonGraphic` property `CustomSlotMaterials` now properly assigns the override material directly instead of assigning the texture of the override material, which was of little use. Thus you can now assign a `SkeletonGraphic` compatible material like `SkeletonGraphicAdditive-Straight`. + - `SkeletonGraphicCustomMaterials` now exposes `Custom Slot Materials` property for slot material overrides. + - Exposed `SpineVisualElement.Initialize` as `public`. + - `SkeletonRenderer` and `SkeletonGraphic` classes now provide `PhysicsPositionInheritanceLimit` and `PhysicsRotationInheritanceLimit` properties, exposed in the component Inspector under `Physics Inheritance` as `Limit` properties, below `Position` and `Rotation`. + - `SkeletonGraphic` now provides a new method `MatchReferenceRectWithBounds` to adjust the reference rectangle bounds to the mesh bounds for use with automatic layout scale modes. The `Match RectTransform with Mesh` `Match` button is now available outside of `Edit Layout Bounds` mode as well and performs this adjustment for quick one-click setup. + - `SkeletonGraphic`: You can now offset the pivot with automatic offset compensation via a newly added blue circle handle. This lets you move the pivot to the skeleton part that you want fixed when auto layout mode scales and moves your skeleton around to fit the RectTransform bounds. It also helps to visualize the current pivot position if you set the pivot numerically via the RectTransform Inspector. + - `SkeletonAnimation` received a `DeltaTimeOverride` callback. This allows advancing by custom delta time for e.g. stepped animation updates in a threaded context. The callback may change `UpdateMode` to disable or limit skeleton updates for certain frames. It is called on the main thread once before animation update. + - Added sample component `SkeletonAnimationFixedTimestepThreaded` as a replacement component for `SkeletonAnimationFixedTimestep` which was limited to single-threaded use only. This component is using the new `DeltaTimeOverride` event and is thus compatible with both single-threaded and multi-threaded animation. + - Added sample component `SkeletonAnimationStaticPoseOptimizer` which automatically skips animation and mesh updates while a SkeletonAnimation's `AnimationState` retains a static pose. It is compatible with threaded animation and mesh updates. The component modifies `SkeletonAnimation.UpdateMode`, so watch out for side effects if multiple components modify this same property. + - On-demand loading modules: Added method `HasRequestFailed` to `GenericOnDemandTextureLoader`, automatically handling when requests fail to be processed. It provides a default implementation returning `false` to maintain the existing behaviour without code change. `AddressableTextureLoader` implements this method accordingly to cover Addressable request failure. Be sure to update both `com.esotericsoftware.spine.addressables` and `com.esotericsoftware.spine.on-demand-loading` UPM packages. + - On-demand loading modules: Added `IDeferredCleanupOnDemandTextureLoader` interface for automatic cleanup by `OnDemandTextureLoaderCleanup` below. `GenericOnDemandTextureLoader` implements this interface. + - On-demand loading modules: Added `OnDemandTextureLoaderCleanup`, which automatically maintains loaders with unreleased texture requests independently of skeleton renderer lifecycle. This is necessary because textures are deliberately kept alive for a delay after their last use to avoid unload/reload thrashing, so cleanup must continue after the last renderer using them is destroyed. When loaders are destroyed or unloaded they now also unload all textures and restore their low-resolution placeholders. + - On-demand loading modules: Build processing now automatically assigns placeholders to all `Material` assets whose main texture references an on-demand target texture. `RenderExistingMesh` replacement materials now support on-demand texture loading. Copied and custom materials used for on-demand loading are restored to placeholders when target textures unload. + +- **Deprecated** + +- **Restructuring (Non-Breaking)** + - Spine Examples have been moved and are now part of the main spine-unity UPM package. To import, select the `spine-unity Runtime` package in the Package Manager window, and in the `Samples` tab and hit `Import`. + +### MonoGame + +- **Breaking changes** + - Updated to use new C# runtime with all breaking changes above + +## iOS + +- **Additions** + - Added native AppKit/macOS support to `SpineiOS` and the example app. + - Added `SpineTextureFilter` overrides to `SpineUIView` and `SpineView`. + - Added generated slider data `max` APIs. + - Added generated physics constraint `scaleYMode` APIs. + - Added generated `Interpolation` and `TrackEntry` mix interpolation APIs. + - Added convex and inverse clipping support through the updated spine-cpp clipping runtime. + +- **Bug fixes** + - Fixed Metal rendering to honor each atlas page's texture filter, mipmap, and wrap settings. + - Fixed draw order timelines not mixing out to the setup pose. + - Fixed bones that don't inherit rotation when parent scale is near zero. + - Fixed `BonePose.updateLocalTransform(_:)` for `noScale` and `noScaleOrReflection` inheritance. + - Fixed attachment timelines so hidden setup-pose attachments remain hidden while mixing out, preserving deform behavior. + - Fixed constraints so modifying a constrained bone's world transform preserves descendant bone transforms from earlier constraints. + - Fixed one-bone IK inheritance calculations in Y-down coordinate systems. + - Improved clipping performance through the updated spine-cpp clipping runtime. + +- **Breaking changes** + - Removed generated `BonePose.resetWorld(_:)` because resetWorld is an internal implementation detail. + - Generated `BonePose.modifyWorld(_:)` now takes a `Skeleton` instead of an update counter. + - Generated SpineSwift attachment loader APIs now receive both the skin `placeholder` and resolved attachment `name`. + - `AnimationState.getCurrent(_:)` renamed to `AnimationState.getTrack(_:)` in SpineSwift. + - SpineSwift mesh attachment APIs now use `sourceMesh` naming instead of `parentMesh` to match spine-cpp. + - SpineSwift attachments now expose `timelineSlots` and `isTimelineActive(...)` to match spine-cpp. + - SpineSwift IK constraint data now uses `scaleY` instead of the old `uniform` boolean. + - SpineSwift IK constraint data `scaleY` and `ScaleY` renamed to `scaleYMode` and `ScaleYMode`. + +## Dart + +- **Additions** + - Added generated slider data `max` APIs. + - Added generated physics constraint `scaleYMode` APIs. + - Added generated `Interpolation` and `TrackEntry` mix interpolation APIs. + - Added `Slider` and `SliderData` classes for slider constraints + - Added `SliderTimeline` and `SliderMixTimeline` for animating sliders + - Added new pose system with `BoneLocal`, `BonePose`, and related classes + - Added `Pose`, `Posed`, and `PosedActive` base classes for unified pose management + +- **Bug fixes** + - Fixed draw order timelines not mixing out to the setup pose. + - Fixed bones that don't inherit rotation when parent scale is near zero. + - Fixed `BonePose.updateLocalTransform()` for `noScale` and `noScaleOrReflection` inheritance. + - Fixed attachment timelines so hidden setup-pose attachments remain hidden while mixing out, preserving deform behavior. + - Fixed constraints so modifying a constrained bone's world transform preserves descendant bone transforms from earlier constraints. + - Fixed one-bone IK inheritance calculations in Y-down coordinate systems. + - Improved clipping performance through the updated spine-cpp clipping runtime. + +- **Breaking changes** + - Removed generated `BonePose.resetWorld()` because resetWorld is an internal implementation detail. + - Generated `BonePose.modifyWorld()` now takes a `Skeleton` instead of an update counter. + - Generated Dart attachment loader APIs now receive both the skin `placeholder` and resolved attachment `name`. + - `AnimationState.getCurrent()` renamed to `AnimationState.getTrack()`. + - The Dart runtime is now fully auto-generated from the C runtime, maintaining the full C++ type hierarchy with proper nullability annotations + - `MeshAttachment.parentMesh` is now `MeshAttachment.sourceMesh`, and attachments now expose `timelineSlots` plus `isTimelineActive(...)` to match spine-cpp. + - All properties are now exposed as getters and setters instead of methods + - API changes to match C++ naming conventions: + - `AnimationState.getData()` → `AnimationState.data` (property) + - `AnimationState.setAnimationByName()` → `AnimationState.setAnimation()` + - `AnimationState.addAnimationByName()` → `AnimationState.addAnimation()` + - `AnimationState.getCurrent()` → `AnimationState.getCurrent()` + - `Skeleton.setSkinByName()` → `Skeleton.setSkin()` + - `Skeleton.setSkin()` → `Skeleton.setSkin2()` + - `Skeleton.setToSetupPose()` → `Skeleton.setupPose()` + - `Skeleton.setBonesToSetupPose()` → `Skeleton.setupPoseBones()` + - `Skeleton.setSlotsToSetupPose()` → `Skeleton.setupPoseSlots()` + - Timeline `apply()` methods now take an additional `appliedPose` parameter + - `EventData` setup payload access moved to `data.setupPose` + - IK constraint data `scaleY` and `ScaleY` renamed to `scaleYMode` and `ScaleYMode`. + +### Flutter + +- **Additions** + - Added generated slider data `max` APIs. + - Added generated physics constraint `scaleYMode` APIs. + - Added generated `Interpolation` and `TrackEntry` mix interpolation APIs. + - Added convex and inverse clipping support through the updated spine-cpp clipping runtime. + - Added `fromMemory` methods to `AtlasFlutter`, `SkeletonDataFlutter`, `SkeletonDrawableFlutter`, and `SpineWidget` for loading Spine data from custom sources (memory, encrypted storage, databases, custom caching, etc.) + - Added example `load_from_memory.dart` demonstrating how to load all assets into memory and use the `fromMemory` API + +- **Bug fixes** + - Fixed draw order timelines not mixing out to the setup pose. + - Fixed bones that don't inherit rotation when parent scale is near zero. + - Fixed `BonePose.updateLocalTransform()` for `noScale` and `noScaleOrReflection` inheritance. + - Fixed attachment timelines so hidden setup-pose attachments remain hidden while mixing out, preserving deform behavior. + - Fixed constraints so modifying a constrained bone's world transform preserves descendant bone transforms from earlier constraints. + - Fixed one-bone IK inheritance calculations in Y-down coordinate systems. + - Improved clipping performance through the updated spine-cpp clipping runtime. + +- **Breaking changes** + - Removed generated `BonePose.resetWorld()` because resetWorld is an internal implementation detail. + - Generated Flutter `BonePose.modifyWorld()` now takes a `Skeleton` instead of an update counter. + - `AnimationState.getCurrent()` renamed to `AnimationState.getTrack()`. + - Generated Flutter attachment loader APIs now receive both the skin `placeholder` and resolved attachment `name`. + - Generated Flutter mesh attachment APIs now use `sourceMesh` naming instead of `parentMesh` to match spine-cpp. + - Generated Flutter bindings now expose `Attachment.timelineSlots` and `Attachment.isTimelineActive(...)` to match spine-cpp. + - Generated Flutter IK constraint data `scaleY` and `ScaleY` renamed to `scaleYMode` and `ScaleYMode`. + - Updated to use the new auto-generated Dart runtime with all the Dart API changes above + - Generated Flutter bindings now use `BonePose` for bone setup and unconstrained pose accessors to match spine-cpp. + - Generated Flutter bindings now expose event setup payloads via `EventData.setupPose` instead of directly on `EventData`. + - Generated Flutter bindings now construct `Animation` with only a name, and setting timelines also requires the animation's bone indices. + - Generated Flutter IK constraint data now uses `scaleY` instead of the old `uniform` boolean. + +## Haxe + +- **Additions** + - Added `Slider` and `SliderData` classes for slider constraints + - Added `SliderTimeline` and `SliderMixTimeline` for animating sliders + - Added new pose system with `BoneLocal`, `BonePose`, and related classes + - Added `Pose`, `Posed`, and `PosedActive` base classes for unified pose management + - Added `ConstraintTimeline` interface for unified constraint timeline indexing + - Added `Animation.getBones()` to get bone indices used by an animation + - Added `Skeleton` properties `windX`, `windY`, `gravityX`, `gravityY` to allow rotating physics force directions + - Added `SequenceTimeline` for sequence animation + - Added `allowMissingRegions` parameter to `AtlasAttachmentLoader` constructor to support skeletons exported with per-skin atlases + - Linked meshes can now inherit deform and sequence timelines from source meshes in different slots + - Added `Attachment.timelineSlots` and `Attachment.isTimelineActive()` for attachment timeline propagation across linked meshes + - Added `DrawOrderFolderTimeline` for animating draw order folders + - Added `Timeline.additive` and `Timeline.instant` to query timeline blending capabilities + - Added `TrackEntry.additive` to control additive blending per track entry + - Added `TrackEntry.mixInterpolation` and `Interpolation` helpers for non-linear AnimationState mixes + - Ported the latest additive timeline updates and alpha/RGB timeline flicker fixes from spine-libgdx + - Ported the AnimationState additive/hold rework from spine-libgdx. `MixBlend` and `MixDirection` are no longer used by timelines. The new system uses `fromSetup`, `add`, and `out` parameters and automatically calculates the required hold state values + - Ported the Skin placeholder name rename from spine-libgdx. `SkinEntry.name` renamed to `placeholderName` to better match Spine editor terminology + - Ported the sequence attachment refactor from spine-libgdx. `Sequence` now precomputes per-frame regions, UVs, and region offsets, and `RegionAttachment` / `MeshAttachment` now mirror the libgdx implementation + - Ported the latest clipping runtime changes from spine-libgdx, including convex and inverse clipping support and the inverse clipping crash fix + - Added `ClippingAttachment.convex` and `ClippingAttachment.inverse` + - Added `Animation.color` for the animation color as it was in Spine when nonessential data is exported + - Added `BoneData` icon size and rotation accessors for nonessential editor data + - Added `ScaleY` enum and `IkConstraintData.scaleY` to control how IK compress/stretch changes `BonePose.scaleY`, including volume preservation + - Fixed `SkeletonData` default FPS and missing `PathAttachment` initialization + - BoundsProvider System: added a new flexible BoundsProvider system to improve bounds calculation performance and correctness across all renderers. + - Added `BoundsProvider` abstract class with interface for calculating skeleton bounding boxes + - Implemented four concrete `BoundsProvider` classes: + - `AABBRectangleBoundsProvider` - Uses a simple axis-aligned bounding box rectangle + - `CurrentPoseBoundsProvider` - Calculates bounds dynamically from the current skeleton pose + - `SetupPoseBoundsProvider` - Uses setup pose bounds (default implementation) + - `SkinsAndAnimationBoundsProvider` - Calculates bounds based on specific skins and animations + +- **Bug fixes** + - Fixed attachment timelines so hidden setup-pose attachments remain hidden while mixing out, preserving deform behavior. + +- **Breaking changes** + - `Bone` now extends `PosedActive` with separate pose, constrained, and applied states + - `Bone` local transform properties moved to `bone.getPose()`: + |||| + |--------------------------|-|-----------------------------| + | bone.x |→| bone.getPose().x | + | bone.y |→| bone.getPose().y | + | bone.rotation |→| bone.getPose().rotation | + | bone.scaleX |→| bone.getPose().scaleX | + | bone.scaleY |→| bone.getPose().scaleY | + | bone.shearX |→| bone.getPose().shearX | + | bone.shearY |→| bone.getPose().shearY | + - `Bone` world and applied transform properties moved to `bone.getAppliedPose()`: + |||| + |---------------------------|-|-------------------------------------| + | bone.ax |→| bone.getAppliedPose().x | + | bone.ay |→| bone.getAppliedPose().y | + | bone.arotation |→| bone.getAppliedPose().rotation | + | bone.ascaleX |→| bone.getAppliedPose().scaleX | + | bone.ascaleY |→| bone.getAppliedPose().scaleY | + | bone.ashearX |→| bone.getAppliedPose().shearX | + | bone.ashearY |→| bone.getAppliedPose().shearY | + | bone.worldX |→| bone.getAppliedPose().worldX | + | bone.worldY |→| bone.getAppliedPose().worldY | + - `Bone` no longer provides a `skeleton` property, constructor no longer takes a `skeleton` parameter + - `Slot` properties moved to `slot.getAppliedPose()`: + |||| + |---------------------------|-|-------------------------------------| + | slot.attachment |→| slot.getAppliedPose().attachment | + | slot.deform |→| slot.getAppliedPose().deform | + | slot.sequenceIndex |→| slot.getAppliedPose().sequenceIndex | + - `Constraint` properties moved to `constraint.getPose()`: + |||| + |----------------------------------|-|----------------------------------------| + | ikConstraint.mix |→| ikConstraint.getPose().mix | + | ikConstraint.softness |→| ikConstraint.getPose().softness | + | ikConstraint.bendDirection |→| ikConstraint.getPose().bendDirection | + | ikConstraint.compress |→| ikConstraint.getPose().compress | + | ikConstraint.stretch |→| ikConstraint.getPose().stretch | + + |||| + |--------------------------------------|-|---------------------------------------| + | transformConstraint.mixRotate |→| transformConstraint.getPose().mixRotate | + | transformConstraint.mixX |→| transformConstraint.getPose().mixX | + | transformConstraint.mixY |→| transformConstraint.getPose().mixY | + | transformConstraint.mixScaleX |→| transformConstraint.getPose().mixScaleX | + | transformConstraint.mixScaleY |→| transformConstraint.getPose().mixScaleY | + | transformConstraint.mixShearY |→| transformConstraint.getPose().mixShearY | + + |||| + |----------------------------------|-|------------------------------------| + | pathConstraint.position |→| pathConstraint.getPose().position | + | pathConstraint.spacing |→| pathConstraint.getPose().spacing | + | pathConstraint.mixRotate |→| pathConstraint.getPose().mixRotate | + | pathConstraint.mixX |→| pathConstraint.getPose().mixX | + | pathConstraint.mixY |→| pathConstraint.getPose().mixY | + + |||| + |--------------------------------------|-|---------------------------------------| + | physicsConstraint.mix |→| physicsConstraint.getPose().mix | + | physicsConstraint.gravity |→| physicsConstraint.getPose().gravity | + | physicsConstraint.strength |→| physicsConstraint.getPose().strength | + | physicsConstraint.damping |→| physicsConstraint.getPose().damping | + | physicsConstraint.massInverse |→| physicsConstraint.getPose().massInverse | + | physicsConstraint.wind |→| physicsConstraint.getPose().wind | + - `ConstraintData` properties moved to `constraintData.setup`: + |||| + |-----|-|-----| + | ikConstraintData.mix |→| ikConstraintData.setup.mix | + | ...| |...| + + - `SkeletonData` now provides a single `ConstraintData` list `constraints` instead of separate lists per constraint type + |||| + |-----|-|-----| + | skeletonData.ikConstraints |→| Filter skeletonData.constraints for IkConstraintData instances | + | skeletonData.transformConstraints |→| Filter skeletonData.constraints for TransformConstraintData instances | + | skeletonData.pathConstraints |→| Filter skeletonData.constraints for PathConstraintData instances | + | skeletonData.physicsConstraints |→| Filter skeletonData.constraints for PhysicsConstraintData instances | + - `SkeletonData` now provides unified `findConstraint()` method with Class parameter: + |||| + |-----|-|-----| + | skeletonData.findIkConstraint(name) |→| skeletonData.findConstraint(name, IkConstraintData) | + | skeletonData.findTransformConstraint(name) |→| skeletonData.findConstraint(name, TransformConstraintData) | + | skeletonData.findPathConstraint(name) |→| skeletonData.findConstraint(name, PathConstraintData) | + | skeletonData.findPhysicsConstraint(name) |→| skeletonData.findConstraint(name, PhysicsConstraintData) | + - Renamed setup pose methods: + |||| + |-----|-|-----| + | `Skeleton.setToSetupPose()` |→| `Skeleton.setupPose()` | + | `Skeleton.setBonesToSetupPose()` |→| `Skeleton.setupPoseBones()` | + | `Skeleton.setSlotsToSetupPose()` |→| `Skeleton.setupPoseSlots()` | + | Bone.setToSetupPose() |→| Bone.setupPose() | + | Slot.setToSetupPose() |→| Slot.setupPose() | + | IkConstraint.setToSetupPose() |→| IkConstraint.setupPose() | + - `Physics` enum moved from nested `Skeleton.Physics` to standalone `Physics` class + - `updateWorldTransform(Skeleton.Physics.update)` → `updateWorldTransform(Physics.update)` + - Timeline `apply()` methods now take `fromSetup`, `add`, `out`, and `appliedPose` parameters instead of `MixBlend` and `MixDirection` + - Removed `MixBlend` and `MixDirection` + - Removed `TrackEntry.holdPrevious` and internal interrupt alpha state. New `AnimationState` hold system automatically calculates the required state values + - Removed `TrackEntry.mixBlend`. Use `TrackEntry.additive` for additive blending + - `AnimationState.setCurrent()` renamed to `AnimationState.setTrack()`; `AnimationState.getCurrent()` is deprecated in favor of `AnimationState.getTrack()` + - Attachment `computeWorldVertices()` methods now take an additional `skeleton` parameter + - `MeshAttachment.getParentMesh()` / `setParentMesh()` renamed to `getSourceMesh()` / `setSourceMesh()` + - `RegionAttachment` and `MeshAttachment` now take a non-null `Sequence` in their constructors and use the new sequence attachment model + - `SkinEntry.name` renamed to `placeholderName` to better match Spine editor terminology + - `AttachmentLoader` methods now receive both the skin `placeholder` and resolved attachment `name`. + - `IkConstraintData.uniform` replaced by `IkConstraintData.scaleY`. `IkConstraint.apply()` methods now take `ScaleY` instead of a boolean `uniform` parameter + - `IkConstraintData.scaleY` and `ScaleY` renamed to `scaleYMode` and `ScaleYMode`. + - Renamed timeline constraint index methods to use unified `getConstraintIndex()` + +### Starling + +- **Additions** + - BoundsProvider Integration + - Integrated BoundsProvider system into Starling renderer + - Added `boundsProvider` public field for customizing bounds calculation strategy + - Added `calculateBounds()` method to recalculate bounds on demand + - Constructor now accepts optional third parameter `boundsProvider` (defaults to `SetupPoseBoundsProvider`) + - Simplified `getBounds()` implementation to use `BoundsProvider` instead of direct calculation + - Added physics position and rotation inheritance settings. + - Scale Integration + - Connected `SkeletonSprite.scale`, `scaleX`, and `scaleY` properties to `skeleton.scaleX/scaleY` values + - Setting scale properties now automatically updates skeleton scale and recalculates bounds + - Ensures consistent scaling behavior between display object and skeleton + +- **Breaking changes** + - Removed `getAnimationBounds()` method - replace with appropriate `BoundsProvider` implementation or create custom one + - `hitTest()` now uses `BoundsProvider` using cached bounds from `BoundsProvider` instead of iterating all slots and attachments, for accurate hit testing with animated skeletons, use `CurrentPoseBoundsProvider` and call `calculateBounds()` each frame or on click + - Changed `_state` to state (public field) + - Changed `_skeleton` to skeleton (public field) + +### Flixel + +- **Additions** + - BoundsProvider Integration + - Integrated `BoundsProvider` system matching Starling implementation + - Constructor now accepts optional third parameter `boundsProvider` (defaults to `SetupPoseBoundsProvider`) + - Added `boundsProvider` public field for customizing bounds calculation strategy + - Added `calculateBounds()` method to recalculate bounds on demand + - Added `bounds` property to get the bounds coordinates + - Added physics position and rotation inheritance settings. +- **Breaking changes** + - `SkeletonSprite` now extends `FlxTypedGroup` instead of FlxObject. This was necessary because `FlxObject` bounding/hitbox is always connected to its position and size and cannot be offset + - This eables proper bounds handling independent of position + - Added methods and properties to maintain FlxObject-like API despite extending FlxTypedGroup + - Removed `getAnimationBounds()` method - replace with appropriate `BoundsProvider` implementation + - Removed `setBoundingBox()` method - use `BoundsProvider` features instead + +## Java + +- **Additions** + - Added `Slider` and `SliderData` classes for slider constraints + - Reworked AnimationState hold system. Replaced `MixBlend`/`MixDirection` in timeline `apply()` with `boolean fromSetup, boolean add, boolean out`. The new bitmask-based hold system prevents dipping during crossfades without requiring `holdPrevious`. + - Added `Timeline.getAdditive()` and `Timeline.getInstant()` to query timeline blending capabilities. + - Added `TrackEntry.getAdditive()` / `TrackEntry.setAdditive()` for additive blending per track entry. + - Renamed `Skin.SkinEntry.getName()` to `getPlaceholderName()`. All `Skin` methods now use `placeholderName` parameter names. + +- **Breaking changes (since previous 4.3 beta)** + - `TrackEntry.getHoldPrevious()` / `setHoldPrevious()` removed. + - `TrackEntry.getMixBlend()` / `setMixBlend()` removed. Use `TrackEntry.getAdditive()` / `setAdditive()` for additive blending. + - `MixBlend` and `MixDirection` enums removed from `Animation`. + - Timeline `apply()` signature changed: `MixBlend blend, MixDirection direction` replaced with `boolean fromSetup, boolean add, boolean out`. + - `Animation.apply()` signature changed to match. + - `CurveTimeline1.getRelativeValue()`, `getAbsoluteValue()`, `getScaleValue()` signatures changed. + - `Skin.SkinEntry.getName()` renamed to `getPlaceholderName()`. + - Added `SliderTimeline` and `SliderMixTimeline` for animating sliders + - Added new pose system with `BoneLocal`, `BonePose`, and related classes + - Added `Pose`, `Posed`, and `PosedActive` base classes for unified pose management + - Added `ConstraintTimeline` interface for unified constraint timeline indexing + - Added `Animation.getBones()` to get bone indices used by an animation + - Added `Skeleton` methods `getGravityX()`, `getGravityY()`, `getWindX()`, `getWindY()` to allow rotating physics force directions + - Added `SequenceTimeline` for sequence animation + - Added `allowMissingRegions` parameter to `AtlasAttachmentLoader` constructor to support skeletons exported with per-skin atlases + +- **Breaking changes** + - `Bone` now extends `PosedActive` with separate pose, constrained, and applied states + - `Bone` local transform methods moved to `bone.getPose()`: + |||| + |---------------|-|-------------| + | bone.getX() |→| bone.getPose().getX() | + | bone.getY() |→| bone.getPose().getY() | + | bone.getRotation() |→| bone.getPose().getRotation() | + | bone.getScaleX() |→| bone.getPose().getScaleX() | + | bone.getScaleY() |→| bone.getPose().getScaleY() | + | bone.getShearX() |→| bone.getPose().getShearX() | + | bone.getShearY() |→| bone.getPose().getShearY() | + | bone.setX(value) |→| bone.getPose().setX(value) | + | bone.setY(value) |→| bone.getPose().setY(value) | + | bone.setRotation(value) |→| bone.getPose().setRotation(value) | + | bone.setScaleX(value) |→| bone.getPose().setScaleX(value) | + | bone.setScaleY(value) |→| bone.getPose().setScaleY(value) | + | bone.setShearX(value) |→| bone.getPose().setShearX(value) | + | bone.setShearY(value) |→| bone.getPose().setShearY(value) | + - `Bone` world and applied transform methods moved to `bone.getAppliedPose()`: + |||| + |---------------------|-|--------------------| + | bone.getAX() |→| bone.getAppliedPose().getX() | + | bone.getAY() |→| bone.getAppliedPose().getY() | + | bone.getARotation() |→| bone.getAppliedPose().getRotation() | + | bone.getAScaleX() |→| bone.getAppliedPose().getScaleX() | + | bone.getAScaleY() |→| bone.getAppliedPose().getScaleY() | + | bone.getAShearX() |→| bone.getAppliedPose().getShearX() | + | bone.getAShearY() |→| bone.getAppliedPose().getShearY() | + | bone.getWorldX() |→| bone.getAppliedPose().getWorldX() | + | bone.getWorldY() |→| bone.getAppliedPose().getWorldY() | + | bone.getWorldRotationX() |→| bone.getAppliedPose().getWorldRotationX() | + | bone.getWorldRotationY() |→| bone.getAppliedPose().getWorldRotationY() | + - `Bone` no longer provides a `getSkeleton()` method, constructor no longer takes a `skeleton` parameter + - `Slot` methods moved to `slot.getAppliedPose()`: + |||| + |-----------------------|-|-----------------------------| + | slot.getAttachment() |→| slot.getAppliedPose().getAttachment() | + | slot.setAttachment(value) |→| slot.getAppliedPose().setAttachment(value) | + | slot.getDeform() |→| slot.getAppliedPose().getDeform() | + | slot.setDeform(value) |→| slot.getAppliedPose().setDeform(value) | + | slot.getSequenceIndex() |→| slot.getAppliedPose().getSequenceIndex() | + | slot.setSequenceIndex(value) |→| slot.getAppliedPose().setSequenceIndex(value) | + - `Constraint` methods moved to `constraint.getPose()`: + |||| + |-----------------------------|-|-----------------------| + | ikConstraint.getMix() |→| ikConstraint.getPose().getMix() | + | ikConstraint.setMix(value) |→| ikConstraint.getPose().setMix(value) | + | ikConstraint.getSoftness() |→| ikConstraint.getPose().getSoftness() | + | ikConstraint.setSoftness(value) |→| ikConstraint.getPose().setSoftness(value) | + | ikConstraint.getBendDirection() |→| ikConstraint.getPose().getBendDirection() | + | ikConstraint.setBendDirection(value) |→| ikConstraint.getPose().setBendDirection(value) | + | ikConstraint.getCompress() |→| ikConstraint.getPose().getCompress() | + | ikConstraint.setCompress(value) |→| ikConstraint.getPose().setCompress(value) | + | ikConstraint.getStretch() |→| ikConstraint.getPose().getStretch() | + | ikConstraint.setStretch(value) |→| ikConstraint.getPose().setStretch(value) | + + |||| + |------------------------------------------|-|--------------------------------------------------| + | transformConstraint.getMixRotate() |→| transformConstraint.getPose().getMixRotate() | + | transformConstraint.setMixRotate(value) |→| transformConstraint.getPose().setMixRotate(value) | + | transformConstraint.getMixX() |→| transformConstraint.getPose().getMixX() | + | transformConstraint.setMixX(value) |→| transformConstraint.getPose().setMixX(value) | + | transformConstraint.getMixY() |→| transformConstraint.getPose().getMixY() | + | transformConstraint.setMixY(value) |→| transformConstraint.getPose().setMixY(value) | + | transformConstraint.getMixScaleX() |→| transformConstraint.getPose().getMixScaleX() | + | transformConstraint.setMixScaleX(value) |→| transformConstraint.getPose().setMixScaleX(value) | + | transformConstraint.getMixScaleY() |→| transformConstraint.getPose().getMixScaleY() | + | transformConstraint.setMixScaleY(value) |→| transformConstraint.getPose().setMixScaleY(value) | + | transformConstraint.getMixShearY() |→| transformConstraint.getPose().getMixShearY() | + | transformConstraint.setMixShearY(value) |→| transformConstraint.getPose().setMixShearY(value) | + + |||| + |-------------------------------------|-|-----------------------------------------------| + | pathConstraint.getPosition() |→| pathConstraint.getPose().getPosition() | + | pathConstraint.setPosition(value) |→| pathConstraint.getPose().setPosition(value) | + | pathConstraint.getSpacing() |→| pathConstraint.getPose().getSpacing() | + | pathConstraint.setSpacing(value) |→| pathConstraint.getPose().setSpacing(value) | + | pathConstraint.getMixRotate() |→| pathConstraint.getPose().getMixRotate() | + | pathConstraint.setMixRotate(value) |→| pathConstraint.getPose().setMixRotate(value) | + | pathConstraint.getMixX() |→| pathConstraint.getPose().getMixX() | + | pathConstraint.setMixX(value) |→| pathConstraint.getPose().setMixX(value) | + | pathConstraint.getMixY() |→| pathConstraint.getPose().getMixY() | + | pathConstraint.setMixY(value) |→| pathConstraint.getPose().setMixY(value) | + + |||| + |------------------------------------------|-|---------------------------------------------------| + | physicsConstraint.getMix() |→| physicsConstraint.getPose().getMix() | + | physicsConstraint.setMix(value) |→| physicsConstraint.getPose().setMix(value) | + | physicsConstraint.getGravity() |→| physicsConstraint.getPose().getGravity() | + | physicsConstraint.setGravity(value) |→| physicsConstraint.getPose().setGravity(value) | + | physicsConstraint.getStrength() |→| physicsConstraint.getPose().getStrength() | + | physicsConstraint.setStrength(value) |→| physicsConstraint.getPose().setStrength(value) | + | physicsConstraint.getDamping() |→| physicsConstraint.getPose().getDamping() | + | physicsConstraint.setDamping(value) |→| physicsConstraint.getPose().setDamping(value) | + | physicsConstraint.getMassInverse() |→| physicsConstraint.getPose().getMassInverse() | + | physicsConstraint.setMassInverse(value) |→| physicsConstraint.getPose().setMassInverse(value) | + | physicsConstraint.getWind() |→| physicsConstraint.getPose().getWind() | + | physicsConstraint.setWind(value) |→| physicsConstraint.getPose().setWind(value) | + - `ConstraintData` methods moved to `constraintData.getSetupPose()`: + |||| + |-----|-|-----| + | ikConstraintData.getMix() |→| ikConstraintData.getSetupPose().getMix() | + | ...| |...| + + - `SkeletonData` now provides a single `ConstraintData` list `getConstraints()` instead of separate lists per constraint type + |||| + |-----|-|-----| + | SkeletonData.getIkConstraints() |→| Filter SkeletonData.getConstraints() for IkConstraintData instances | + | SkeletonData.getTransformConstraints() |→| Filter SkeletonData.getConstraints() for TransformConstraintData instances | + | SkeletonData.getPathConstraints() |→| Filter SkeletonData.getConstraints() for PathConstraintData instances | + | SkeletonData.getPhysicsConstraints() |→| Filter SkeletonData.getConstraints() for PhysicsConstraintData instances | + - `SkeletonData` now provides unified `findConstraint()` method with Class parameter: + |||| + |-----|-|-----| + | SkeletonData.findIkConstraint(name) |→| SkeletonData.findConstraint(name, IkConstraintData.class) | + | SkeletonData.findTransformConstraint(name) |→| SkeletonData.findConstraint(name, TransformConstraintData.class) | + | SkeletonData.findPathConstraint(name) |→| SkeletonData.findConstraint(name, PathConstraintData.class) | + | SkeletonData.findPhysicsConstraint(name) |→| SkeletonData.findConstraint(name, PhysicsConstraintData.class) | + - Renamed setup pose methods: + |||| + |-----|-|-----| + | `Skeleton.setToSetupPose()` |→| `Skeleton.setupPose()` | + | `Skeleton.setBonesToSetupPose()` |→| `Skeleton.setupPoseBones()` | + | `Skeleton.setSlotsToSetupPose()` |→| `Skeleton.setupPoseSlots()` | + | Bone.setToSetupPose() |→| Bone.setupPose() | + | Slot.setToSetupPose() |→| Slot.setupPose() | + | IkConstraint.setToSetupPose() |→| IkConstraint.setupPose() | + - `Physics` enum moved from nested `Skeleton.Physics` to standalone class `Physics` + - `updateWorldTransform(Skeleton.Physics.update)` → `updateWorldTransform(Physics.update)` + - Timeline `apply()` methods now take an additional `appliedPose` parameter + - Attachment `computeWorldVertices()` methods now take an additional `skeleton` parameter + - Renamed timeline constraint index methods to use unified `getConstraintIndex()` + - Reorganized timeline class hierarchy with `BoneTimeline1`, `BoneTimeline2`, and `SlotCurveTimeline` base classes + +### libGDX + +- **Breaking changes** + - Updated to use new pose system from Java runtime + +- **Bug fixes** + - Updated the Gradle wrapper and fixed the headless test fat jar task to build included libgdx runtime classpath artifacts before packaging. + - Gradle builds now delete stale Eclipse `bin/` output before compiling so removed classes don't linger on Java headless test classpaths. + - Updated the libGDX dependency from `1.14.1-SNAPSHOT` to the released `1.14.1`. + - Fixed `TwoColorPolygonBatch` ignoring the configured maximum vertex count. + - Improved clipping performance by computing barycentric data lazily and reusing edge side tests. + - Fixed binary skeleton loading from `FileHandle` to use buffered I/O, avoiding slow per-byte file reads. + +### Android + +- **Breaking changes** + - Updated to use new Java runtime with all breaking changes above + +- **Bug fixes** + - Updated the Android atlas attachment loader to match the current `AttachmentLoader` method signatures. + - Updated the Android examples to use `AnimationState.getTrack()` instead of the removed `getCurrent()` API. + - Updated the libGDX dependency from `1.14.1-SNAPSHOT` to the released `1.14.1`. + - Updated the bundled spine-libgdx release with the `TwoColorPolygonBatch` max vertices fix and clipping performance improvements. + - Fixed large binary skeleton files taking a long time to load from files by buffering spine-libgdx file reads. + +## Swift + +- **Additions** + - Added `Slider` and `SliderData` classes for slider constraints + - Added `SliderTimeline` and `SliderMixTimeline` for animating sliders + - Added new pose system with `BoneLocal`, `BonePose`, and related classes + - Added `Pose`, `Posed`, and `PosedActive` base classes for unified pose management + +- **Breaking changes** + - The Swift runtime is now fully auto-generated from the C runtime, maintaining the full C++ type hierarchy with proper nullability annotations + - All properties are now exposed as getters and setters instead of methods + - Event setup payloads now live on `EventData.setupPose` instead of directly on `EventData` + - API changes to match C++ naming conventions: + - `AnimationState.setAnimationByName()` → `AnimationState.setAnimation()` + - `AnimationState.addAnimationByName()` → `AnimationState.addAnimation()` + - `AnimationState.getCurrent()` → `AnimationState.getCurrent()` + - `Skeleton.findSlot(slotName:)` → `Skeleton.findSlot()` + - `Skeleton.setToSetupPose()` → `Skeleton.setupPose()` + - `Skeleton.setBonesToSetupPose()` → `Skeleton.setupPoseBones()` + - `Skeleton.setSlotsToSetupPose()` → `Skeleton.setupPoseSlots()` + - Timeline `apply()` methods now take an additional `appliedPose` parameter + +### iOS + +- **Breaking changes** + - Updated to use the new auto-generated Swift runtime with all the Swift API changes above + - Generated Swift bindings now use `BonePose` for bone setup and unconstrained pose accessors to match spine-cpp. + - Generated Swift bindings now expose event setup payloads via `EventData.setupPose` instead of directly on `EventData`. + - Generated Swift bindings now construct `Animation` with only a name, and setting timelines also requires the animation's bone indices. + +## TypeScript/JavaScript + +- **Additions** + - Added `Slider` and `SliderData` classes for slider constraints + - Added `SliderTimeline` and `SliderMixTimeline` for animating sliders + - Added new pose system with `BoneLocal`, `BonePose`, and related classes + - Added `Pose`, `Posed`, and `PosedActive` base classes for unified pose management + - Added `ConstraintTimeline` interface for unified constraint timeline indexing + - Added `Animation.getBones()` to get bone indices used by an animation + - Added `Skeleton` properties `windX`, `windY`, `gravityX`, `gravityY` to allow rotating physics force directions + - Added `SequenceTimeline` for sequence animation + - Added `allowMissingRegions` parameter to `AtlasAttachmentLoader` constructor to support skeletons exported with per-skin atlases + - Added `TextureLoader` type with optional `pma?: boolean` parameter to `AssetManagerBase`. `AssetManagerBase` now tracks and passes PMA metadata from atlas pages to texture loaders, allowing runtimes to automatically premultiply textures on upload + - Added `SkeletonRendererCore` class to reduce complexity of runtime-specific render code + - Linked meshes can now inherit deform and sequence timelines from source meshes in different slots + - Added `Attachment.timelineSlots` and `Attachment.isTimelineActive()` for attachment timeline propagation across linked meshes + - Added `DrawOrderFolderTimeline` for animating draw order folders + - Added `Timeline.additive` and `Timeline.instant` to query timeline blending capabilities + - Added `TrackEntry.additive` to control additive blending per track entry + - Added `TrackEntry.mixInterpolation` and `Interpolation` helpers for non-linear AnimationState mixes + - Added support for passing `null` as the attachment name to `Skeleton.setAttachment()` + - Ported the latest parser fixes from spine-libgdx, including the 4.3 path constraint flag fix and the weighted mesh binary vertex allocation/count fix + - Ported the latest additive timeline updates and alpha/RGB timeline flicker fixes from spine-libgdx + - Ported the AnimationState additive/hold rework from spine-libgdx. `MixBlend` and `MixDirection` are no longer used by timelines. The new system uses `fromSetup`, `add`, and `out` parameters and automatically calculates the required hold state values + - Ported the Skin placeholder name rename from spine-libgdx. `SkinEntry.name` renamed to `placeholderName` to better match Spine editor terminology + - Ported the sequence attachment refactor from spine-libgdx. `Sequence` now precomputes per-frame regions, UVs, and region offsets, and `RegionAttachment` / `MeshAttachment` now mirror the libgdx implementation + - Ported the latest clipping runtime changes from spine-libgdx, including convex and inverse clipping support and the inverse clipping crash fix + - Added `ClippingAttachment.convex` and `ClippingAttachment.inverse` + - Added `Animation.color` for the animation color as it was in Spine when nonessential data is exported + - Added `BoneData` icon size and rotation accessors for nonessential editor data + - Added `ScaleY` enum and `IkConstraintData.scaleY` to control how IK compress/stretch changes `BonePose.scaleY`, including volume preservation + - Fixed `SkeletonData` default FPS and missing `PathAttachment` initialization + - Fixed reverse IK bend positive logic and transform constraint/slider scaling issues + +- **Bug fixes** + - Fixed attachment timelines so hidden setup-pose attachments remain hidden while mixing out, preserving deform behavior. + +- **Breaking changes** + - `Bone` now extends `PosedActive` with separate pose, constrained, and applied states + - `Bone` local transform properties moved to `bone.getPose()`: + |||| + |-------------------------|-|-----------------------------| + | bone.x |→| bone.getPose().x | + | bone.y |→| bone.getPose().y | + | bone.rotation |→| bone.getPose().rotation | + | bone.scaleX |→| bone.getPose().scaleX | + | bone.scaleY |→| bone.getPose().scaleY | + | bone.shearX |→| bone.getPose().shearX | + | bone.shearY |→| bone.getPose().shearY | + - `Bone` world and applied transform properties moved to `bone.getAppliedPose()`: + |||| + |---------------------------|-|-------------------------------------| + | bone.ax |→| bone.getAppliedPose().x | + | bone.ay |→| bone.getAppliedPose().y | + | bone.arotation |→| bone.getAppliedPose().rotation | + | bone.ascaleX |→| bone.getAppliedPose().scaleX | + | bone.ascaleY |→| bone.getAppliedPose().scaleY | + | bone.ashearX |→| bone.getAppliedPose().shearX | + | bone.ashearY |→| bone.getAppliedPose().shearY | + | bone.worldX |→| bone.getAppliedPose().worldX | + | bone.worldY |→| bone.getAppliedPose().worldY | + - `Bone` no longer provides a `skeleton` property, constructor no longer takes a `skeleton` parameter + - `Slot` properties moved to `slot.getAppliedPose()`: + |||| + |---------------------------|-|-------------------------------------| + | slot.attachment |→| slot.getAppliedPose().attachment | + | slot.deform |→| slot.getAppliedPose().deform | + | slot.sequenceIndex |→| slot.getAppliedPose().sequenceIndex | + - `Constraint` properties moved to `constraint.getPose()`: + |||| + |---------------------------------|-|----------------------------------------| + | ikConstraint.mix |→| ikConstraint.getPose().mix | + | ikConstraint.softness |→| ikConstraint.getPose().softness | + | ikConstraint.bendDirection |→| ikConstraint.getPose().bendDirection | + | ikConstraint.compress |→| ikConstraint.getPose().compress | + | ikConstraint.stretch |→| ikConstraint.getPose().stretch | + + |||| + |-------------------------------------|-|---------------------------------------| + | transformConstraint.mixRotate |→| transformConstraint.getPose().mixRotate | + | transformConstraint.mixX |→| transformConstraint.getPose().mixX | + | transformConstraint.mixY |→| transformConstraint.getPose().mixY | + | transformConstraint.mixScaleX |→| transformConstraint.getPose().mixScaleX | + | transformConstraint.mixScaleY |→| transformConstraint.getPose().mixScaleY | + | transformConstraint.mixShearY |→| transformConstraint.getPose().mixShearY | + + |||| + |---------------------------------|-|------------------------------------| + | pathConstraint.position |→| pathConstraint.getPose().position | + | pathConstraint.spacing |→| pathConstraint.getPose().spacing | + | pathConstraint.mixRotate |→| pathConstraint.getPose().mixRotate | + | pathConstraint.mixX |→| pathConstraint.getPose().mixX | + | pathConstraint.mixY |→| pathConstraint.getPose().mixY | + + |||| + |-------------------------------------|-|---------------------------------------| + | physicsConstraint.mix |→| physicsConstraint.getPose().mix | + | physicsConstraint.gravity |→| physicsConstraint.getPose().gravity | + | physicsConstraint.strength |→| physicsConstraint.getPose().strength | + | physicsConstraint.damping |→| physicsConstraint.getPose().damping | + | physicsConstraint.massInverse |→| physicsConstraint.getPose().massInverse | + | physicsConstraint.wind |→| physicsConstraint.getPose().wind | + - `ConstraintData` properties moved to `constraintData.setupPose`: + |||| + |-----|-|-----| + | ikConstraintData.mix |→| ikConstraintData.setupPose.mix | + | ...| |...| + + - `SkeletonData` now provides a single `ConstraintData` list `constraints` instead of separate lists per constraint type + |||| + |-----|-|-----| + | skeletonData.ikConstraints |→| Filter skeletonData.constraints for IkConstraintData instances | + | skeletonData.transformConstraints |→| Filter skeletonData.constraints for TransformConstraintData instances | + | skeletonData.pathConstraints |→| Filter skeletonData.constraints for PathConstraintData instances | + | skeletonData.physicsConstraints |→| Filter skeletonData.constraints for PhysicsConstraintData instances | + - `SkeletonData` now provides unified `findConstraint()` method with type constructor parameter: + |||| + |-----|-|-----| + | skeletonData.findIkConstraint(name) |→| skeletonData.findConstraint(name, IkConstraintData) | + | skeletonData.findTransformConstraint(name) |→| skeletonData.findConstraint(name, TransformConstraintData) | + | skeletonData.findPathConstraint(name) |→| skeletonData.findConstraint(name, PathConstraintData) | + | skeletonData.findPhysicsConstraint(name) |→| skeletonData.findConstraint(name, PhysicsConstraintData) | + - Renamed setup pose methods: + |||| + |-----|-|-----| + | `Skeleton.setToSetupPose()` |→| `Skeleton.setupPose()` | + | `Skeleton.setBonesToSetupPose()` |→| `Skeleton.setupPoseBones()` | + | `Skeleton.setSlotsToSetupPose()` |→| `Skeleton.setupPoseSlots()` | + | Bone.setToSetupPose() |→| Bone.setupPose() | + | Slot.setToSetupPose() |→| Slot.setupPose() | + | IkConstraint.setToSetupPose() |→| IkConstraint.setupPose() | + - `Physics` enum moved from nested `Skeleton.Physics` to standalone `Physics` export + - `updateWorldTransform(Skeleton.Physics.update)` → `updateWorldTransform(Physics.update)` + - Timeline `apply()` methods now take `fromSetup`, `add`, `out`, and `appliedPose` parameters instead of `MixBlend` and `MixDirection` + - Removed `MixBlend` and `MixDirection` + - Removed `TrackEntry.holdPrevious` and internal interrupt alpha state. New `AnimationState` hold system automatically calculates the required state values + - Removed `TrackEntry.mixBlend`. Use `TrackEntry.additive` for additive blending + - `AnimationState.setCurrent()` renamed to `AnimationState.setTrack()`; `AnimationState.getCurrent()` is deprecated in favor of `AnimationState.getTrack()` + - Attachment `computeWorldVertices()` methods now take an additional `skeleton` parameter + - `MeshAttachment.getParentMesh()` / `setParentMesh()` renamed to `getSourceMesh()` / `setSourceMesh()` + - `RegionAttachment` and `MeshAttachment` now take a non-null `Sequence` in their constructors and use the new sequence attachment model + - `EventData` no longer stores `intValue`, `floatValue`, `stringValue`, `volume`, and `balance` directly. Use `eventData.setupPose` to access the setup pose `Event` which provides these properties instead + - `SkinEntry.name` renamed to `placeholderName` to better match Spine editor terminology + - `AttachmentLoader` methods now receive both the skin `placeholder` and resolved attachment `name`. + - `IkConstraintData.uniform` replaced by `IkConstraintData.scaleY`. `IkConstraint.apply()` methods now take `ScaleY` instead of a boolean `uniform` parameter + - `IkConstraintData.scaleY` and `ScaleY` renamed to `scaleYMode` and `ScaleYMode`. + - Renamed timeline constraint index methods to use unified `getConstraintIndex()` + - API changes to match reference runtime naming conventions: + - `addAnimationWith()` → `addAnimation()` + - `setAnimationWith()` → `setAnimation()` + - `setMixWith()` → `setMix()` + - `setSkinByName()` → `setSkin()` + - `getAttachmentByName()` → `getAttachment()` + +### WebGL backend + +- **Breaking changes** + - Updated to use new TypeScript/JavaScript runtime + - `GLTexture` constructor now requires `pma: boolean` parameter (automatically read from atlas page metadata) + - Removed `GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL` static property + - `SkeletonRenderer` and `SkeletonDebugRenderer` no longer have `premultipliedAlpha` property - PMA is handled automatically + - `SceneRenderer.drawSkeleton()` and `drawSkeletonDebug()` no longer take `premultipliedAlpha` parameter + - `PolygonBatcher.setBlendMode()` no longer takes `premultipliedAlpha` parameter + - `LoadingScreen` no longer accepts PMA parameters + +### Canvas backend + +- **Breaking changes** + - Updated to use new TypeScript/JavaScript runtime + +### CanvasKit backend + +- **Breaking changes** + - Updated to use new TypeScript/JavaScript runtime + - Simplified rendering implementation + +### Three.js backend + +- **Additions** + - Added a React Three Fiber example for using `SkeletonMesh` with R3F's `` and `useFrame` + - Added support for Three.js versions from `0.162.0` up to `0.184.x` + - Added physics position and rotation inheritance settings. + +- **Breaking changes** + - Updated to use new TypeScript/JavaScript runtime + - `AssetManager` constructor no longer takes `pma` parameter - PMA is handled automatically + +### Player + +- **Additions** + - Added support for multiple skins in the skin selector + - Added `debug` support as a boolean option + +- **Fixes** + - Fixed resize mode regressions + - The progress bar is now shown only when hovering the bottom bar and can be dragged outside its area + +- **Breaking changes** + - Updated to use new TypeScript/JavaScript runtime + - Removed `premultipliedAlpha` option from `SpinePlayerConfig` - PMA is now handled automatically + +### Pixi v7 + +- **Additions** + - Added static `createOptions` method for Spine initialization config to simplify subclassing + - Added `allowMissingRegions` parameter to game object factory + - Added physics position and rotation inheritance settings. + +- **Breaking changes** + - Updated to use new TypeScript/JavaScript runtime + - Deprecated `from()` method in favor of constructor accepting both `SpineOptions` and `SpineFromOptions` + - Removed deprecated methods + +### Pixi v8 + +- **Additions** + - Added static `createOptions` method for Spine initialization config to simplify subclassing + - Added `allowMissingRegions` parameter to game object factory + - Added physics position and rotation inheritance settings. + - Restored control bones example + +- **Fixes** + - Fixed clipping regressions + +- **Breaking changes** + - Updated to use new TypeScript/JavaScript runtime + - Deprecated `from()` method in favor of constructor accepting both `SpineOptions` and `SpineFromOptions` + +### Phaser v3 + +- **Additions** + - Added physics position and rotation inheritance settings. + +- **Breaking changes** + - Updated to use new TypeScript/JavaScript runtime + - `SpinePlugin.spineAtlas()` loader no longer takes `premultipliedAlpha` parameter - PMA is handled automatically + - `SpinePlugin.createSkeleton()` no longer takes `premultipliedAlpha` parameter + +### Phaser v4 + +- **Additions** + - Added physics position and rotation inheritance settings. + +- **Breaking changes** + - Updated to use new TypeScript/JavaScript runtime + - `SpinePlugin.spineAtlas()` loader no longer takes `premultipliedAlpha` parameter - PMA is handled automatically + - `SpinePlugin.createSkeleton()` no longer takes `premultipliedAlpha` parameter + +### Web Components + +- **Breaking changes** + - Updated to use new TypeScript/JavaScript runtime + - Updated skeleton and overlay component implementations + - Removed `pma` property from `SpineWebComponentSkeleton` - PMA is handled automatically + +## Unreal Engine + +- **Bug fixes** + - Fixed Spine atlas and skeleton data reimport actions and automatic source change detection in recent Unreal Engine versions. + - Fixed editor crashes caused by parsing stale skeleton data while loading assets. Skeleton metadata is now validated and cached during import and reimport. + +# 4.2 + +## C + +- **Additions** + - Added physics support + - Added `spPhysicsConstraintTimeline` and `spPhysicsConstraintResetTimeline` + - Added `spPhysics` to be passed to `spSkeleton_updateWorldTransform()` + - Added `spSkeletonData_findPhysicsConstraint()` to query a physics constraint by name + - Added `spSkeleton_findPhysicsConstraint()` to query a physics constraint by name + - Added `spSkeleton_physicsTranslate()` to translate all physics constraints by some distances in the skeleton coordinate system + - Added `spSkeleton_physicsRotate()` to rotate all physics constraints by some distances in the skeleton coordinate system + - Added `spSkeleton::time` to keep track of time for physics simulations + - See also breaking changes for `spSkeleton_updateWorldTransform()` and the requirement to call `spSkeleton_update()` to advance + pyhsics each frame. + - Added `spInheritTimeline` + - Added [`spTrackEntry::alphaAttachmentThreshold`](http://esotericsoftware.com/spine-api-reference#TrackEntry-alphaAttachmentThreshold) + - Removed `const` qualifiers where appropriate + - Added `spTrackEntry_setMixDuration()` to set the mix duration in conjunction with a delay + - Added `spTrackEntry_wasApplied()` to check if the entry has been applied + - Added `spBone_worldToParent()` to transform coordinates from world space to the parent space of a bone + - Added `spBone_localToParent()` to transform coordinates from a bone's local space to its parent space + - Added non essential fields `icon` and `visible` to `spBoneData` + - Added non essential fields `path` and `visible` to `spSlotData` +- **Breaking changes** + - Renamed `spTrackEntry::attachmentThreshold` to `spTrackEntry::mixAttachmentThreshold` + - Renamed `spTrackEntry::drawOrderThreshold` to `spTrackEntry::mixDrawOrdertThreshold` + - Renamed `spTransformMode` to `spInherit` and all `SP_TRANSFORMMODE_*` enums to `SP_INHERIT_*` + - Changed `spMeshAttachment::edges` from `int *` to `unsigned short *` + - You must call `spSkeleton_update(delta)` before calling `spSkeleton_updateWorldTransform()` if the frame time has advanced. This is needed to update physics accordingly + - `spSkeleton_updateWorldTransform()` takes an additional `spPhysics` parameter. See the `spPhysics` documentation for information on what the different enum values do + +### SFML + +- Added physics examples +- `SkeletonDrawable::update()` now takes an additional `spPhysics physics` parameter that specifies how physics should be updated + +### SDL + +- `spSkeletonDrawable_update()` now takes an additional `spPhysics physics` parameter that specifies how physics should be updated + +## C++ + +- Added physics support + - Added `PhysicsConstraintXXXTimeline` and `PhysicsConstraintResetTimeline` + - Added `Physics` to be passed to `Skeleton::updateWorldTransform()` + - Added `SkeletonData::findPhysicsConstraint()` and `SkeletonData::getPhysicsConstraints()` to query physics constraints + - Added `Skeleton::findPhysicsConstraint()` and `Skeleton::getPhysicsConstraints()` to query physics constraints + - Added `Skeleton::physicsTranslate()` to translate all physics constraints by some distances in the skeleton coordinate system + - Added `Skeleton::physicsRotate()` to rotate all physics constraints by some distances in the skeleton coordinate system + - Added `Skeleton::time` to keep track of time for physics simulations + - See also breaking changes for `Skeleton::updateWorldTransform()` and the requirement to call `Skeleton::update()` to advance + pyhsics each frame. +- Added `InheritTimeline` +- Added [`TrackEntry::_alphaAttachmentThreshold`](http://esotericsoftware.com/spine-api-reference#TrackEntry-alphaAttachmentThreshold) +- Added `TrackEntry::setMixDuration()` to set the mix duration in conjunction with a delay +- Added `TrackEntry::wasApplied()` to check if the entry has been applied +- Added `Bone::worldToParent()` to transform coordinates from world space to the parent space of a bone +- Added `Bone::localToParent()` to transform coordinates from a bone's local space to its parent space +- Added non essential fields `icon` and `visible` to `BoneData` +- Added non essential fields `path` and `visible` to `SlotData` +- Added `setToSetupPose()` to all contraint classes +- **Breaking changes** + - Renamed `TrackEntry::attachmentThreshold` to `TrackEntry::mixAttachmentThreshold` + - Renamed `TrackEntry::drawOrderThreshold` to `TrackEntry::mixDrawOrdertThreshold` + - Renamed `TransformMode` to `Inherit` and all `TransformMode_*` enums to `Inherit_*` + - You must call `Skeleton::update(delta)` before calling `Skeleton::updateWorldTransform()` if the frame time has advanced. This is needed to update physics accordingly + - `Skeleton::updateWorldTransform()` takes an additional `Physics` parameter. See the `Physics` documentation for information on what the different enum values do + - All `Updatable` sub-classes like `Bone` and constraints now take an additional `Physics` parameter for their `update()` methods + +### Cocos2d-x + +- Added physics example +- Improved build system and build documentation + +### SFML + +- `SkeletonDrawable::update()` now takes an additional `Physics physics` parameter that specifies how physics should be updated + +### SDL + +- `SkeletonDrawable::update()` now takes an additional `Physics physics` parameter that specifies how physics should be updated + +### UE4 + +- **Breaking**: Renamed runtime folder from `spine-ue4` to `spine-ue` +- **Breaking**: Renamed plugin `SpinePlugin`. You must update your project's `Build.cs` file accordingly +- **Breaking**: Starting with Unreal Engine 5.3 imported `.skel`/`.json` and `.atlas` files in the same folder must NOT have a common prefix. E.g. `skeleton.json` and `skeleton.atlas` will not work. Make sure to rename at least one of the two files so there is no prefix collision, e.g. `skeleton-data.json` and `skeleton.atlas`. +- Added compatibility with UE 5.3 +- Added more example maps +- Added blueprint-callable methods `PhysicsTranslate()`, `PhysicsRotate()` and `ResetPhysicsConstraints()` (which will reset all physics constraints in the skeleton) to `SpineSkeletonComponent` and `SpineWidget`. + +### Godot + +- **Breaking**: Renamed `TrackEntry.set_attachment_threshold` and `TrackEntry.get_attachment_threshold` to `TrackEntry.set_mix_attachment_threshold` and `TrackEntry.get_mix_attachment_threshold` +- **Breaking**: Renamed `TrackEntry.set_draw_order_threshold` and `TrackEntry.get_draw_order_threshold` to `TrackEntry.set_mix_draw_order_threshold` and `TrackEntry.get_mix_draw_order_threshold` +- **BReaking**: `SpineSkeleton.update_world_transform` takes an additional `physics` parameter that specifies how physics should be updated +- Added compatibility for Godot 4.1, 4.2 and C#, see builds at [https://esotericsoftware.com/spine-godot](https://esotericsoftware.com/spine-godot) +- Added physics examples +- Added `SpineBone.world_to_parent` to transform coordinates from world space to the parent space of a bone +- Added `SpineBone.local_to_parent` to transform coordinates from a bone's local space to its parent space +- Physics support + - Added `SpineBone.get_inherit`/`SpineBone.set_inherit` + - Added `SpinePhysicsConstraint` and `SpinePhysicsConstraintData` + - Added `SpineSkeleton.update()` to advance the physics time + - ADded `SpineSkeleton.get_time`/`SpineSkeleton.set_time` to access the physics time + - Added `SpineSkeleton.physics_translate()` to translate all physics constraints by some distances in the skeleton coordinate system + - Added `SpineSkeleton.physics_rotate()` to rotate all physics constraints by some distances in the skeleton coordinate system + - Added `SpineSkeleotnDataResource.set_reference_scale`/`SpineSkeletonDataResource.get_reference_scale` to access the reference scale of the loaded skeleton data +- Added [`TrackEntry.set_alpha_attachment_threshold`](http://esotericsoftware.com/spine-api-reference#TrackEntry-alphaAttachmentThreshold) +- Added `TrackEntry.set_mix_duration_and_delay()` to set the mix duration in conjunction with a delay +- Added `TrackEntry::was_applied()` to check if the entry has been applied + +## C# + +- **Additions** + + - Added [`TrackEntry.AlphaAttachmentThreshold`](http://esotericsoftware.com/spine-api-reference#TrackEntry-alphaAttachmentThreshold). + +- **Breaking changes** + - Renamed `TrackEntry` `AttachmentThreshold` to `MixAttachmentThreshold`, renamed `DrawOrderThreshold` to `MixDrawOrderThreshold`. + - Changed signature of `Skeleton.UpdateWorldTransform()` to `UpdateWorldTransform(Skeleton.Physics physics)`. The default replacement for `skeleton.UpdateWorldTransform()` calls is `skeleton.UpdateWorldTransform(Skeleton.Physics.Update)`. If you are certain that a subsequent call to `skeleton.UpdateWorldTransform(Skeleton.Physics.Update)` follows in the same frame, you can pass `Skeleton.Physics.Pose` as argument instead of `Skeleton.Physics.Update`. + +### Unity + +- **Officially supported Unity versions are 2017.1-6000.1**. + +- **Additions** + + - `OnPostProcessVertices` callback parameter `MeshGeneratorBuffers` now provides access to `uv2Buffer` and `uv3Buffer` properties of `MeshGenerator`, automatically allocating buffers upon access if `tintBlack` is disabled. This allows for passing own vertex data to a shader on second and third uv channels. + - Added `Spine/SkeletonGraphic Grayscale` shader to provide a basic grayscale shader for SkeletonGraphic as well. SkeletonGraphic Material `SkeletonGraphicDefaultGrayscale` uses this shader and can be assigned at `SkeletonGraphic` components as usual. + - `SkeletonGraphic` now supports automatic scaling based on its `RectTransform` bounds. Automatic scaling can be enabled by setting the added `Layout Scale Mode` Inspector property to either `Width Controls Height`, `Height Controls Width`, `FitInParent` or `EnvelopeParent`. It is set to `None` by default to keep previous behaviour and avoid breaking existing projects. To modify the reference layout bounds, hit the additional `Edit Layout Bounds` toggle button to switch into edit mode, adjust the bounds or hit `Match RectTransform with Mesh`, and hit the button again when done adjusting. The skeleton will now be scaled accordingly to fit the reference layout bounds to the object's `RectTransform`. + - Added previously missing unlit URP 2D shader variant, available under `Universal Render Pipeline/2D/Spine/Skeleton`. + - Added support for light cookies at `Universal Render Pipeline/Spine/Sprite` shader. + - Timeline extension package: An additional Spine preferences parameter `Timeline` - `Default Mix Duration` has been added, setting newly added `SpineAnimationStateClip` clips accordingly, defaults to false. This Spine preferences parameter can be enabled to default to the previous behaviour before this update. + - Tint Black: Added support for [Tint Black](http://en.esotericsoftware.com/spine-slots#Tint-black) functionality at all Spine URP shaders (2D and 3D shaders) and at all standard pipeline `Spine/Sprite` shaders. This feature can be enabled via the `Tint Black` material parameter in the Inspector. Note: The URP Sprite shaders provided in the Spine URP Shaders extension UPM package require the latest version of the spine-unity runtime (package version 4.1.12, 2023-05-31 or newer) to display the added material parameters in the Inspector GUI. + - Added `SkeletonGraphic.MeshScale` property to allow access to calculated mesh scale. `MeshScale` is based on (1) Canvas pixels per unit, and (2) `RectTransform` bounds when using `Layout Scale Mode` other than `None` at `SkeletonGraphic` which scales the skeleton mesh to fit the parent `RectTransform` bounds accordingly. + - Added `updateSeparatorPartScale` property to `SkeletonGraphic` to let render separator parts follow the scale (lossy scale) of the `SkeletonGraphic` GameObject. Defaults to `false` to maintain existing behaviour. + - Added experimental `EditorSkeletonPlayer` component to allow Editor playback of the initial animation set at `SkeletonAnimation` or `SkeletonGraphic` components. Add this component to your skeleton GameObject to enable the in-editor animation preview. Allows configurations for continuous playback when selected, deselected, and alternative single-frame preview by setting `Fixed Track Time` to any value other than 0. Limitations: At skeletons with variable material count the Inspector preview may be too unresponsive. It is then recommended to disable the `EditorSkeletonPlayer` component (at the top of the Inspector) to make it responsive again, then you can disable `Play When Selected` and re-enable the component to preview playback only when deselected. + - Added example component `RenderCombinedMesh` to render a combined mesh of multiple meshes or submeshes. This is required by `OutlineOnly` shaders to render a combined outline when using `SkeletonRenderSeparator` or multiple atlas pages which would normally lead to outlines around individual parts. To add a combined outline to your SkeletenRenderer: + 1. Add a child GameObject and move it a bit back (e.g. position Z = 0.01). + 2. Add a `RenderCombinedMesh` component, provided in the `Spine Examples/Scripts/Sample Components` directory. + 3. Copy the original material, add _\_Outline_ to its name and set the shader to your outline-only shader like `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly` or `Spine/Outline/OutlineOnly-ZWrite`. + 4. Assign this _\_Outline_ material at the new child GameObject's `MeshRenderer` component. + If you are using `SkeletonRenderSeparator` and need to enable and disable the `SkeletonRenderSeparator` component at runtime, you can increase the `RenderCombinedMesh` `Reference Renderers` array by one and assign the `SkeletonRenderer` itself at the last entry after the parts renderers. Disabled `MeshRenderer` components will be skipped when combining the final mesh, so the combined mesh is automatically filled from the desired active renderers. + - Timeline extension package: Added static `EditorEvent` callback to allow editor scripts to react to animation events outside of play-mode. Register to the events via `Spine.Unity.Playables.SpineAnimationStateMixerBehaviour.EditorEvent += YourCallback;`. + - URP Shaders: Added `Depth Write` property to shaders `Universal Render Pipeline/Spine/Skeleton` and `Universal Render Pipeline/Spine/Skeleton Lit`. Defaults to false to maintain existing behaviour. + - Added `Animation Update` mode (called `UpdateTiming` in code) `In Late Update` for `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic`. This allows you to update the `SkeletonMecanim` skeleton in the same frame that the Mecanim Animator updated its state, which happens between `Update` and `LateUpdate`. + - URP Shaders: Added URP "Blend Mode" shader variants for both URP 3D and URP 2D renderers. They are listed under shader name "Universal Render Pipeline/Spine/Blend Modes/" and "Universal Render Pipeline/2D/Spine/Blend Modes/" respectively. + - URP Shaders: Added support for [Tint Black](http://en.esotericsoftware.com/spine-slots#Tint-black) functionality at "Blend Modes" Spine URP shaders (2D and 3D shaders). + - PhysicsConstraints: Skeleton GameObjects now automatically apply Transform translation and rotation to the skeleton's `PhysicsConstraints`. You can disable applying translation or rotation at the Skeleton component Inspector under `Advanced - Physics Inheritance` by setting `Position` to (0,0)and `Rotation` to 0, or by setting the properties `physicsPositionInheritanceFactor` to `Vector2.zero` and `physicsRotationInheritanceFactor` to `0` at the skeleton component via code. + - Added `Physics Constraints` example scene (located in `Spine Examples/Other Examples`) together with `celestial-circus` example skeleton assets. This scene demonstrates Transform movement automatically affecting physics constraints of a skeleton. + - PhysicsConstraints: Skeleton components now allow you to use relative instead of world-space Transform movement by assigning a Transform (typically the parent) to the new `Movement relative to` property. Leave this property at `null` (the default) to use world-space Transform movement for physics. + - PhysicsConstraints: Added Spine Preferences settings `Editor Instantiation` - `Physics Inheritance` - `Default Position` and `Default Rotation` to initialize skeletons physics settings with the desired Transform position and rotation inheritance factors when added to a scene via drag-and-drop. + - SkeletonGraphic: Added Tint Black blend mode shaders `Spine/SkeletonGraphic Tint Black Additive`, `Spine/SkeletonGraphic Tint Black Multiply` and `Spine/SkeletonGraphic Tint Black Screen`. + - SkeletonGraphic: Added pre-defined SkeletonGraphic material sets for main workflow parameters in folders `spine-unity/Materials` instead of requiring manual copies: + `SkeletonGraphic-PMATexture` containing materials for premultiplied-alpha texture workflow (`Straight Alpha Texture` disabled) and `SkeletonGraphic-StaightAlphaTexture` containing materials for straight alpha texture workflow (`Straight Alpha Texture` enabled). These directories contain a set of materials with `CanvasGroup Compatible` disabled for usage with `Advanced - PMA Vertex Color` enabled at the component. Each directory also provides a subdirectory `CanvasGroupCompatible` with materials with `CanvasGroup Compatible` enabled for usage with `CanvasGroup` alpha (requiring `Advanced - PMA Vertex Color` disabled at the component). + - SkeletonGraphic: Added auto-detect functionality for parameters `Advanced` - `Tint Black`, `CanvasGroup Compatible` and `PMA Vertex Color`. If unsure which settings are correct, hit the `Detect` button next to each parameter, in top to bottom order, or the `Detect Settings` to detect all three. Also added automatic material assignment via a `Detect Material` button in the `Advanced` section and a `Detect` button next to the `Material` property at the top of the component Inspector, as well as next to the `Blend Mode Materials` section when using multiple canvas renderers with blend modes. The suitable material is selected based on these three settings, combined with texture settings (PMA or straight alpha texture settings). If you receive incorrect results, likely your texture settings are incorrectly setup for your PMA or Straight alpha texture export settings. + - `SkeletonRenderTexture` example components now provide a `shaderPasses` parameter to customize which passes are rendered to the `RenderTexture`. It defaults to `-1` for all passes to keep the existing behaviour. You might want to set it to `0` to only render the first pass e.g. to avoid issues when using a URP shader at the original skeleton. + - `SkeletonGraphicRenderTexture` example component now also received a `quadMaterial` property, defaulting to the newly added Material asset `RenderQuadGraphicMaterial` which applies proper premultiplied-alpha blending of the render texture. The `quadMaterial` member variable was moved from `SkeletonRenderTexture` to the common base class `SkeletonRenderTextureBase`. + - All Spine Outline shaders, including the URP outline shader, now provide an additional parameter `Width in Screen Space`. Enable it to keep the outline width constant in screen space instead of texture space. Requires more expensive computations, so enable only where necessary. Defaults to `disabled` to maintain existing behaviour. + - Added support for BlendModeMaterials at runtime instantiation from files via an additional method `SkeletonDataAsset.SetupRuntimeBlendModeMaterials`. See example scene `Spine Examples/Other Examples/Instantiate from Script` for a usage example. + - SkeletonGraphic: You can now offset the skeleton mesh relative to the pivot via a newly added green circle handle. This allows you to e.g. frame only the face of a skeleton inside a masked frame. Previously offsetting the pivot downwards fails when `Layout Scale Mode` scales the mesh smaller and towards the pivot (e.g. the feet) and thus out of the frame. Now you can keep the pivot in the center of the `RectTransform` while offsetting only the mesh downwards, keeping the desired skeleton area (e.g. the face) centered while resizing. Moving the new larger green circle handle moves the mesh offset, while moving the blue pivot circle handle moves the pivot as usual. + - `Universal Render Pipeline/Spine/Skeleton` shader now performs proper alpha-testing when `Depth Write` is enabled, using the existing `Shadow alpha cutoff` parameter. + - `SkeletonRootMotion` components now provide a public `Initialize()` method which is automatically called when calling `skeletonAnimation.Initialize(true)` to update the necessary skeleton references. If a different root bone shall be used, be sure to set `skeletonRootMotion.rootMotionBoneName` before calling `skeletonAnimation.Initialize(true)`. + - Skeleton Mecanim: Added new `Mix Mode` `Match`. When selected, Spine animation weights are calculated to best match the provided Mecanim clip weights. This mix mode is recommended on any layer using blend tree nodes. + - URP Shaders: Added `ZWrite` variant of outline shader `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly ZWrite`. Suitable for e.g. depth of field (DoF) effect where writing to the depth buffer is required. Note that for DoF effect, `Render Queue` needs to be set to `Alpha Test`. + - SkeletonGraphic: Exposed `SetScaledPivotOffset` as public method outside of the editor to support programatically moving mesh offsets at runtime based on mesh bounds. + - SkeletonMecanim: Added `Scene Preview` option to preview an Animation Clip for e.g. easier event placement. When enabled, the Animation Clip selected in the Animation window is previewed in the Scene and Game views. Lock the `SkeletonMecanim` Inspector window, open the Animation window and select the Animation Clip. Then in the Animation window scrub through the timeline to see the current animation frame previewed. + - `Universal Render Pipeline/Spine/Skeleton Lit` shader now supports [Adaptive Probe Volumes (APV)](https://docs.unity3d.com/6000.0/Documentation/Manual/urp/probevolumes-concept.html) introduced in Unity 6. The shader also provides a new material property `APV per Pixel` to either calculate APV lighting contribution per pixel (the default) or per vertex. + - `Universal Render Pipeline/Spine/Sprite` shader now also supports [Adaptive Probe Volumes (APV)](https://docs.unity3d.com/6000.0/Documentation/Manual/urp/probevolumes-concept.html) introduced in Unity 6. APV lighting contribution is automatically calculated per pixel. + - All Spine Outline shaders, including the URP outline shaders, now provide an additional parameter `Fill`. Enable it to also fill the opaque area inside the outline with the outline color. Prevents a semi-transparent gap between outline and skeleton. Defaults to `disabled` to maintain existing behaviour. + - Added example component `RenderExistingMeshGraphic` (similar to `RenderExistingMesh`) to render a `SkeletonGraphic` mesh again with different materials. This might be required by e.g. URP and SkeletonGraphic outline shaders skipping additional render passes. To add a second outline variant of your SkeletonGraphic: + 1. Add a GameObject at the same hierarchy level as the reference SkeletonGraphic and move it before the reference SkeletonGraphic to render behind. + 2. Add a `RenderExistingMeshGraphic` component. + 3. In the `RenderExistingMeshGraphic` component Inspector at `Reference Skeleton Graphic` assign the original `SkeletonGraphic` object. + 4. At `Replacement Material` assign e.g. the included _SkeletonGraphicDefaultOutline_ material to replace all materials with this material. Alternatively, if `Multiple CanvasRenderers` is enabled at the reference SkeletonGraphic, you can add entries to the `Replacement Materials` list and at each entry assign the original SkeletonGraphic material (e.g. _SkeletonGraphicDefault_) to be replaced and the respective `Replacement Material` (e.g. _SkeletonGraphicDefaultOutline_). + - Added option for unsafe direct data loading when loading skeleton binary data to avoid some allocations, enabled via build define `SPINE_ALLOW_UNSAFE`. This define can be set via Spine Preferences, setting `Unsafe Build Defines - Direct data access`. The define is disabled by default to maintain existing behaviour. Changed asmdef setting for spine-unity assembly to allow unsafe code, has no effect other than allowing setting the `SPINE_ALLOW_UNSAFE` define. + - Added option to `BoneFollower` components to follow attachment Z spacing offset. The Inspector component property can be found under `Follow Z Position` - `Attachment Z Spacing`. Defaults to `false` to maintain existing behaviour. + +- **Breaking changes** + + - Changed `SpineShaderWithOutlineGUI` outline related methods from `private` to `protected virtual` to allow for custom shader GUI subclasses to switch to different outline shaders. + - Changed `BoneFollower` and `BoneFollowerGraphic` methods `LateUpdate` and `Initialize` to `virtual` to allow easier overriding for e.g. positional offset in custom subclasses. + - `MeshGenerator` received a new optimization option to avoid rendering fully transparent attachments at slot alpha 0 by default. Comment out `#define SLOT_ALPHA_DISABLES_ATTACHMENT` in `MeshGenerator.cs` to revert to previous behaviour. You may only need this option disabled when utilizing a custom shader which uses vertex color alpha for purposes other than transparency. + - PhysicsConstraints: bool properties `ApplyTranslationToPhysics` and `ApplyRotationToPhysics` were changed to `Vector2 PhysicsPositionInheritanceFactor` and `float PhysicsRotationInheritanceFactor` to allow the Transform movement the be scaled by a factor before being applied to the skeleton. You can set the properties to `Vector2.zero` and `0` respectively to disable applying any Transform movement at all. The `Advanced` Inspector section `Physics Constraints` was renamed to `Physics Inheritance`, the properties in the section are now called `Position` and `Rotation`. + - SkeletonGraphic Materials: Since the addition of new material sets for the `CanvasGroupCompatible` parameters, the default SkeletonGraphic materials all have `CanvasGroup Compatible` disabled. Please assign the respective material from the `CanvasGroupCompatible` material subdirectory if you want `CanvasGroup Compatible` enabled at your SkeletonGraphic. + - SkeletonGraphic: The parameter `SkeletonGraphic.MeshGenerator.settings.canvasGroupTintBlack` was changed to `canvasGroupCompatible` to help with auto-detecting correct Vertex Data and Material settings. Set the parameter to true if the SkeletonGraphic component is located below a `CanvasGroup` component. The parameter value is automatically migrated from `canvasGroupTintBlack`. + - Inspector: String attribute `SpineSkin()` now allows to include `` in the list of parameters. Previously the `includeNone=true` parameter of the `SpineSkin()` attribute defaulted to `true` but was ignored. Now it defaults to `false` and has an effect on the list. Only the Inspector GUI is affected by this behaviour change. + - `SkeletonGraphicRenderTexture` example component: `protected RawImage quadRawImage` was changed to `protected SkeletonSubmeshGraphic quadMaskableGraphic` for a bugfix. This is only relevant for subclasses of `SkeletonGraphicRenderTexture` or when querying the `RawImage` component via e.g. `skeletonGraphicRenderTexture.quad.GetComponent()`. + - Fixed a bug where when Linear color space is used and `PMA vertex colors` enabled, additive slots add a too dark (too transparent) color value. If you want the old incorrect behaviour (darker additive slots) or are not using Linear but Gamma color space, you can comment-out the define `LINEAR_COLOR_SPACE_FIX_ADDITIVE_ALPHA` in `MeshGenerator.cs` to deactivate the fix or just to skip unnecessary instructions. + - Fixed SkeletonRootMotion components ignoring parent bone scale when set by transform constraints. Using applied scale of parent bone now. If you need the old behaviour, comment out the line `#define USE_APPLIED_PARENT_SCALE` in SkeletonRootMotionBase.cs. + - Fixed SkeletonUtility callback update order when used with SkeletonRootMotion components so that the position when following a bone is updated after SkeletonRootMotion clears root-bone position. The order of SkeletonUtilityBone callbacks is changed to be later to achieve this. This is a breaking change in the unlikely case that you are using SkeletonRootMotion together with SkeletonUtility and subscribed to `UpdateLocal`, `UpdateWorld` or `UpdateComplete` yourself and relied on a certain callback order. One solution is to then resubscribe your own callback events accordingly by calling + `.UpdateLocal -= Callback; .UpdateLocal += Callback;`. + +- **Changes of default values** + +- **Deprecated** + +- **Restructuring (Non-Breaking)** + +### XNA/MonoGame + +- **Additions** + - Apply external movement to physics: If you are not directly modifying `Skeleton.X` or `Skeleton.Y`, you can apply external game object movement to skeleton physics as follows: + Add a `Vector2 lastPosition;` member variable to your class interacting with the skeleton. Then call e.g. the following code each frame: + ``` + Vector2 currentPosition = ; + Vector2 externalPositionDelta = currentPosition - lastPosition; + skeleton.PhysicsTranslate(externalPositionDelta.x, externalPositionDelta.y); + lastPosition = currentPosition; + ``` + +## Java + +- Added physics support + - Added `PhysicsConstraintXXXTimeline` and `PhysicsConstraintResetTimeline` + - Added `Physics` to be passed to `Skeleton#updateWorldTransform()` + - Added `SkeletonData#findPhysicsConstraint()` and `SkeletonData#getPhysicsConstraints()` to query physics constraints + - Added `Skeleton#findPhysicsConstraint()` and `Skeleton#getPhysicsConstraints()` to query physics constraints + - Added `Skeleton#physicsTranslate()` to translate all physics constraints by some distances in the skeleton coordinate system + - Added `Skeleton#physicsRotate()` to rotate all physics constraints by some distances in the skeleton coordinate system + - Added `Skeleton#time` and respective setters/getters to keep track of time for physics simulations + - See also breaking changes for `Skeleton#updateWorldTransform()` and the requirement to call `Skeleton#update()` to advance + pyhsics each frame. +- Added `InheritTimeline` +- Added [`TrackEntry#alphaAttachmentThreshold`](http://esotericsoftware.com/spine-api-reference#TrackEntry-alphaAttachmentThreshold) +- Added `TrackEntry#setMixDuration()` to set the mix duration in conjunction with a delay +- Added `TrackEntry#wasApplied()` to check if the entry has been applied +- Added `Bone#worldToParent()` to transform coordinates from world space to the parent space of a bone +- Added `Bone#localToParent()` to transform coordinates from a bone's local space to its parent space +- Added non essential fields `icon` and `visible` to `BoneData` +- Added non essential fields `path` and `visible` to `SlotData` +- Added `setToSetupPose()` to all contraint classes +- **Breaking changes** + - Renamed `TrackEntry#attachmentThreshold` to `TrackEntry#mixAttachmentThreshold` along with respective getters/settesr + - Renamed `TrackEntry::drawOrderThreshold` to `TrackEntry#mixDrawOrdertThreshold` along with respective getters/settesr + - Renamed `TransformMode` to `Inherit` and all `TransformMode_*` enums to `Inherit_*` + - You must call `Skeleton#update(delta)` before calling `Skeleton#updateWorldTransform()` if the frame time has advanced. This is needed to update physics accordingly + - `Skeleton#updateWorldTransform()` takes an additional `Physics` parameter. See the `Physics` documentation for information on what the different enum values do + - All `Updatable` sub-classes like `Bone` and constraints now take an additional `Physics` parameter for their `update()` methods + +### libGDX + +- Added physics examples + +## Typescript/Javascript + +- Added physics support + - Added `PhysicsConstraintXXXTimeline` and `PhysicsConstraintResetTimeline` + - Added `Physics` to be passed to `Skeleton#updateWorldTransform()` + - Added `SkeletonData#findPhysicsConstraint()` and `SkeletonData#getPhysicsConstraints()` to query physics constraints + - Added `Skeleton#findPhysicsConstraint()` and `Skeleton#getPhysicsConstraints()` to query physics constraints + - Added `Skeleton#physicsTranslate()` to translate all physics constraints by some distances in the skeleton coordinate system + - Added `Skeleton#physicsRotate()` to rotate all physics constraints by some distances in the skeleton coordinate system + - Added `Skeleton#time` and respective setters/getters to keep track of time for physics simulations + - See also breaking changes for `Skeleton#updateWorldTransform()` and the requirement to call `Skeleton#update()` to advance + pyhsics each frame. +- Added `InheritTimeline` +- Added [`TrackEntry#alphaAttachmentThreshold`](http://esotericsoftware.com/spine-api-reference#TrackEntry-alphaAttachmentThreshold) +- Added `TrackEntry#setMixDuration()` to set the mix duration in conjunction with a delay +- Added `TrackEntry#wasApplied()` to check if the entry has been applied +- Added `Bone#worldToParent()` to transform coordinates from world space to the parent space of a bone +- Added `Bone#localToParent()` to transform coordinates from a bone's local space to its parent space +- Added non essential fields `icon` and `visible` to `BoneData` +- Added non essential fields `path` and `visible` to `SlotData` +- Added `setToSetupPose()` to all contraint classes +- **Breaking changes** + - Renamed `TrackEntry#attachmentThreshold` to `TrackEntry#mixAttachmentThreshold` along with respective getters/settesr + - Renamed `TrackEntry::drawOrderThreshold` to `TrackEntry#mixDrawOrdertThreshold` along with respective getters/settesr + - Renamed `TransformMode` to `Inherit` and all `TransformMode_*` enums to `Inherit_*` + - You must call `Skeleton#update(delta)` before calling `Skeleton#updateWorldTransform()` if the frame time has advanced. This is needed to update physics accordingly + - `Skeleton#updateWorldTransform()` takes an additional `Physics` parameter. See the `Physics` documentation for information on what the different enum values do + - All `Updatable` sub-classes like `Bone` and constraints now take an additional `Physics` parameter for their `update()` methods + +### WebGL backend + +- Added physics examples + +### Canvas backend + +### CanvasKit backend + +- Added spine-canvaskit runtime. See https://esotericsoftware.com/spine-canvaskit + +### Three.js backend + +- Added physics support + +### Player + +- Added physics support +- Added `scale` field to configuration which defines the scale to load the skeleton at +- Added `updateWorldTransform` field to configuration which expects a function that updates the skeleton. Defaults to player.skeleton.updateWorldTransform(spine.Physics.update) +- Added `skeleton` to `SpinePlayerConfig` to specify the URL of the skeleton .json or .skel file. Deprecated `jsonURL` and `binaryURL`. The old fields can still be used, but will be removed in Spine 4.3 +- Added `atlas` to `SpinePlayerConfig` to specify the URL of the .atlas file. Deprecated `atlasURL`. The old field can still be used, but will be removed in Spine 4.3. + +### Pixi + +- Added spine-pixi runtime, also backported to Spine 4.1. See https://esotericsoftware.com/spine-pixi + +### Phaser + +- Added spine-phaser runtime, also backported to Spine 4.1. See https://esotericsoftware.com/spine-phaser + +## Haxe + +- Added spine-haxe runtime, also backported to Spine 4.1. See https://esotericsoftware.com/spine-haxe + +## Flutter + +- Added spine-flutter runtime, also backported to Spine 4.1. See https://esotericsoftware.com/spine-flutter + +# 4.1 + +## C + +- **Additions** + - Support for sequences. + - Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + - Added CMake parameter `SPINE_SANITIZE` which will enable sanitizers on macOS and Linux. + - Added `SPINE_MAJOR_VERSION`, `SPINE_MINOR_VERSION`, and `SPINE_VERSION_STRING`. Parsing skeleton .JSON and .skel files will report an error if the skeleton version does not match the runtime version. +- **Breaking changes** + - `spRegionAttachment` and `spMeshAttachment` now contain a `spTextureRegion*` instead of encoding region fields directly. + - `sp_AttachmentLoader_newRegionAttachment()` and `spAttachmentLoader_newMeshAttachment()` now take an additional `Sequence*` parameter. + - `spMeshAttachment_updateUVs()` was renamed to `spMeshAttachment_updateRegion()`. + - `spRegionAttachment_updateOffset()` was renamed to `spRegionAttachment_updateRegion()`, `spRegionAttachment_setUVs()` was merged into `spRegionAttachment_updateRegion()`. + - `spSlot_getAttachmentTime()` and `spSlot_setAttachmentTime()` have been removed. + - `spVertexAttachment->deformAttachment` was renamed to `spVertexAttachment->timelineAttachment`. + - `spSkeleton_update()` has been removed. + - `spSkeleton->time` has been removed. + - `spVertexEffect` has been removed. + +### SFML + +- Updated example to use SFML 2.5.1. +- Added dragon example. + +## C++ + +- **Additions** + - Support for sequences. + - Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + - Added CMake parameter `SPINE_SANITIZE` which will enable sanitizers on macOS and Linux. + - Added `SPINE_MAJOR_VERSION`, `SPINE_MINOR_VERSION`, and `SPINE_VERSION_STRING`. Parsing skeleton .JSON and .skel files will report an error if the skeleton version does not match the runtime version. + - Added `SkeletonBounds::getBoundingBox()`, `SkeletonBounds::getPolygons()`, and `SkeletonBounds::getBoundingBoxes()`. +- **Breaking changes** + - `RegionAttachment` and `MeshAttachment` no longer implement `HasRendererObject`. + - `RegionAttachment` and `MeshAttachment` now contain a `TextureRegion*` instead of encoding region fields directly. + - `AttachmentLoader::newRegionAttachment()` and `AttachmentLoader::newMeshAttachment()` now take an additional `Sequence*` parameter. + - `MeshAttachment::updateUVs()` was renamed to `MeshAttachment::updateRegion()`. + - `RegionAttachment::updateOffset()` was renamed to `RegionAttachment::updateRegion()`, `RegionAttachment::setUVs()` was merged into `updateRegion()`. + - `Slot::getAttachmentTime()` and `Slot::setAttachmentTime()` have been removed. + - `VertexAttachment::getDeformAttachment()` was renamed to `VertexAttachment::getTimelineAttachment()`. + - `Skeleton::update()` has been removed. + - `Skeleton::getTime()` has been removed. + - `VertexEffect` has been removed. + +### Cocos2d-x +- Renamed `SkeletonRenderer` to `SkeletonRendererCocos2dX` to avoid name clash with spine-cpp class. + +### SFML + +- Updated example to use SFML 2.5.1. +- Added dragon example. + +### UE4 + +- Updated example project to UE 4.27 + +## C# + +- **Additions** + + - Full support for sequences. + - Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + - `RegionAttachment` and `MeshAttachment` now provide a `Region` property. Use this property instead of the removed `RendererObject` property (see section _Breaking Changes_ below). + +- **Breaking changes** + - Removed `RendererObject` property from `RegionAttachment` and `MeshAttachment`. Use `attachment.Region` property instead. Removed removed `IHasRendererObject` interface. Use `IHasTextureRegion` instead. + - Replaced `RegionAttachment.UpdateOffset` and `MeshAttachment.UpdateUVs` with `Attachment.UpdateRegion`. The caller must ensure that the attachment's region is not `null`. + - Removed `AttachmentRegionExtensions` methods `Attachment.SetRegion`, `MeshAttachment.SetRegion` and `RegionAttachment.SetRegion(region, update)`. Use `attachment.Region = region; if (update) attachment.UpdateRegion()` instead. + - `AttachmentLoader.NewRegionAttachment()` and `AttachmentLoader.NewMeshAttachment()` take an additional `Sequence` parameter. + - `VertexAttachment.DeformAttachment` property has been replaced with `VertexAttachment.TimelineAttachment`. + - `RegionAttachment.ComputeWorldVertices()` takes a `Slot` instead of a `Bone` as the first argument. + - Removed `Skeleton.Update(float deltaTime)` method. + - Removed `Slot.AttachmentTime` property. + - Removed extension method `AtlasRegion.GetSpineAtlasRect()` parameter `includeRotate` (with default value `true`). Most likely this method was never used with `includeRotate=false` in user code so no changes are required. + - `AtlasRegion.PackedWidth` and `AtlasRegion.PackedHeight` are swapped compared to 4.0 when packing rotation is equal to 90 degrees. Most likely this property was never accessed in user code so no changes are required. + +### Unity + +- **Officially supported Unity versions are 2017.1-2023.1**. + +- **Additions** + + - `SpineAtlasAsset.CreateRuntimeInstance` methods now provide an optional `newCustomTextureLoader` parameter (defaults to `null`) which can be set to e.g. `(a) => new YourCustomTextureLoader(a)` to use your own `TextureLoader` subclass instead of `MaterialsTextureLoader`. + - `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic` now provide an Inspector parameter `Advanced` - `Animation Update` with modes `In Update` **(previous behaviour, the default)**, `In FixedUpdate` and `Manual Update`. This allows to update animation in `FixedUpdate` when using the `SkeletonRootMotion` component (which is the recommended combination now, issuing a warning otherwise). The reason is that when root motion leads to a collision with a physics collider, it can introduce jittery excess movement when updating animation in `Update` due to more `Update` calls following a single `FixedUpdate` call. + - Added `SkeletonRootMotion` properties `PreviousRigidbodyRootMotion` and `AdditionalRigidbody2DMovement`. Setting or querying these movement vectors can be necessary when multiple scripts call `Rigidbody2D.MovePosition` on the same object where the last call overwrites the effect of preceding ones. + - `BoneFollower` and `BoneFollowerGraphic` now provide an additional `Follow Parent World Scale` parameter to allow following simple scale of parent bones (rotated/skewed scale can't be supported). + - Improved `Advanced - Fix Prefab Override MeshFilter` property for `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`), now providing an additional option to use a global value which can be set in `Edit - Preferences - Spine`. + - Timeline naming improvements: `Spine AnimationState Clip` Inspector parameter `Custom Duration` changed and inverted to `Default Mix Duration` for more clarity. Shortened all Timeline add track menu entries from: `Spine.Unity.Playables - ` to `Spine - `, `Spine Animation State Track` to `SkeletonAnimation Track`, `Spine AnimationState Graphic Track` to `SkeletonGraphic Track`, and `Spine Skeleton Flip Track` to `Skeleton Flip Track`. + - Timeline track appearance and Inspector: Tracks now show icons and track colors to make them easier to distinguish. When a Track is selected, the Inspector now shows an editable track name which was previously only editable at the Timeline asset. + - Added example component `SkeletonRenderTexture` to render a `SkeletonRenderer` to a `RenderTexture`, mainly for proper transparency. Added an example scene named `RenderTexture FadeOut Transparency` that demonstrates usage for a fadeout transparency effect. + - Added another fadeout example component named `SkeletonRenderTextureFadeout` which takes over transparency fadeout when enabled. You can use this component as-is, attach it in disabled state and enable it to start a fadeout effect. + - Timeline clips now offer an additional `Alpha` parameter for setting a custom constant mix alpha value other than 1.0, just as `TrackEntry.Alpha`. Defaults to 1.0. + - `GetRemappedClone` copying from `Sprite` now provides additional `pmaCloneTextureFormat` and `pmaCloneMipmaps` parameters to explicitly specify the texture format of a newly created PMA texture. + - Spine property Inspector fields (`Animation Name`, `Bone Name`, `Slot` and similar) now display the name in red when the respective animation/bone/etc no longer exists at the skeleton data. This may be helpful when such items have been renamed or deleted. + - Added `UnscaledTime` property at `SkeletonAnimation` as well, behaving like `SkeletonGraphic.UnscaledTime`. If enabled, AnimationState uses unscaled game time (`Time.unscaledDeltaTime`), running animations independent of e.g. game pause (`Time.timeScale`). + - `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic` now provide an additional `OnAnimationRebuild` callback delegate which is issued after both the skeleton and the animation state have been initialized. + - Timeline `SkeletonAnimation Track` and `SkeletonGraphic Track` now provide an `Unscaled Time` property. Whenever starting a new animation clip of this track, `SkeletonAnimation.UnscaledTime` or `SkeletonGraphic.UnscaledTime` will be set to this value. This allows you to play back Timeline clips either in normal game time or unscaled game time. Note that `PlayableDirector.UpdateMethod` is ignored and replaced by this property, which allows more fine-granular control per Timeline track. + - Added `SkeletonRootMotion` callback delegates `ProcessRootMotionOverride` and `PhysicsUpdateRootMotionOverride` to customize how root motion is applied. The new property `disableOnOverride` determines whether the callback will be issued in addition or instead of normally applying root motion. Added property `rootMotionScaleRotation` to allow scaling rotational root-motion to match e.g. a 90 degree rotation to a custom target angle. + - Added outline shader parameter `Advanced - Opaque Alpha` which can be used to exclude problematic semi-transparent areas, which may receive an undesired large outline color overlay otherwise. + - Added Spine Preferences setting `Prefabs` - `Optimize Preview Meshes`. When enabled, Spine prefab preview meshes will be removed in a pre-build step to reduce build size. This increases build time as all prefabs in the project will be processed. Defaults to false to not slow down builds substantially every time. + - Added Spine Preferences setting `Reload SkeletonData after Play`. When enabled, the shared `SkeletonData` of all skeletons in the active scene is reloaded (from the `.json` or `.skel.bytes` file) after exiting play-mode. You can disable this setting to avoid the reloading delay if you can ensure that there are no (accidental) modifications to the shared `SkeletonData` during play-mode (otherwise it would carry over its effect into subsequent plays). Defaults to `true` (the safe setting), which maintains existing behaviour. + - Added `SkeletonAnimationMulti` sample component methods `SetActiveSkeleton(int index)` and getter property `SkeletonAnimations` to more easily apply changes at all SkeletonAnimation instances instead of only the active one. + - PMA textures now have `sRGB (Color Texture)` disabled by default, the preset template `PMATexturePreset.preset` has been adjusted accordingly. As PMA textures are only allowed with Gamma color space, `sRGB (Color Texture)` shall be disabled to prevent border artifacts when mipmaps are enabled. In Gamma color space having this setting disabled has no drawbacks, only benefits. + - `SkeletonRenderTexture` and `SkeletonGraphicRenderTexture` components now support automatic down-scaling when required size on screen exceeds `Max Render Texture Size`. + - Added `Spine/SkeletonGraphic Fill` shader to provide functionality of `Spine/Skeleton Fill` shader for `SkeletonGraphic`. + - Lit Spine URP shaders (`Universal Render Pipeline/Spine/Sprite` and `Universal Render Pipeline/Spine/Skeleton Lit`) now support `Forward+` rendering path as introduced by Unity 2022.2 and URP version 14. + - `SkeletonGraphic` now supports automatic scaling based on its `RectTransform` bounds. Automatic scaling can be enabled by setting the added `Layout Scale Mode` Inspector property to either `Width Controls Height`, `Height Controls Width`, `FitInParent` or `EnvelopeParent`. It is set to `None` by default to keep previous behaviour and avoid breaking existing projects. To modify the reference layout bounds, hit the additional `Edit Layout Bounds` toggle button to switch into edit mode, adjust the bounds or hit `Match RectTransform with Mesh`, and hit the button again when done adjusting. The skeleton will now be scaled accordingly to fit the reference layout bounds to the object's `RectTransform`. + - Added previously missing unlit URP 2D shader variant, available under `Universal Render Pipeline/2D/Spine/Skeleton`. + - Added support for light cookies at `Universal Render Pipeline/Spine/Sprite` shader. + - Timeline extension package: An additional Spine preferences parameter `Timeline` - `Default Mix Duration` has been added, setting newly added `SpineAnimationStateClip` clips accordingly, defaults to false. This Spine preferences parameter can be enabled to default to the previous behaviour before this update. + - Tint Black: Added support for [Tint Black](http://en.esotericsoftware.com/spine-slots#Tint-black) functionality at all Spine URP shaders (2D and 3D shaders) and at all standard pipeline `Spine/Sprite` shaders. This feature can be enabled via the `Tint Black` material parameter in the Inspector. Note: The URP Sprite shaders provided in the Spine URP Shaders extension UPM package require the latest version of the spine-unity runtime (package version 4.1.12, 2023-05-31 or newer) to display the added material parameters in the Inspector GUI. + - Added `SkeletonGraphic.MeshScale` property to allow access to calculated mesh scale. `MeshScale` is based on (1) Canvas pixels per unit, and (2) `RectTransform` bounds when using `Layout Scale Mode` other than `None` at `SkeletonGraphic` which scales the skeleton mesh to fit the parent `RectTransform` bounds accordingly. + - Added `updateSeparatorPartScale` property to `SkeletonGraphic` to let render separator parts follow the scale (lossy scale) of the `SkeletonGraphic` GameObject. Defaults to `false` to maintain existing behaviour. + - Added experimental `EditorSkeletonPlayer` component to allow Editor playback of the initial animation set at `SkeletonAnimation` or `SkeletonGraphic` components. Add this component to your skeleton GameObject to enable the in-editor animation preview. Allows configurations for continuous playback when selected, deselected, and alternative single-frame preview by setting `Fixed Track Time` to any value other than 0. Limitations: At skeletons with variable material count the Inspector preview may be too unresponsive. It is then recommended to disable the `EditorSkeletonPlayer` component (at the top of the Inspector) to make it responsive again, then you can disable `Play When Selected` and re-enable the component to preview playback only when deselected. + - Added example component `RenderCombinedMesh` to render a combined mesh of multiple meshes or submeshes. This is required by `OutlineOnly` shaders to render a combined outline when using `SkeletonRenderSeparator` or multiple atlas pages which would normally lead to outlines around individual parts. To add a combined outline to your SkeletenRenderer: + 1. Add a child GameObject and move it a bit back (e.g. position Z = 0.01). + 2. Add a `RenderCombinedMesh` component, provided in the `Spine Examples/Scripts/Sample Components` directory. + 3. Copy the original material, add _\_Outline_ to its name and set the shader to your outline-only shader like `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly` or `Spine/Outline/OutlineOnly-ZWrite`. + 4. Assign this _\_Outline_ material at the new child GameObject's `MeshRenderer` component. + If you are using `SkeletonRenderSeparator` and need to enable and disable the `SkeletonRenderSeparator` component at runtime, you can increase the `RenderCombinedMesh` `Reference Renderers` array by one and assign the `SkeletonRenderer` itself at the last entry after the parts renderers. Disabled `MeshRenderer` components will be skipped when combining the final mesh, so the combined mesh is automatically filled from the desired active renderers. + - Timeline extension package: Added static `EditorEvent` callback to allow editor scripts to react to animation events outside of play-mode. Register to the events via `Spine.Unity.Playables.SpineAnimationStateMixerBehaviour.EditorEvent += YourCallback;`. + - URP Shaders: Added `Depth Write` property to shaders `Universal Render Pipeline/Spine/Skeleton` and `Universal Render Pipeline/Spine/Skeleton Lit`. Defaults to false to maintain existing behaviour. + - Added `Animation Update` mode (called `UpdateTiming` in code) `In Late Update` for `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic`. This allows you to update the `SkeletonMecanim` skeleton in the same frame that the Mecanim Animator updated its state, which happens between `Update` and `LateUpdate`. + - URP Shaders: Added URP "Blend Mode" shader variants for both URP 3D and URP 2D renderers. They are listed under shader name "Universal Render Pipeline/Spine/Blend Modes/" and "Universal Render Pipeline/2D/Spine/Blend Modes/" respectively. + - URP Shaders: Added support for [Tint Black](http://en.esotericsoftware.com/spine-slots#Tint-black) functionality at "Blend Modes" Spine URP shaders (2D and 3D shaders). + +- **Breaking changes** + + - Made `SkeletonGraphic.unscaledTime` parameter protected, use the new property `UnscaledTime` instead. + - `SkeletonGraphic` `OnRebuild` callback delegate is now issued after the skeleton has been initialized, before the `AnimationState` component is initialized. This makes behaviour consistent with `SkeletonAnimation` and `SkeletonMecanim` component behaviour. Use the new callback `OnAnimationRebuild` if you want to receive a callback after the `SkeletonGraphic` `AnimationState` has been initialized. + - Changed name of prefab skeleton meshes stored at prefabs from `Skeleton Prefab Mesh "name"` to `Skeleton Prefab Mesh [name]` to avoid issues with quotes in mesh asset names (see [this issue](https://github.com/EsotericSoftware/spine-runtimes/issues/2572)). Likely this change poses no problems at all, however if you are parsing the prefab's mesh name for whatever reason, be sure to adjust the pattern accordingly. + +- **Changes of default values** + +- **Deprecated** + + - Shader macro `RETURN_UNLIT_IF_ADDITIVE_SLOT` in `spine-unity/Shaders/Sprite/CGIncludes/ShaderShared.cginc` has been deprecated and will be removed in spine-unity 4.2. Use RETURN_UNLIT_IF_ADDITIVE_SLOT_TINT instead. + +- **Restructuring (Non-Breaking)** + - Moved Spine URP Shaders Examples directory from the main package directory to Samples which can be installed via the Unity Package Manager. To import, select the `Spine Universal RP Shaders` package in the Package Manager window, expand `Samples` at the bottom and hit `Import` next to `Examples`. This follows the standard [samples guideline](https://docs.unity3d.com/Manual/cus-samples.html) and prevents warning messages about unexpectedly altered immutable assets. + +### XNA/MonoGame + +- **Breaking change**: Removed spine-xna in favor of spine-monogame. See https://github.com/EsotericSoftware/spine-runtimes/issues/1949 +- Added new spine-monogame solution. See [spine-monogame/README.md](spine-monogame/README.md) for updated instructions on how to use spine-monogame. + +## Java + +- **Additions** + - Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + - Support for sequences. +- **Breaking changes** + - `AttachmentLoader#newRegionAttachment()` and `AttachmentLoader#newMeshAttachment()` take an additional `Sequence` parameter. + - `Slot#setAttachmentTime()` and `Slot#getAttachmentTime()` have been removed. + - `VertexAttachment#setDeformAttachment()` and `VertexAttachment#getDeformAttachment()` have been replaced with `VertexAttachment#setTimelineAttachment()` and `VertexAttachment#getTimelineAttachment()`. + - `RegionAttachment#updateOffset()` has been renamed to `RegionAttachment#updateRegion()`. The caller must ensure that the attachment's region is not `null`. + - `RegionAttachment#computeWorldVertices()` takes a `Slot` instead of a `Bone` as the first argument. + - `VertexEffect` has been removed. + +### libGDX + +- `spine-libgdx`, `spine-libgdx-tests`, and `spine-skeletonviewer` are now fully Gradle-ified. +- `spine-skeletonviewer` now supports quickly loading skeletons by dragging and dropping `.json` or `.skel` skeleton files onto the window. + +## Typescript/Javascript + +- **Additions** + - full support for sequences. + - Added `Promise` based `AssetManager.loadAll()`. Allows synchronous waiting via `await assetManager.loadAll()`, simplifying loader logic in applications. + - Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027. + - Full support for sequences. +- **Breaking changes** + - `AttachmentLoader#newRegionAttachment()` and `AttachmentLoader#newMeshAttachment()` take an additional `Sequence` parameter. + - `Slot#attachmentTime` and has been removed. + - `VertexAttachment#deformAttachment` has been replaced with `VertexAttachment#timelineAttachment`. + - `RegionAttachment#updateOffset()` has been renamed to `RegionAttachment#updateRegion()`. The caller must ensure that the attachment's region is not `null`. + - `RegionAttachment#computeWorldVertices()` takes a `Slot` instead of a `Bone` as the first argument. + - Removed `PlayerEditor`. + - `VertexEffect` has been removed. + - Removed `RegionAttachment.rendererObject`. + - Renamed `TextureRegion.renderObject` to `TextureRegion.texture`. + +### WebGL backend + +- `PolygonBatcher` can now disable culling automatically if the static variable `PolygonBatcher.disableCulling` is set to true. +- Added `SpineCanvas`, a simpler way to render a scene via spine-webgl. See `spine-ts/spine-webgl/examples/barebones.html` and `spine-ts/spine-webgl/examples/mix-and-match.html`. +- Added `SpineCanavs.dispose()` to halt the updating and rendering of the canvas. + +### Canvas backend + +- Improved example. + +### Three.js backend + +- Added orbital controls to THREJS example. +- `SkeletonMesh` takes an optional `SkeletonMeshMaterialCustomizer`, allowing modification of materials used by `SkeletonMesh`. +- Added `SkeletonMeshMaterial.alphaTest`, when > 0, alpha testing will be performed and fragments will not be written to the depth buffer, if depth writes are enabled. + +### Player + +- Added `SpinePlayer.dispose()` to explicitely dispose of all resources the player holds on to. + +# 4.0 + +## AS3 + +**NOTE: Spine 4.0 will be the last release supporting spine-as3. Starting from Spine 4.1, spine-as3 will no longer be supported or maintained.** + +- Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. +- Expose non-essential colors on bones, bounding box, clipping, and path attachments. +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +- Added support for reverse animation playback via `TrackEntry.reverse`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. + +### Starling + +**NOTE: Spine 4.0 will be the last release supporting spine-starling. Starting from Spine 4.1, spine-starling will no longer be supported or maintained.** + +- Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. +- Updated to Starling 2.6 and Air SDK 33. + +## C + +- **Breaking change:** Removed `SPINE_SHORT_NAMES` define and C++ constructors. +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `spAnimationState_clearNext()` which removes the given `spTrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `spAtlasRegion.keyValues`. +- Added support for reverse animation playback via `spTrackEntry.reverse`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. + +### Cocos2d-Objc + +**NOTE: Spine 4.0 will be the last release supporting spine-cocos2d-objc. Starting from Spine 4.1, spine-cocos2d-objc will no longer be supported or maintained.** + +### SFML + +- Added `ikDemo()` in `main.cpp`. to illustrate how to drive a bone and IK chain through mouse movement. + +## C++ + +- Removed dependency on STL throughout the code base, cutting down on the LOC that need parsing by 66%. +- Exposed `x` and `y` on `SkeletonData` through getters and setters. +- Expose non-essential colors on bones, bounding box, clipping, and path attachments. +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +- Added support for reverse animation playback via `TrackEntry.reverse`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. +- spine-cpp now requires C++11. + +### Cocos2d-x + +- Added `IKExample` scene to illustrate how to drive a bone and IK chain through mouse movement. +- Added `SkeletonAnimation::setPreUpdateWorldTransformsListener()` and `SkeletonAnimation::setPostUpdateWorldTransformsListener()`. This allows users to modify bone transforms and other skeleton properties before and after the world transforms of all bones are calculated. See the `IKExample` for a usage example. + +### SFML + +- Added `ikDemo()` in `main.cpp`. to illustrate how to drive a bone and IK chain through mouse movement. + +### UE4 + +- `SpineWidget` now supports the full widget transform, including rendering scale/shear. +- Materials on `SkeletonRendererComponent` are now blueprint read and writeable. This allows setting dynamic material instances at runtime. +- Added `InitialSkin` property to `USpineWidget`. This allows previewing different skins in the UMG Designer. Initial skins can still be overridden via blueprint events such as `On Initialized`. +- **Breaking change:** `SpineWidget` no longer has the `Scale` property. Instead the size x/y properties can be used. +- Added `SetSlotColor` on `USpineSkeletonComponent` to easily set the color of a slot via blueprints. +- Changed mixes set on an `SkeletonDataAsset` will now be applied to instances of `USpineSkeletonComponent`. +- Generated normals are now correctly flipped for back faces. +- Modifying parent materials updates material instances accordingly. +- Only `.json` files that are actually encoding Spine skeletons will be loaded. Other `.json` files will be left to other importers. +- Updated example project to UE 4.27. + +## C# + +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +- Added support for reverse animation playback via `TrackEntry.Reverse`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. +- **Breaking change:** Removed `SkeletonData` and `Skeleton` methods: `FindBoneIndex`, `FindSlotIndex`. Bones and slots have an `Index` field that should be used instead. Be sure to check for e.g. `bone == null` accordingly before accessing `bone.Index`. + +### Unity + +- **Officially supported Unity versions are 2017.1-2022.1**. +- **Breaking changes** + + - Removed all `Spine.Unity.AttachmentTools.SkinUtilities` Skin extension methods. These have become obsoleted and error-prone since the introduction of the new Skin API in 3.8. To fix any compile errors, replace any usage of `Skin` extension methods with their counterparts, e.g. replace occurrances of `skin.AddAttachments()` with `skin.AddSkin()`. Please see the example scene `Mix and Match Skins` on how to use the new Skin API to combine skins, or the updated old example scenes `Mix and Match` and `Mix and Match Equip` on how you can update an existing project using the old workflow. If you are using `skeletonAnimation.Skeleton.UnshareSkin()` in your code, you can replace it with `Skin customSkin = new Skin("custom skin"); customSkin.AddSkin(skeletonAnimation.Skeleton.Skin);`. + - `Skin.GetAttachments()` has been replaced by `Skin.Attachments`, returning an `ICollection`. This makes access more consistent and intuitive. To fix any compile errors, replace any occurrances of `Skin.GetAttachments()` by `Skin.Attachments`. + - Removed redundant `Spine.Unity.AttachmentTools.AttachmentCloneExtensions` extension methods `Attachment.GetCopy()` and `Attachment.GetLinkedMesh()`. To fix any compile errors, replace any occurrances with `Attachment.Copy()` and `Attachment.NewLinkedMesh()`. + - Removed `Spine.Unity.AttachmentTools.AttachmentRegionExtensions` extension methods `Attachment.GetRegion()`. Use `Attachment.RendererObject as AtlasRegion` instead. + - Removed redundant `Spine.SkeletonExtensions` extension methods: + Replace: + + - `Skeleton.SetPropertyToSetupPose()` + - `Skeleton.SetDrawOrderToSetupPose()` + - `Skeleton.SetSlotAttachmentsToSetupPose()` + - `Skeleton.SetSlotAttachmentToSetupPose()` + + with `Skeleton.SetSlotsToSetupPose()`. + Replace: + + - `Slot.SetColorToSetupPose()` + - `Slot.SetAttachmentToSetupPose()` + + with `Slot.SetToSetupPose()`. + + Also removed less commonly used extension methods: + `TrackEntry.AllowImmediateQueue()`, `Animation.SetKeyedItemsToSetupPose()` and `Attachment.IsRenderable()`. + + - **`SkeletonGraphic` now no longer uses a `RawImage` component at each submesh renderer** GameObject when `allowMultipleCanvasRenderers` is true. Instead, a new custom component `SkeletonSubmeshGraphic` is used which is more resource friendly. Replacement of these components will be performed automatically through editor scripting, saving scenes or prefabs will persist the upgrade. + - **Linear color space:** Previously Slot colors were not displayed the same in Unity as in the Spine Editor. This is now fixed at all shaders, including URP and LWRP shaders. See section _Additions_ below for more details. If you have tweaked Slot colors to look correct in `Linear` color space in Unity but incorrect in Spine, you might want to adjust the tweaked colors. Slot colors displayed in Unity should now match colors displayed in the Spine Editor when configured to display as `Linear` color space in the Spine Editor Settings. + - **Additive Slots have always been lit** before they were written to the target buffer. Now all lit shaders provide an additional parameter `Light Affects Additive` which defaults to `false`, as it is the more intuitive default value. You can enable the old behaviour by setting this parameter to `true`. + - **Corrected blending behaviour of all `Sprite` shaders** in `Premultiply Alpha` blend mode (including URP and LWRP packages). Previously vertex color alpha was premultiplied again, even though `Premultiply Alpha` blend mode assumes PMA texture and PMA vertex color input. Slot-alpha blending will thus be correctly lighter after upgrading to 4.0. If you have compensated this problem by disabling `Advanced - PMA Vertex Colors` you can now re-enable this parameter, also allowing for rendering Additive slots in a single pass. + - **Corrected all `Outline` shaders outline thickness** when `Advanced - Sample 8 Neighbourhood` is disabled (thus using `4 Neighbourhood`). Previously weighting was incorrectly thick (4x as thick) compared to 8 neighbourhood, now it is more consistent. This might require adjustment of all your outline materials where `Sample 8 Neighbourhood` is disabled to restore the previous outline thickness, by adjusting the `Outline Threshold` parameter through adding a `/4` to make the threshold 4 times smaller. + - Reverted changes: `BoneFollower` property `followLocalScale` has intermediately been renamed to `followScale` but was renamed back to `followLocalScale`. Serialized values (scenes and prefabs) will automatically be upgraded, only code accessing `followScale` needs to be adapted. + - Fixed Timeline not pausing (and resuming) clip playback on Director pause, this is now the default behaviour. If you require the old behaviour (e.g. to continue playing an idle animation during Director pause), there is now an additional parameter `Don't Pause with Director` provided that can be enabled for each Timeline clip. + - Fixed Timeline `Spine AnimationState Clips` ignoring empty space on the Timeline after a clip's end. Timeline clips now also offer `Don't End with Clip` and `Clip End Mix Out Duration` parameters if you prefer the old behaviour of previous versions. By default when empty space follows the clip on the timeline, the empty animation is set on the track with a MixDuration of `Clip End Mix Out Duration`. Set `Don't End with Clip` to `true` to continue playing the clip's animation instead and mimic the old 3.8 behaviour. If you prefer pausing the animation instead of mixing out to the empty animation, set `Clip End Mix Out Duration` to a value less than 0, then the animation is paused instead. + +- **Additions and Improvements** + + - Additional **Fix Draw Order** parameter at SkeletonRenderer, defaults to `disabled` (previous behaviour). + Applies only when 3+ submeshes are used (2+ materials with alternating order, e.g. "A B A"). + If `true`, MaterialPropertyBlocks are assigned at each material to prevent aggressive batching of submeshes + by e.g. the LWRP renderer, leading to incorrect draw order (e.g. "A1 B A2" changed to "A1A2 B"). + You can leave this parameter disabled when everything is drawn correctly to save the additional performance cost. + - **Additional Timeline features.** SpineAnimationStateClip now provides a `Speed Multiplier`, a start time offset parameter `Clip In`, support for blending successive animations by overlapping tracks. An additional `Use Blend Duration` parameter _(defaults to true)_ allows for automatic synchronisation of MixDuration with the current overlap blend duration. An additional Spine preferences parameter `Use Blend Duration` has been added which can be disabled to default to the previous behaviour before this update. + - Additional `SpriteMask and RectMask2D` example scene added for demonstration of mask setup and interaction. + - `Real physics hinge chains` for both 2D and 3D physics. The [SkeletonUtilityBone](https://esotericsoftware.com/spine-unity-utility-components#SkeletonUtilityBone) Inspector provides an interface to create 2D and 3D hinge chains. Previously created chains have only been respecting gravity, but not momentum of the skeleton or parent bones. The new physics rig created when pressing `Create 3D Hinge Chain` and `Create 2D Hinge Chain` creates a more complex setup that also works when flipping the skeleton. Note that the chain root node is no longer parented to bones of the skeleton. This is a requirement in Unity to have momentum applied properly - do not reparent the chain root to bones of your skeleton, or you will loose any momentum applied by the skeleton's movement. + - `Outline rendering functionality for all shaders.` Every shader now provides an additional set of `Outline` parameters to enable custom outline rendering. When outline rendering is enabled via the `Material` inspector, it automatically switches the shader to the respective `Spine/Outline` shader variant. Outlines are generated by sampling neighbour pixels, so be sure to add enough transparent padding when exporting your atlas textures to fit the desired outline width. In order to enable outline rendering at a skeleton, it is recommended to first prepare an additional outline material copy and then switch the material of the target skeleton to this material. This prevents unnecessary additional runtime material copies and drawcalls. Material switching can be prepared via a [SkeletonRendererCustomMaterials](https://esotericsoftware.com/spine-unity-utility-components#SkeletonRendererCustomMaterials) component and then enabled or disabled at runtime. Alternatively, you can also directly modify the `SkeletonRenderer.CustomMaterialOverride` property. + Outline rendering is fully supported on `SkeletonGraphic` shaders as well. + - Added `SkeletonRenderer.EditorSkipSkinSync` scripting API property to be able to set custom skins in editor scripts. Enable this property when overwriting the Skeleton's skin from an editor script. Without setting this parameter, changes will be overwritten by the next inspector update. Only affects Inspector synchronisation of skin with `initialSkinName`, not startup initialization. + - `AtlasUtilities.GetRepackedAttachments()` and `AtlasUtilities.GetRepackedSkin()` provide support for additional texture channels such as normal maps via the optional parameter `additionalTexturePropertyIDsToCopy `. See the spine-unity runtime documentation, section [Combining Skins - Advanced - Runtime Repacking with Normalmaps](http://esotericsoftware.com/spine-unity#Combining-Skins) for further info and example usage code. + - `BoneFollower` can now optionally follow (uniform) world scale of the reference bone. There is now a `Mode` dropdown selector in the Inspector which can be set to either `Local` or `World Uniform`. + - All `Spine/SkeletonGraphic` shaders now provide a parameter `CanvasGroup Compatible` which can be enabled to support `CanvasGroup` alpha blending. For correct results, you should then disable `Pma Vertex Colors` in the `SkeletonGraphic` Inspector, in section `Advanced` (otherwise Slot alpha will be applied twice). + - **Now supporting Universal Render Pipeline (URP), including the 2D Renderer pipeline, through an additional UPM package.** + + - **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + + - a) the `Packages` directory in your project where it will automatically be loaded, or + - b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + The Project panel should now show an entry `Spine Universal RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + + - **Usage:** The package provides two shaders specifically built for the universal render pipeline: + - `Universal Render Pipeline/Spine/Skeleton`, as a universal variant of the `Spine/Skeleton` shader, + - `Universal Render Pipeline/Spine/Skeleton Lit`, as a universal variant of the `Spine/Skeleton Lit` shader, + - `Universal Render Pipeline/Spine/Sprite`, as a universal variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the universal render pipeline, + - `Universal Render Pipeline/2D/Spine/Skeleton Lit`, as a universal 2D Renderer variant of the `Spine/Skeleton Lit` shader, and + - `Universal Render Pipeline/2D/Spine/Sprite`, as a universal 2D Renderer variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders. + The shaders can be assigned to materials as usual and will respect your settings of the assigned `UniversalRenderPipelineAsset` under `Project Settings - Graphics`. + - **Restrictions** As all Spine shaders, the URP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + - **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.urp-shaders-3.8/Examples/URP Shaders.unity` that demonstrates usage of the URP shaders. + + - Spine Preferences now provide an **`Atlas Texture Settings`** parameter for applying customizable texture import settings at all newly imported Spine atlas textures. + When exporting atlas textures from Spine with `Premultiply alpha` enabled (the default), you can leave it at `PMATexturePreset`. If you have disabled `Premultiply alpha`, set it to the included `StraightAlphaTexturePreset` asset. You can also create your own `TextureImporter` `Preset` asset and assign it here (include `PMA` or `Straight` in the name). In Unity versions before 2018.3 you can use `Texture2D` template assets instead of the newer `Preset` assets. Materials created for imported textures will also have the `Straight Alpha Texture` parameter configured accordingly. + - All `Sprite` shaders (including URP and LWRP extension packages) now provide an additional `Fixed Normal Space` option `World-Space`. PReviously options were limited to `View-Space` and `Model-Space`. + - `SkeletonGraphic` now fully supports [`SkeletonUtility`](https://esotericsoftware.com/spine-unity-utility-components#SkeletonUtility) for generating a hierarchy of [`SkeletonUtilityBones`](https://esotericsoftware.com/spine-unity-utility-components#SkeletonUtilityBone) in both modes `Follow` and `Override`. This also enables creating hinge chain physics rigs and using `SkeletonUtilityConstraints` such as `SkeletonUtilityGroundConstraint` and `SkeletonUtilityEyeConstraint` on `SkeletonGraphic`. + - Added **native support for slot blend modes** `Additive`, `Multiply` and `Screen` with automatic assignment at newly imported skeleton assets. `BlendModeMaterialAssets` are now obsolete and replaced by the native properties at `SkeletonDataAsset`. The `SkeletonDataAsset` Inspector provides a new `Blend Modes - Upgrade` button to upgrade an obsolete `BlendModeMaterialAsset` to the native blend modes properties. This upgrade will be performed automatically on imported and re-imported assets. + - `BoneFollower` and `BoneFollowerGraphic` components now provide better support for following bones when the skeleton's Transform is not the parent of the follower's Transform. Previously e.g. rotating a common parent Transform did not lead to the desired result, as well as negatively scaling a skeleton's Transform when it is not a parent of the follower's Transform. + - **Linear color space:** Previously Slot colors were not displayed the same in Unity as in the Spine Editor (when configured to display as `Linear` color space in Spine Editor Settings). This is now fixed at all shaders, including URP and LWRP shaders. + - All Spine shaders (also including URP and LWRP shaders) now support `PMA Vertex Colors` in combination with `Linear` color space. Thus when using Spine shaders, you should always enable `PMA Vertex Colors` at the `SkeletonRenderer` component. This allows using single pass `Additive` Slots rendering. Note that textures shall still be exported as `Straight alpha` when using `Linear` color space, so combine `PMA Vertex Colors` with `Straight Texture`. All `Sprite` shaders now provide an additional blend mode for this, named `PMA Vertex, Straight Texture` which shall be the preferred Sprite shader blend mode in `Linear` color space. + - Additive Slots have always been lit before they were written to the target buffer. Now all lit shaders provide an additional parameter `Light Affects Additive` which defaults to `false`, as it is the more intuitive default value. You can enable the old behaviour by setting this parameter to `true`. + - `SkeletonRootMotion` and `SkeletonMecanimRootMotion` components now support arbitrary bones in the hierarchy as `Root Motion Bone`. Previously there were problems when selecting a non-root bone as `Root Motion Bone`. `Skeleton.ScaleX` and `.ScaleY` and parent bone scale is now respected as well. + - URP and LWRP `Sprite` and `SkeletonLit` shaders no longer require `Advanced - Add Normals` enabled to properly cast and receive shadows. It is recommended to disable `Add Normals` if normals are otherwise not needed. + - Added an example component `RootMotionDeltaCompensation` located in `Spine Examples/Scripts/Sample Components` which can be used for applying simple delta compensation. You can enable and disable the component to toggle delta compensation of the currently playing animation on and off. + - `SkeletonRagdoll` and `SkeletonRagdoll2D` now support bone scale at any bone in the skeleton hierarchy. This includes negative scale and root bone scale. + - `Attachment.GetRemappedClone(Sprite)` method now provides an additional optional parameter `useOriginalRegionScale`. When set to `true`, the replaced attachment's scale is used instead of the Sprite's `Pixel per Unity` setting, allowing for more consistent scaling. _Note:_ When remapping Sprites, be sure to set the Sprite's `Mesh Type` to `Full Rect` and not `Tight`, otherwise the scale will be wrong. + - `SkeletonGraphic` now **supports all Slot blend modes** when `Advanced - Multiple Canvas Renderers` is enabled in the Inspector. The `SkeletonGraphic` Inspector now provides a `Blend Mode Materials` section where you can assign `SkeletonGraphic` materials for each blend mode, or use the new default materials. New `SkeletonGraphic` shaders and materials have been added for each blend mode. The `BlendModes.unity` example scene has been extended to demonstrate this new feature. For detailed information see the [`SkeletonGraphic documentation page`](http://esotericsoftware.com/spine-unity#Parameters). + - Timeline clips now also offer `Don't End with Clip` and `Clip End Mix Out Duration` parameters. By default when empty space follows the clip on the timeline, the empty animation is set on the track with a MixDuration of `Clip End Mix Out Duration`. Set `Don't End with Clip` to `true` to continue playing the clip's animation instead and mimic the old 3.8 behaviour. If you prefer pausing the animation instead of mixing out to the empty animation, set `Clip End Mix Out Duration` to a value less than 0, then the animation is paused instead. + - Prefabs containing `SkeletonRenderer`, `SkeletonAnimation` and `SkeletonMecanim` now provide a proper Editor preview, including the preview thumbnail. + - `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`) now provide a property `Advanced - Fix Prefab Override MeshFilter`, which when enabled fixes the prefab always being marked as changed. It sets the MeshFilter's hide flags to `DontSaveInEditor`. Unfortunately this comes at the cost of references to the `MeshFilter` by other components being lost, therefore this parameter defaults to `false` to keep the safe existing behaviour. + - `BoundingBoxFollower` and `BoundingBoxFollowerGraphic` now provide previously missing `usedByEffector` and `usedByComposite` parameters to be set at all generated colliders. + - `BoneFollower` and `BoneFollowerGraphic` now provide an additional `Follow Parent World Scale` parameter to allow following simple scale of parent bones (rotated/skewed scale can't be supported). + - Improved `Advanced - Fix Prefab Override MeshFilter` property for `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`), now providing an additional option to use a global value which can be set in `Edit - Preferences - Spine`. + - Timeline naming improvements: `Spine AnimationState Clip` Inspector parameter `Custom Duration` changed and inverted to `Default Mix Duration` for more clarity. Shortened all Timeline add track menu entries from: `Spine.Unity.Playables - ` to `Spine - `, `Spine Animation State Track` to `SkeletonAnimation Track`, `Spine AnimationState Graphic Track` to `SkeletonGraphic Track`, and `Spine Skeleton Flip Track` to `Skeleton Flip Track`. + - Timeline track appearance and Inspector: Tracks now show icons and track colors to make them easier to distinguish. When a Track is selected, the Inspector now shows an editable track name which was previously only editable at the Timeline asset. + - Added example component `SkeletonRenderTexture` to render a `SkeletonRenderer` to a `RenderTexture`, mainly for proper transparency. Added an example scene named `RenderTexture FadeOut Transparency` that demonstrates usage for a fadeout transparency effect. + - Added another fadeout example component named `SkeletonRenderTextureFadeout` which takes over transparency fadeout when enabled. You can use this component as-is, attach it in disabled state and enable it to start a fadeout effect. + - Timeline clips now offer an additional `Alpha` parameter for setting a custom constant mix alpha value other than 1.0, just as `TrackEntry.Alpha`. Defaults to 1.0. + - `SkeletonGraphic` now provides additional render callback delegates `OnInstructionsPrepared`, `AssignMeshOverrideSingleRenderer` and `AssignMeshOverrideMultipleRenderers`. `OnInstructionsPrepared` is raised at the end of LateUpdate after render instructions are done, target renderers are prepared, and the mesh is ready to be generated. The two `AssignMeshOverride` delegates allow separate code to take over mesh and material assignment of a `SkeletonGraphic` component. + - Added example component `SkeletonGraphicRenderTexture` to render a `SkeletonGraphic` to a `RenderTexture` (similar as `SkeletonRenderTexture`), mainly for proper transparency. Extended example scene `RenderTexture FadeOut Transparency` accordingly. + +- **Changes of default values** + +- **Deprecated** + +- **Restructuring (Non-Breaking)** + +### XNA/MonoGame + +- Added normalmap support via `SpineEffectNormalmap` and support for loading multiple texture layers following a suffix-pattern. Please see the example code on how to use them. +- Added `Z` property to `SkeletonRenderer` to provide a constant Z offset that's added to all vertices. +- Added `ZSpacing` property to `SkeletonRenderer` to allow specifying the distance on the z-axis between attachments. +- SkeletonDebugRenderer bone color attributes are now public and modifiable by user. + +## Java + +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `Region.names` and `Region.values`. +- Added support for reverse animation playback via `TrackEntry.getReverse()` and `TrackEntry.setReverse()`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. +- **Breaking change:** Removed `SkeletonData` and `Skeleton` methods: `findBoneIndex`, `findSlotIndex`. Bones and slots have an `index` field that should be used instead. + +### libGDX + +- Exposed colors in `SkeletonRendererDebug`. +- Updated to libGDX 1.10.0. + +## Lua + +- Expose non-essential colors on bones, bounding box, clipping, and path attachments. +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +- Added support for reverse animation playback via `TrackEntry.reverse`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. + +### Love2D + +### Corona + +- **Breaking change:** spine-corona has been renamed to spine-solar2d. Change your `require "spine-corona.spine"` statements to `require "spine-solar2d.spine"` + +## Typescript/Javascript + +- **Breaking change:** refactored to ECMAScript modules. See this [blog post](http://esotericsoftware.com/blog/spine-goes-npm) as well as the updated [README.md](spine-ts/README.md). +- **Breaking change:** the `build/` folder and compiled artifacts are no longer part of the repository. Instead, `npm run build` in `spine-ts/` to generate ECMAScript modules and IIFE modules in `spine-/dist`. +- **Breaking change:** the `.npmignore` and `package.json` files in the root directory have been deleted. Use the corresponding files in `spine-ts/` instead, or better, depend on the packages from the NPM registry. +- Updated runtime to be compatible with TypeScript 3.6.3. +- Added `AssetManager#setRawDataURI(path, data)`. Allows to set raw data URIs for a specific path, which in turn enables embedding assets into JavaScript/HTML. +- Expose non-essential colors on bones, bounding box, clipping, and path attachments. +- Timeline API has been extended to support component-wise timelines exported by Spine 4.0. +- Added `AnimationState.clearNext()` which removes the given `TrackEntry` and all entries after it. +- Added support for texture atlas key value pairs, see `AtlasRegion.names` and `AtlasRegion.values`. +- Added support for reverse animation playback via `TrackEntry.reverse`. +- Added proportional spacing mode support for path constraints. +- Added support for uniform scaling for two bone IK. +- Fixed applying a constraint reverting changes from other constraints. +- `AssetManager` constructor now takes an option `Downloader` instance. Used to download assets only once and share them between `AssetManager` instances. +- Added web worker support to `AssetManager`. +- Added various default parameters to `AnimationState` methods for ease of use. +- Added `SpineCanvas`, a simpler way to render a scene via spine-webgl. See `spine-ts/spine-webgl/examples/barebones.html` and `spine-ts/spine-webgl/examples/mix-and-match.html`. + +### WebGL backend + +- **Breaking change:** removed `SharedAssetManager`. Use `AssetManager` with a shared `Downloader` instance instead. +- **Breaking change:** the global object `spine.webgl` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.webgl.` in your source code with `spine.`. + +### Canvas backend + +- Renderer now accounts for whitespace stripping. +- **Breaking change:** the global object `spine.canvas` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.canvas.` in your source code with `spine.`. + +### Three.js backend + +- `SkeletonMesh` now takes an optional `SkeletonMeshMaterialParametersCustomizer` function that allows you to modify the `ShaderMaterialParameters` before the material is finalized. Use it to modify things like THREEJS' `Material.depthTest` etc. See #1590. +- **Breaking change:** the global object `spine.canvas` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.threejs.` in your source code with `spine.`. +- **Breaking change:** the default fragment shader of `SkeletonMeshMaterial` now explicitely discards fragments with alpha < 0.5. See https://github.com/EsotericSoftware/spine-runtimes/issues/1985 +- **Breaking change:** reversal of the previous breaking change: the default fragment shader of `SkeletonMeshMaterial` does no longer discard fragments with alpha < 0.5. Pass a `SkeletonMeshMaterialParametersCustomizer` to the `SkeletonMesh` constructor, and modify `parameters.alphaTest` to be > 0. + +### Player + +- Added `SpinePlayerConfig.rawDataURIs`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. See the example for a demonstration. +- Added `SpinePlayerConfig.frame`. If set, the callback is called each frame, before the skeleton is posed or drawn. +- Added `SpinePlayerConfig.update`. If set, the callback is called each frame, just after the skeleton is posed. +- Added `SpinePlayerConfig.draw`. If set, the callback is called each frame, just after the skeleton is drawn. +- Added `SpinePlayerConfig.downloader`. The `spine.Downloader` instance can be shared between players so assets are only downloaded once. +- If `SpinePlayerConfig.jsonURL` ends with an anchor, the anchor text is used to find the skeleton in the specified JSON file. +- Added `SpinePlayer.dispose()`, disposes all CPU and GPU side resources, removes all listeners, and removes the player DOM from the parent. + +# 3.8 + +## AS3 + +- **Breaking changes** + + - Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + - Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + - Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + - Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + - Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. + +- **Additions** + - Added `SkeletonBinary` to load binary `.skel` files. See `MixAndMatchExample.as` in `spine-startling-example`. + - Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `Skin#getAttachments()`. Returns all attachments in the skin. + - Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + - Added `Skin#addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `Skin#copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + +### Starling + +- Added `MixAndMatchExample.as` to demonstrate the new Skin API additions and how to load binary `.skel` files. +- Switched projects from FDT to Visual Studio Code. See updated `README.md` files for instructions. + +## C + +- **Breaking changes** + + - Renamed `spSlot#attachmentVertices` to `spSlot#deform`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `spSkin_addAttachment()` to `Skin#spSkin_addAttachment()`. + - Removed `spVertexAttachment_applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `spDeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `inheritDeform` field, getter, and setter from `spMeshAttachment`. + - Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + - Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +- **Additions** + - Added `x` and `y` coordinates for setup pose AABB in `spSkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `spSkin_getAttachments()`. Returns all attachments in the skin. + - Added `spSkin_getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + - Added `spSkin_addSkin(spSkin* skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `spSkin_copySkin(spSkin* skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `spVertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - All attachments inserted into skins are reference counted. When the last skin referencing an attachment is disposed, the attachment will also be disposed. + - Added `spAttachment_copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `spMeshAttachment_newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + +### Cocos2d-Objc + +- Added mix-and-match example to demonstrate the new Skin API. +- Added `IKExample`. +- Added `SkeletonAnimation preUpdateWorldTransformsListener` and `SkeletonAnimation postUpdateWorldTransformsListener`. When set, these callbacks will be invokved before and after the skeleton's `updateWorldTransforms()` method is called. See the `IKExample` how it can be used. + +### SFML + +- Added mix-and-match example to demonstrate the new Skin API. +- Added `IKExample`. + +## C++ + +- **Breaking Changes** + + - Renamed `Slot::getAttachmentVertices()` to `Slot::getDeform()`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `Skin::addAttachment()` to `Skin::setAttachment()`. + - Removed `VertexAttachment::applyDeform()` and replaced it with `VertexAttachment::getDeformAttachment()`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `_inheritDeform` field, getter, and setter from `MeshAttachment`. + - Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + - Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +- **Additions** + - `AnimationState` and `TrackEntry` now also accept a subclass of `AnimationStateListenerObject` as a listener for animation events in the overloaded `setListener()` method. + - `SkeletonBinary` and `SkeletonJson` now parse and set all non-essential data like audio path. + - Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `Skin#getAttachments()`. Returns all attachments in the skin. + - Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + - Added `Skin#addSkin(Skin &skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `Skin#copySkin(Skin &skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - All attachments inserted into skins are reference counted. When the last skin referencing an attachment is disposed, the attachment will also be disposed. + - Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + - Exposed `x` and `y` on `SkeletonData` through getters and setters. + +### Cocos2d-x + +- Updated to cocos2d-x 3.17.1 +- Added mix-and-match example to demonstrate the new Skin API. +- Exmaple project requires Visual Studio 2019 on Windows +- Added `IKExample`. +- Added `SkeletonAnimation::setPreUpdateWorldTransformsListener()` and `SkeletonAnimation::setPreUpdateWorldTransformsListener()`. When set, these callbacks will be invokved before and after the skeleton's `updateWorldTransforms()` method is called. See the `IKExample` how it can be used. + +### SFML + +- Added mix-and-match example to demonstrate the new Skin API. + +### UE4 + +- Added `bAutoPlaying` flag to `USpineSkeletonAnimationComponent`. When `false`, the component will not update the internal animation state and skeleton. +- Updated example project to UE 4.22. +- (Re-)Importing Spine assets will perform a version compatibility check and alert users about mismatches in editor mode. +- `USpineSkeletonRendererComponent` allows passing a `USpineSkeletonComponent` to update it. This way, the renderer component can be used without a skeleton component on the same actor. +- Added blueprint-callable methods to `SpineSkeletonComponent` and `SpineSkeletonAnimationComponent` to query and set skins, and enumerate bones, slots, and animations. +- Extended skeleton data editor preview. The preview now shows bones, slots, animations, and skins found in the skeleton data. See this [blog post](http://esotericsoftware.com/blog/Unreal-Engine-4-quality-of-life-improvements). +- Added preview animation and skin fields, allowing you to preview animations and skins right in the editor. See this [blog post](http://esotericsoftware.com/blog/Unreal-Engine-4-quality-of-life-improvements). +- Removed dependency on `RHI`, `RenderCore`, and `ShaderCore`. +- Re-importing atlases and their textures now works consistently in all situations. +- Added mix-and-match example to demonstrate the new Skin API. +- Materials on `SkeletonRendererComponent` are now blueprint read and writeable. This allows setting dynamic material instances at runtime. +- Added `InitialSkin` property to `USpineWidget`. This allows previewing different skins in the UMG Designer. Initial skins can still be overridden via blueprint events such as `On Initialized`. +- `USpineWidget` will now report its own desired size based on the setup pose dimensions of the skeleton. This is used when selecting `Size to content` on a `USpineWidget` in the designer. +- Updated example project to UE 5.2. + +## C# + +- **Breaking changes** + + - **Changed `IkConstraintData.Bones` type from `List` to `ExposedList`** for unification reasons. _Note: this modification will most likely not affect user code._ + - Renamed `Slot.AttachmentVertices` to `Slot.Deform`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `Skin.AddAttachment()` to `Skin.SetAttachment()`. + - Removed `FindAttachmentsForSlot(int slotIndex, List attachments)` and `FindNamesForSlot (int slotIndex, List names)` and replaced it with `Skin.GetAttachments(int slotIndex, List attachments)` which returns the combined `SkinEntry` object holding both name and attachment. + - Removed `VertexAttachment.ApplyDeform()` and replaced it with `VertexAttachment.DeformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + - Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + - Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +- **Additions** + - Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `Skin.GetAttachments()`. Returns all attachments in the skin. + - Added `Skin.GetAttachments(int slotIndex, List attachments)`. Returns all attachements in the skin for the given slot index. This method replaces `FindAttachmentsForSlot` and `FindNamesForSlot`. + - Added `Skin.AddSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `Skin.CopySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - Added `Attachment.Copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `MeshAttachment.NewLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + +### Unity + +- **Breaking changes** + + - **Officially supported Unity versions are 2017.1-2020.2**. + - **Spine `.asmdef` files are again active by default**. They have previously been deactivated to `.txt` extension which is now no longer necessary. + - **Removed PoseSkeleton() and PoseWithAnimation()** extension methods to prevent issues where animations are not mixed out. Problem was that these methods did not set AnimationState, leaving incorrect state at e.g. attachments enabled at slots when starting subsequent animations. As a replacement you can use `AnimationState.ClearTrack(0);` followed by `var entry = AnimationState.SetAnimation(0, animation, loop); entry.TrackTime = time` to achieve similar behaviour. + - **The `Shadow alpha cutoff` shader parameter is now respecting slot-color alpha** values at all Spine shaders. A fragment's texture color alpha is multiplied with slot-color alpha before the result is tested against the `Shadow alpha cutoff` threshold. + - **Removed redundant `Attachment.GetClone()` and `MeshAttachment.GetLinkedClone()` extension methods**. Use methods `Attachment.Copy` and `MeshAttachment.NewLinkedMesh()` instead. + - **Renamed extension method `Attachment.GetClone(bool cloneMeshesAsLinked)` to `Attachment.GetCopy(bool cloneMeshesAsLinked)`** to follow the naming scheme of the Spine API. + - `SkeletonDataAsset.atlasAssets` is now an array of the base class `AtlasAssetBase` instead of `SpineAtlasAsset`, which provides `IEnumerable<> Materials` instead of `List<> materials`. Replace any access via `atlasAsset.materials[0]` with `atlasAsset.Materials.First()` and add a `using System.Linq;` statement. + - **Changed `MeshAttachment.GetLinkedMesh()` method signatures:** removed optional parameters `bool inheritDeform = true, bool copyOriginalProperties = false`. + - Changed namespace `Spine.Unity.Modules` to `Spine.Unity` and `Spine.Unity.Examples` after restructuring (see section below) in respective classes: + - When receiving namespace related errors, replace using statements of `using Spine.Unity.Modules.AttachmentTools;` with `using Spine.Unity.AttachmentTools;`. You can remove `using Spine.Unity.Modules;` statements when a `using Spine.Unity` statement is already present in the file. + - `AttachmentTools`, `SkeletonPartsRenderer`, `SkeletonRenderSeparator`, `SkeletonRendererCustomMaterials` changed to namespace `Spine.Unity`. + - `SkeletonGhost`, `SkeletonGhostRenderer`, `AtlasRegionAttacher`, `SkeletonGraphicMirror`, `SkeletonRagdoll`, `SkeletonRagdoll2D`, `SkeletonUtilityEyeConstraint`, `SkeletonUtilityGroundConstraint`, `SkeletonUtilityKinematicShadow` changed to namespace `Spine.Unity.Examples`. + - Split `Editor/Utility/SpineEditorUtilities` class into multiple files with partial class qualifier. + - Nested classes `SpineEditorUtilities.AssetUtility` and `SpineEditorUtilities.EditorInstantiation` are now no longer nested. If you receive namespace related errors, replace any occurrance of + - `SpineEditorUtilities.AssetUtility` with `AssetUtility` and + - `SpineEditorUtilities.EditorInstantiation` with `EditorInstantiation`. + - **Timeline Support has been moved to a separate UPM Package** Previously the Spine Timeline integration was located in the `Modules/Timeline` directory and was deactivated by default, making it necessary to activate it via the Spine Preferences. Now the Timeline integration has been moved to an additional UPM package which can be found under `Modules/com.esotericsoftware.spine.timeline`. + - **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + a) the `Packages` directory in your project where it will automatically be loaded, or + b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + The Project panel should now show an entry `Spine Timeline Extensions` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + - `SkeletonMecanim`'s `Layer Mix Mode` enum name `MixMode.SpineStyle` has been renamed to `MixMode.Hard`. This is most likely not set via code and thus unlikely to be a problem. Serialized scenes and prefabs are unaffected. + - `SkeletonRootMotion` and `SkeletonMecanimRootMotion` components now support arbitrary bones in the hierarchy as `Root Motion Bone`. Previously there were problems when selecting a non-root bone as `Root Motion Bone`. `Skeleton.ScaleX` and `.ScaleY` and parent bone scale is now respected as well. + +- **Additions** + + - **Spine Preferences stored in Assets/Editor/SpineSettings.asset** Now Spine uses the new `SettingsProvider` API, storing settings in a SpineSettings.asset file which can be shared with team members. Your old preferences are automatically migrated to the new system. + - Added support for Unity's SpriteMask to `SkeletonAnimation` and `SkeletonMecanim`. All mask interaction modes are supported. See this [blog post](http://esotericsoftware.com/blog/Unity-SpriteMask-and-RectMask2D-support). + - Added support for Unity's RectMask2D to SkeletonGraphics. See this [blog post](http://esotericsoftware.com/blog/Unity-SpriteMask-and-RectMask2D-support). + - Added `Create 2D Hinge Chain` button at `SkeletonUtilityBone` inspector, previously only `Create 3D Hinge Chain` was available. + - **Now supporting Lightweight Render Pipeline (LWRP) through an additional UPM package.** + + - **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + + - a) the `Packages` directory in your project where it will automatically be loaded, or + - b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + > If you are using git and Unity 2019.2 or newer versions and receive an error that dependencies could not be resolved by the package manager (only higher versions of Unity's `Lightweight RP` package are available, e.g. `6.9.0` and up), please copy the prepared package-UNITYVERSION.json file for your Unity version (e.g. `package-2019.2.json`) over the existing package.json file to change the dependency accordingly. Unfortunately Unity's Package Manager does not provide a way to specify a version range for a dependency like "5.7.2 - 6.9.0" yet, so this manual step is necessary for git users. + + The Project panel should now show an entry `Spine Lightweight RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + + - **Usage:** The package provides two shaders specifically built for the lightweight render pipeline: + - `Lightweight Render Pipeline/Spine/Skeleton`, as a lightweight variant of the `Spine/Skeleton` shader, + - `Lightweight Render Pipeline/Spine/Skeleton Lit`, as a lightweight variant of the `Spine/Skeleton Lit` shader and + - `Lightweight Render Pipeline/Spine/Sprite`, as a lightweight variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the lightweight render pipeline. The shaders can be assigned to materials as usual and will respect your settings of the assigned `LightweightRenderPipelineAsset` under `Project Settings - Graphics`. + - **Restrictions** As all Spine shaders, the LWRP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + - **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.lwrp-shaders-3.8/Examples/LWRP Shaders.unity` that demonstrates usage of the LWRP shaders. + + - Added `Spine/Skeleton Lit ZWrite` shader. This variant of the `Spine/Skeleton Lit` shader writes to the depth buffer with configurable depth alpha threshold. Apart from that it is identical to `Spine/Skeleton Lit`. + - Additional yield instructions to wait for animation track events `End`, `Complete` and `Interrupt`. + - `WaitForSpineAnimationComplete` now proves an additional `bool includeEndEvent` parameter, defaults to `false` (previous behaviour). + - Added a new `WaitForSpineAnimationEnd` yield instruction. + - Added a new generic `WaitForSpineAnimation` yield instruction which can be configured to wait for any combination of animation track events. It is now used as base class for `WaitForSpineAnimationComplete` and `WaitForSpineAnimationEnd`. + - Additional **Fix Draw Order** parameter at SkeletonRenderer, defaults to `disabled` (previous behaviour). + Applies only when 3+ submeshes are used (2+ materials with alternating order, e.g. "A B A"). + If true, MaterialPropertyBlocks are assigned at each material to prevent aggressive batching of submeshes + by e.g. the LWRP renderer, leading to incorrect draw order (e.g. "A1 B A2" changed to "A1A2 B"). + You can leave this parameter disabled when everything is drawn correctly to save the additional performance cost. + - **Additional Timeline features.** SpineAnimationStateClip now provides a `Speed Multiplier`, a start time offset parameter `Clip In`, support for blending successive animations by overlapping tracks. An additional `Use Blend Duration` parameter _(defaults to true)_ allows for automatic synchronisation of MixDuration with the current overlap blend duration. An additional Spine preferences parameter `Use Blend Duration` has been added which can be disabled to default to the previous behaviour before this update. + - Additional `SpriteMask and RectMask2D` example scene added for demonstration of mask setup and interaction. + - `Real physics hinge chains` for both 2D and 3D physics. The [SkeletonUtilityBone](https://esotericsoftware.com/spine-unity-utility-components#SkeletonUtilityBone) Inspector provides an interface to create 2D and 3D hinge chains. Previously created chains have only been respecting gravity, but not momentum of the skeleton or parent bones. The new physics rig created when pressing `Create 3D Hinge Chain` and `Create 2D Hinge Chain` creates a more complex setup that also works when flipping the skeleton. Note that the chain root node is no longer parented to bones of the skeleton. This is a requirement in Unity to have momentum applied properly - do not reparent the chain root to bones of your skeleton, or you will loose any momentum applied by the skeleton's movement. + - `Outline rendering functionality for all shaders.` Every shader now provides an additional set of `Outline` parameters to enable custom outline rendering. When outline rendering is enabled via the `Material` inspector, it automatically switches the shader to the respective `Spine/Outline` shader variant. Outlines are generated by sampling neighbour pixels, so be sure to add enough transparent padding when exporting your atlas textures to fit the desired outline width. In order to enable outline rendering at a skeleton, it is recommended to first prepare an additional outline material copy and then switch the material of the target skeleton to this material. This prevents unnecessary additional runtime material copies and drawcalls. Material switching can be prepared via a [SkeletonRendererCustomMaterials](https://esotericsoftware.com/spine-unity-utility-components#SkeletonRendererCustomMaterials) component and then enabled or disabled at runtime. Alternatively, you can also directly modify the `SkeletonRenderer.CustomMaterialOverride` property. + Outline rendering is fully supported on `SkeletonGraphic` shaders as well. + - Added `SkeletonRenderer.EditorSkipSkinSync` scripting API property to be able to set custom skins in editor scripts. Enable this property when overwriting the Skeleton's skin from an editor script. Without setting this parameter, changes will be overwritten by the next inspector update. Only affects Inspector synchronisation of skin with `initialSkinName`, not startup initialization. + - All `Spine/SkeletonGraphic` shaders now provide a parameter `CanvasGroup Compatible` which can be enabled to support `CanvasGroup` alpha blending. For correct results, you should then disable `Pma Vertex Colors` in the `SkeletonGraphic` Inspector, in section `Advanced` (otherwise Slot alpha will be applied twice). + - **Now supporting Universal Render Pipeline (URP), including the 2D Renderer pipeline, through an additional UPM package.** + + - **Installation:** You can download the Unity Package Manager (UPM) package via the [download page](http://esotericsoftware.com/spine-unity-download) or find it in the [spine-runtimes/spine-unity/Modules](https://github.com/EsotericSoftware/spine-runtimes/tree/3.8-beta/spine-unity/Modules) subdirectory on the git repository. You can then either unzip (copy if using git) the package to + + - a) the `Packages` directory in your project where it will automatically be loaded, or + - b) to an arbitrary directory outside the Assets directory and then open Package Manager in Unity, select the `+` icon, choose `Add package from disk..` and point it to the package.json file. + + The Project panel should now show an entry `Spine Universal RP Shaders` under `Packages`. If the directory is not yet listed, you will need to close and re-open Unity to have it display the directory and its contents. + + - **Usage:** The package provides two shaders specifically built for the universal render pipeline: + - `Universal Render Pipeline/Spine/Skeleton`, as a universal variant of the `Spine/Skeleton` shader, + - `Universal Render Pipeline/Spine/Skeleton Lit`, as a universal variant of the `Spine/Skeleton Lit` shader, + - `Universal Render Pipeline/Spine/Sprite`, as a universal variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders, which were not functioning in the universal render pipeline, + - `Universal Render Pipeline/2D/Spine/Skeleton Lit`, as a universal 2D Renderer variant of the `Spine/Skeleton Lit` shader, and + - `Universal Render Pipeline/2D/Spine/Sprite`, as a universal 2D Renderer variant of the `Spine/Sprite/Vertex Lit` and `Pixel Lit` shaders. + The shaders can be assigned to materials as usual and will respect your settings of the assigned `UniversalRenderPipelineAsset` under `Project Settings - Graphics`. + - **Restrictions** As all Spine shaders, the URP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`. + - **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.urp-shaders-3.8/Examples/URP Shaders.unity` that demonstrates usage of the URP shaders. + + - Spine Preferences now provide an **`Atlas Texture Settings`** parameter for applying customizable texture import settings at all newly imported Spine atlas textures. + When exporting atlas textures from Spine with `Premultiply alpha` enabled (the default), you can leave it at `PMATexturePreset`. If you have disabled `Premultiply alpha`, set it to the included `StraightAlphaTexturePreset` asset. You can also create your own `TextureImporter` `Preset` asset and assign it here (include `PMA` or `Straight` in the name). In Unity versions before 2018.3 you can use `Texture2D` template assets instead of the newer `Preset` assets. Materials created for imported textures will also have the `Straight Alpha Texture` parameter configured accordingly. + - All `Sprite` shaders (including URP and LWRP extension packages) now provide an additional `Fixed Normal Space` option `World-Space`. PReviously options were limited to `View-Space` and `Model-Space`. + - `SkeletonGraphic` now fully supports [`SkeletonUtility`](https://esotericsoftware.com/spine-unity-utility-components#SkeletonUtility) for generating a hierarchy of [`SkeletonUtilityBones`](https://esotericsoftware.com/spine-unity-utility-components#SkeletonUtilityBone) in both modes `Follow` and `Override`. This also enables creating hinge chain physics rigs and using `SkeletonUtilityConstraints` such as `SkeletonUtilityGroundConstraint` and `SkeletonUtilityEyeConstraint` on `SkeletonGraphic`. + - Added `OnMeshAndMaterialsUpdated` callback event to `SkeletonRenderer` and `SkeletonGraphic`. It is issued at the end of `LateUpdate`, before rendering. + - Added `Skeleton-OutlineOnly` single pass shader to LWRP and URP extension modules. It can be assigned to materials as `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly`. This allows for separate outline child _GameObjects_ that reference the existing Mesh of their parent, and re-draw the mesh using this outline shader. + - Added example component `RenderExistingMesh` to render a mesh again with different materials, as required by the new `Skeleton-OutlineOnly` shaders. + In URP the outline has to be rendered via a separate GameObject as URP does not allow multiple render passes. To add an outline to your SkeletenRenderer: + 1. Add a child GameObject and move it a bit back (e.g. position Z = 0.01). + 2. Add a `RenderExistingMesh` component, provided in the `Spine Examples/Scripts/Sample Components` directory. + 3. Copy the original material, add _\_Outline_ to its name and set the shader to `Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly`. + 4. Assign this _\_Outline_ material at the `RenderExistingMesh` component under _Replacement Materials_. + - Added `Outline Shaders URP` example scene to URP extension module to demonstrate the above additions. + - Added support for Unity's [`SpriteAtlas`](https://docs.unity3d.com/Manual/class-SpriteAtlas.html) as atlas provider (as an alternative to `.atlas.txt` and `.png` files) alongside a skeleton data file. There is now an additional `Spine SpriteAtlas Import` tool window accessible via `Window - Spine - SpriteAtlas Import`. Additional information can be found in a new section on the [spine-unity documentation page](http://esotericsoftware.com/spine-unity#Advanced---Using-Unity-SpriteAtlas-as-Atlas-Provider). + - Added support for **multiple atlas textures at `SkeletonGraphic`**. You can enable this feature by enabling the parameter `Multiple CanvasRenders` in the `Advanced` section of the `SkeletonGraphic` Inspector. This automatically creates the required number of child `CanvasRenderer` GameObjects for each required draw call (submesh). + - Added support for **Render Separator Slots** at `SkeletonGraphic`. Render separation can be enabled directly in the `Advanced` section of the `SkeletonGraphic` Inspector, it does not require any additional components (like `SkeletonRenderSeparator` or `SkeletonPartsRenderer` for `SkeletonRenderer` components). When enabled, additional separator GameObjects will be created automatically for each separation part, and `CanvasRenderer` GameObjects re-parented to them accordingly. The separator GameObjects can be moved around and re-parented in the hierarchy according to your requirements to achieve the desired draw order within your `Canvas`. A usage example can be found in the updated `Spine Examples/Other Examples/SkeletonRenderSeparator` scene. + - Added `SkeletonGraphicCustomMaterials` component, providing functionality to override materials and textures of a `SkeletonGraphic`, similar to `SkeletonRendererCustomMaterials`. Note: overriding materials or textures per slot is not provided due to structural limitations. + - Added **Root Motion support** for `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic` via new components `SkeletonRootMotion` and `SkeletonMecanimRootMotion`. The `SkeletonAnimation` and `SkeletonGraphic` component Inspector now provides a line `Root Motion` with `Add Component` and `Remove Component` buttons to add/remove the new `SkeletonRootMotion` component to your GameObject. The `SkeletonMecanim` Inspector detects whether root motion is enabled at the `Animator` component and adds a `SkeletonMecanimRootMotion` component automatically. + - `SkeletonMecanim` now provides an additional `Custom MixMode` parameter under `Mecanim Translator`. It is enabled by default in version 3.8 to maintain current behaviour, using the set `Mix Mode` for each Mecanim layer. When disabled, `SkeletonMecanim` will use the recommended `MixMode` according to the layer blend mode. Additional information can be found in the [Mecanim Translator section](http://esotericsoftware.com/spine-unity#Parameters-for-animation-blending-control) on the spine-unity documentation pages. + - Added **SkeletonGraphic Timeline support**. Added supprot for multi-track Timeline preview in the Editor outside of play mode (multi-track scrubbing). See the [Timeline-Extension-UPM-Package](http://esotericsoftware.com/spine-unity#Timeline-Extension-UPM-Package) section of the spine-unity documentation for more information. + - Added support for double-sided lighting at all `SkeletonLit` shaders (including URP and LWRP packages). + - Added frustum culling update mode parameters `Update When Invisible` (Inspector parameter) and `UpdateMode` (available via code) to all Skeleton components. This provides a simple way to disable certain updates when the `Renderer` is no longer visible (outside all cameras, culled in frustum culling). The new `UpdateMode` property allows disabling updates at a finer granularity level than disabling the whole component. Available modes are: `Nothing`, `OnlyAnimationStatus`, `EverythingExceptMesh` and `FullUpdate`. + - Added a new `Spine/Outline/OutlineOnly-ZWrite` shader to provide correct outline-only rendering. Note: the shader requires two render passes and is therefore not compatible with URP. The `Spine Examples/Other Examples/Outline Shaders` example scene has been updated to demonstrate the new shader. + - Added `OnMeshAndMaterialsUpdated` callback event to `SkeletonRenderSeparator` and `SkeletonPartsRenderer`. It is issued at the end of `LateUpdate`, before rendering. + - Added `Root Motion Scale X/Y` parameters to `SkeletonRootMotionBase` subclasses (`SkeletonRootMotion` and `SkeletonMecanimRootMotion`). Also providing `AdjustRootMotionToDistance()` and other methods to allow for easy delta compensation. Delta compensation can be used to e.g. stretch a jump to a given distance. Root motion can be adjusted at the start of an animation or every frame via `skeletonRootMotion.AdjustRootMotionToDistance(targetPosition - transform.position, trackIndex);`. + - Now providing a `Canvas Group Tint Black` parameter at the `SkeletonGraphic` Inspector in the `Advanced` section. When using the `Spine/SkeletonGraphic Tint Black` shader you can enable this parameter to receive proper blending results when using `Additive` blend mode under a `CanvasGroup`. Be sure to also have the parameter `CanvasGroup Compatible` enabled at the shader. Note that the normal `Spine/SkeletonGraphic` does not support `Additive` blend mode at a `CanvasGroup`, as it requires additional shader channels to work. + - Added `Mix and Match Skins` example scene to demonstrate how the 3.8 Skin API and combining skins can be used for a wardrobe and equipment use case. + - Spine Timeline Extensions: Added `Hold Previous` parameter at `SpineAnimationStateClip`. + - Added more warning messages at incompatible SkeletonRenderer/SkeletonGraphic Component vs Material settings. They appear both as an info box in the Inspector as well as upon initialization in the Console log window. The Inspector box warnings can be disabled via `Edit - Preferences - Spine`. + - Now providing `BeforeApply` update callbacks at all skeleton animation components (`SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic`). + - Added `BoundingBoxFollowerGraphic` component. This class is a counterpart of `BoundingBoxFollower` that can be used with `SkeletonGraphic`. + - Added Inspector context menu functions `SkeletonRenderer - Add all BoundingBoxFollower GameObjects` and `SkeletonGraphic - Add all BoundingBoxFollowerGraphic GameObjects` that automatically generate bounding box follower GameObjects for every `BoundingBoxAttachment` for all skins of a skeleton. + - `GetRemappedClone()` now provides an additional parameter `pivotShiftsMeshUVCoords` for `MeshAttachment` to prevent uv shifts at a non-central Sprite pivot. This parameter defaults to `true` to maintain previous behaviour. + - `SkeletonRenderer` components now provide an additional update mode `Only Event Timelines` at the `Update When Invisible` property. This mode saves additional timeline updates compared to update mode `Everything Except Mesh`. + - Now all URP (Universal Render Pipeline) and LWRP (Lightweight Render Pipeline) shaders support SRP (Scriptable Render Pipeline) batching. See [Unity SRPBatcher documentation pages](https://docs.unity3d.com/Manual/SRPBatcher.html) for additional information. + - Sprite shaders now provide four `Diffuse Ramp` modes as an Inspector Material parameter: `Hard`, `Soft`, `Old Hard` and `Old Soft`. In spine-unity 3.8 it defaults to `Old Hard` to keep the behaviour of existing projects unchanged. From 4.0 on it defaults to `Hard` for newly created materials while existing ones remain unchanged. Note that `Old Hard` and `Old Soft` ramp versions were using only the right half of the ramp texture, and additionally multiplying the light intensity by 2, both leading to brighter lighting than without a ramp texture active. The new ramp modes `Hard` and `Soft` use the full ramp texture and do not modify light intensity, being consistent with lighting without a ramp texture active. + - Added **native support for slot blend modes** `Additive`, `Multiply` and `Screen` with automatic assignment at newly imported skeleton assets. `BlendModeMaterialAssets` are now obsolete and replaced by the native properties at `SkeletonDataAsset`. The `SkeletonDataAsset` Inspector provides a new `Blend Modes - Upgrade` button to upgrade an obsolete `BlendModeMaterialAsset` to the native blend modes properties. This upgrade will be performed automatically on imported and re-imported assets in Unity 2020.1 and newer to prevent reported `BlendModeMaterialAsset` issues in these Unity versions. spine-unity 4.0 and newer will automatically perform this upgrade regardless of the Unity version. + - `BoneFollower` and `BoneFollowerGraphic` components now provide better support for following bones when the skeleton's Transform is not the parent of the follower's Transform. Previously e.g. rotating a common parent Transform did not lead to the desired result, as well as negatively scaling a skeleton's Transform when it is not a parent of the follower's Transform. + - URP and LWRP `Sprite` and `SkeletonLit` shaders no longer require `Advanced - Add Normals` enabled to properly cast and receive shadows. It is recommended to disable `Add Normals` if normals are otherwise not needed. + - Added an example component `RootMotionDeltaCompensation` located in `Spine Examples/Scripts/Sample Components` which can be used for applying simple delta compensation. You can enable and disable the component to toggle delta compensation of the currently playing animation on and off. + - Root motion delta compensation now allows to only adjust X or Y components instead of both. Adds two parameters to `SkeletonRootMotionBase.AdjustRootMotionToDistance()` which default to adjusting both X and Y as before. The `RootMotionDeltaCompensation` example component exposes these parameters as public attributes. + - Root motion delta compensation now allows to also add translation root motion to e.g. adjust a horizontal jump upwards or downwards over time. This is necessary because a Y root motion of zero cannot be scaled to become non-zero. + - `Attachment.GetRemappedClone(Sprite)` method now provides an additional optional parameter `useOriginalRegionScale`. When set to `true`, the replaced attachment's scale is used instead of the Sprite's `Pixel per Unity` setting, allowing for more consistent scaling. _Note:_ When remapping Sprites, be sure to set the Sprite's `Mesh Type` to `Full Rect` and not `Tight`, otherwise the scale will be wrong. + +- **Changes of default values** + + - `SkeletonMecanim`'s `Layer Mix Mode` now defaults to `MixMode.MixNext` instead of `MixMode.MixAlways`. + - `BlendModeMaterialAsset` and it's instance `Default BlendModeMaterials.asset` now have `Apply Additive Material` set to `true` by default in order to apply all blend modes by default. + +- **Deprecated** + + - Deprecated `Modules/SlotBlendModes/SlotBlendModes` component. Changed namespace from `Spine.Unity.Modules` to `Spine.Unity.Deprecated`. Moved to `Deprecated/SlotBlendModes`. + +- **Restructuring (Non-Breaking)** + + Note: The following changes will most likely not affect users of the Spine-Unity runtime as the API remains unchanged and no references are invalidated. + + - Removed duplicates of `.cginc` files in `Modules/Shaders/Sprite` that were also present in the `Modules/Shaders/Sprite/CGIncludes` directory. + - Moved shaders from `Modules/Shaders` to `Shaders` directory. + - Moved shaders from `Modules/SkeletonGraphic/Shaders` to `Shaders/SkeletonGraphic`. + - Renamed shader `Shaders/Spine-SkeletonLit.shader` to `Shaders/Spine-Skeleton-Lit.shader`. + - Moved components from `SkeletonGraphic` to `Components` and `Components/Following` except for `SkeletonGraphicMirror` which was moved to `Spine Examples/Scripts/Sample Components`. + - Moved `BoneFollower`, `BoneFollowerGraphic` and `PointFollower` from `Components` directory to `Components/Following`. + - Moved `BoundingBoxFollower` component from `Modules/BoundingBoxFollower` to `Components/Following`. + - Moved `Modules/SkeletonRenderSeparator` directory to `Components/SkeletonRenderSeparator`. + - Moved `Modules/CustomMaterials` directory to `Components/SkeletonRendererCustomMaterials`. + - Moved `Asset Types/BlendModeMaterialsAsset.cs` class, `Shaders/BlendModes/Default BlendModeMaterials.asset` and materials from `Shaders/BlendModes` to `SkeletonDataModifierAssets/BlendModeMaterials` directory. + - Moved `Modules/Ghost` directory to `Spine Examples/Scripts/Sample Components/Ghost`. + - Moved `Modules/SkeletonUtility Modules` directory to `Spine Examples/Scripts/Sample Components/SkeletonUtility Modules`. + - Moved `Modules/AnimationMatchModifier` directory to `Spine Examples/Scripts/MecanimAnimationMatchModifier`. + - Moved `SkeletonRagdoll` and `SkeletonRagdoll2D` components from `Modules/Ragdoll` directory to `Spine Examples/Scripts/Sample Components/SkeletonUtility Modules`. + - Moved `AttachmentTools.cs` to `Utility` directory. + - Split the file `AttachmentTools` into 5 separate files for each contained class. No namespace or other API changes performed. + - Split the file `Mesh Generation/SpineMesh` into 4 separate files for each contained class. No namespace or other API changes performed. + - Moved `SkeletonExtensions.cs` to `Utility` directory. + - Moved `Modules/YieldInstructions` directory to `Utility/YieldInstructions`. + - Moved corresponding editor scripts of the above components to restructured directories as well. + - Renamed inspector editor class `PointFollowerEditor` to `PointFollowerInspector` for consistency reasons. + +### XNA/MonoGame + +- Updated to latest MonoGame version 3.7.1 +- Rewrote example project to be cleaner and better demonstrate basic Spine features. +- Added mix-and-match example to demonstrate the new Skin API. +- Added normalmap support via `SpineEffectNormalmap` and support for loading multiple texture layers following a suffix-pattern. Please see the example code on how to use them. + +## Java + +- **Breaking changes** + + - Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + - Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + - Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + - `JsonRollback` tool now converts from 3.8 JSON to 3.7. + - Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +- **Additions** + - Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `Skin#getAttachments()`. Returns all attachments in the skin. + - Added `Skin#getAttachments(int slotIndex)`. Returns all attachements in the skin for the given slot index. + - Added `Skin#addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `Skin#copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + +### libGDX + +- `SkeletonViewer` can load a skeleton by specifying it as the first argument on the command line. +- Added mix-and-match example to demonstrate the new Skin API. + +## Lua + +- **Breaking changes** + + - Renamed `Slot:getAttachmentVertices()` to `Slot#deform`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `Skin:addAttachment()` to `Skin#setAttachment()`. + - Removed `VertexAttachment:applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + - Changed the `.json` file format to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + +- **Additions** + - Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `Skin:getAttachments()`. Returns all attachments in the skin. + - Added `Skin:getAttachments(slotIndex)`. Returns all attachements in the skin for the given slot index. + - Added `Skin:addSkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `Skin:copySkin(Skin skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - Added `Attachment:copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `MeshAttachment:newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + +### Love2D + +- Added support for 0-1 RGBA color component range change in Löve 0.11+. Older Löve versions using the 0-255 range are still supported! +- Added mix-and-match example to demonstrate the new Skin API. + +### Corona + +- Added mix-and-match example to demonstrate the new Skin API. + +## Typescript/Javascript + +- **Breaking changes** + + - Renamed `MixDirection.in/out` to `MixDirection.mixIn/mixOut` as it was crashing a JS compressor. + - Renamed `Slot#getAttachmentVertices()` to `Slot#getDeform()`. + - Changed the `.json` curve format and added more assumptions for omitted values, reducing the average size of JSON exports. + - Renamed `Skin#addAttachment()` to `Skin#setAttachment()`. + - Removed `VertexAttachment#applyDeform()` and replaced it with `VertexAttachment#deformAttachment`. The attachment set on this field is used to decide if a `DeformTimeline` should be applied to the attachment active on the slot to which the timeline is applied. + - Removed `inheritDeform` field, getter, and setter from `MeshAttachment`. + - Changed `.skel` binary format, added a string table. References to strings in the data resolve to this string table, reducing storage size of binary files considerably. + - Changed the `.json` and `.skel` file formats to accomodate the new feature and file size optimiations. Old projects must be exported with Spine 3.8.20+ to be compatible with the 3.8 Spine runtimes. + - Updated runtime to be compatible with TypeScript 3.6.3. + +- **Additions** + - Added support for loading binary data via `AssetManager#loadBinary()`. `AssetManager#get()` will return a `Uint8Array` for such assets. + - Added support for loading binaries via new `SkeletonBinary`. Parses a `Uint8Array`. + - Added `x` and `y` coordinates for setup pose AABB in `SkeletonData`. + - Added support for rotated mesh region UVs. + - Added skin-specific bones and constraints which are only updated if the skeleton's current skin contains them. + - Improved Skin API to make it easier to handle mix-and-match use cases. + - Added `Skin#getAttachments()`. Returns all attachments in the skin. + - Added `Skin#getAttachments(slotIndex: number)`. Returns all attachements in the skin for the given slot index. + - Added `Skin#addSkin(skin: Skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. + - Added `Skin#copySkin(skin: Skin)`. Adds all attachments, bones, and skins from the specified skin to this skin. `VertexAttachment` are shallowly copied and will retain any parent mesh relationship. All other attachment types are deep copied. + - Added `Attachment#copy()` to all attachment type implementations. This lets you deep copy an attachment to modify it independently from the original, i.e. when programmatically changing texture coordinates or mesh vertices. + - Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh. + - Added IK softness. + - Added `AssetManager.setRawDataURI(path, data)`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. + - Added `AssetManager.loadAll()` to allow Promise/async/await based waiting for completion of asset load. See the `spine-canvas` examples. + - Added `Skeleton.getBoundRect()` helper method to calculate the bouding rectangle of the current pose, returning the result as `{ x, y, width, height }`. Note that this method will create temporary objects which can add to garbage collection pressure. + +### WebGL backend + +- `Input` can now take a partially defined implementation of `InputListener`. +- Added mix-and-match example to demonstrate the new Skin API. + +### Canvas backend + +### Three.js backend + +- `SkeletonMesh` now takes an optional `SkeletonMeshMaterialParametersCustomizer` function that allows you to modify the `ShaderMaterialParameters` before the material is finalized. Use it to modify things like THREEJS' `Material.depthTest` etc. See #1590. + +### Player + +- `SpinePlayer#setAnimation()` can now be called directly to set the animation being displayed. +- The player supports loading `.skel` binary skeleton files by setting the `SpinePlayerConfig#skelUrl` field instead of `SpinePlayerConfig#jsonUrl`. +- Added `SpinePlayerConfig#rawDataURIs`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. See the example for a demonstration. + +# 3.7 + +## AS3 + +- **Breaking changes** + - The completion event will fire for looped 0 duration animations every frame. + - `MixPose` is now called `MixBlend` + - Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + - Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +- **Additions** + - Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + - Support for stretchy IK + - Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + - `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Starling + +- Added support for vertex effects. See `RaptorExample.as` +- Added 'getTexture()' method to 'StarlingTextureAtlasAttachmentLoader' +- Breaking change: if a skeleton requires two color tinting, you have to enable it via `SkeletonSprite.twoColorTint = true`. In this case the skeleton will use the `TwoColorMeshStyle`, which internally uses a different vertex layout and shader. This means that skeletons with two color tinting enabled will break batching and hence increase the number of draw calls in your app. +- Added `VertexEffect` and implementations `JitterEffect` and `SwirlEffect`. Allows you to modify vertices before they are submitted for drawing. See Starling changes. +- Fix issues with StarlingAtlasAttachmentLoader, see https://github.com/EsotericSoftware/spine-runtimes/issues/939 +- Fix issues with region trimming support, see https://github.com/EsotericSoftware/spine-runtimes/commit/262bc26c64d4111002d80e201cb1a3345e6727df +- Added support for overriding `StarlingAtlasAttachmentLoader#getTexture()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/ea7dbecb98edc74e439aa9ef90dcf6eed865f718 +- Texture atlas operations are no longer handled in `Starling#newRegionAttachment` and `Starling#newMeshAttachment` but delegated to the atlas. +- Added sample for additive animation blending, see https://github.com/EsotericSoftware/spine-runtimes/blob/6a556de01429878df47bb276a97959a8bdbbe32f/spine-starling/spine-starling-example/src/spine/examples/OwlExample.as +- Added sample on how to use bounding box attachment vertices https://github.com/EsotericSoftware/spine-runtimes/commit/e20428b02699226164fa73ba4b12f7d029ae6f4d +- Fully transparent meshes are not submitted for rendering. +- No hit-tests are performed when a skeleton is invisible. + +## C + +- **Breaking changes** + - Listeners on `spAnimationState` and `spTrackEntry` will now also be called if a track entry gets disposed as part of disposing an animation state. + - The completion event will fire for looped 0 duration animations every frame. + - The spine-cocos2dx and spine-ue4 runtimes are now based on spine-cpp. See below for changes. + - Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + - Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 + - `spMeshAttachment` has two new fields `regionTextureWith` and `regionTextureHeight`. These must be set in custom attachment loader. See `AtlasAttachmentLoader`. +- **Additions** + - Added support for local and relative transform constraint calculation, including additional fields in `spTransformConstraintData`. + - `Animation#apply` and ` Timeline#apply`` now take enums `MixPose`and`MixDirection` instead of booleans + - Added `spVertexEffect` and corresponding implementations `spJitterVertexEffect` and `spSwirlVertexEffect`. Create/dispose through the corresponding `spXXXVertexEffect_create()/dispose()` functions. Set on framework/engine specific renderer. + - Functions in `extension.h` are not prefixed with `_sp` instead of just `_` to avoid interference with other libraries. + - Introduced `SP_API` macro. Every spine-c function is prefixed with this macro. By default, it is an empty string. Can be used to markup spine-c functions with e.g. ``__declspec` when compiling to a dll or linking to that dll. + - Added `void *userData` to `spAnimationState`to be consumed in callbacks. + - Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `spTrackEntry->mixBlend = SP_MIXBLEND_ADD)` on each track. To specify the blend percentage, set `spTrackEntry->alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + - Optimized attachment lookup to give a 40x speed-up. See https://github.com/EsotericSoftware/spine-runtimes/commit/cab81276263890b65d07fa2329ace16db1e365ff + - Support for stretchy IK + - Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + - `spTrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Cocos2d-Objc + +- Added vertex effect support to modify vertices of skeletons on the CPU. See `RaptorExample.m`. +- Explanation how to handle ARC, see https://github.com/EsotericSoftware/spine-runtimes/commit/a4f122b08c5e2a51d6aad6fc5a947f7ec31f2eb8 +- The super class `::update()` method of `SkeletonRenderer` is now called, see https://github.com/EsotericSoftware/spine-runtimes/commit/f7bb98185236a6d8f35bfefc70afe4f31e9ec9d2 +- Added improved tint-black shader. + +### SFML + +- `spine-sfml.h` no longer defines `SPINE_SHORT_NAMES` to avoid collisions with other APIs. See #1058. +- Added support for vertex effects. See raptor example. +- Added premultiplied alpha support to `SkeletonDrawable`. Use `SkeletonDrawable::setUsePremultipliedAlpha()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/34086c1f41415309b2ecce86055f6656fcba2950 +- Added additive animation blending sample, see https://github.com/EsotericSoftware/spine-runtimes/blob/b7e712d3ca1d6be3ebcfe3254dc2cea9c44dda71/spine-sfml/example/main.cpp#L369 + +## C++ + +- ** Additions ** + - Added C++ Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. + - Added parsing of non-essential data (fps, images path, audio path) to for `.json`/`.skel` parsers. + +### Cocos2d-x + +- Added ETC1 alpha support, thanks @halx99! Does not work when two color tint is enabled. +- Added `spAtlasPage_setCustomTextureLoader()` which let's you do texture loading manually. Thanks @jareguo. +- Added `SkeletonRenderer:setSlotsRange()` and `SkeletonRenderer::createWithSkeleton()`. This allows you to split rendering of a skeleton up into multiple parts, and render other nodes in between. See `SkeletonRendererSeparatorExample.cpp` for an example. +- Fully transparent attachments will not be rendered, improving rendering performance. +- Added improved tint-black shader. +- Updated to cocos2d-x 3.16 +- The skeleton setup pose and world transform are now calculated on initialization to avoid flickering on start-up. +- Updated to cocos2d-x 3.17.1 +- **Breaking change**: Switched from [spine-c](spine-c) to [spine-cpp](spine-cpp) as the underlying Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. + - Added `Cocos2dAttachmentLoader` to be used when constructing an `Atlas`. Used by default by `SkeletonAnimation` and `SkeletonRenderer` when creating instances via the `createXXX` methods. + - All C structs and enums `spXXX` have been replaced with their C++ equivalents `spine::XXX` in all public interfaces. + - All instantiations via `new` of C++ classes from spine-cpp should contain `(__FILE__, __LINE__)`. This allows the tracking of instantations and detection of memory leaks via the `spine::DebugExtension`. + +### SFML + +- Create a second SFML backend using [spine-cpp](spine-cpp/). See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. +- Added support for vertex effects. See raptor example. +- Added premultiplied alpha support to `SkeletonDrawable`. Use `SkeletonDrawable::setUsePremultipliedAlpha()`, see https://github.com/EsotericSoftware/spine-runtimes/commit/34086c1f41415309b2ecce86055f6656fcba2950 +- Added additive animation blending sample, see https://github.com/EsotericSoftware/spine-runtimes/blob/b7e712d3ca1d6be3ebcfe3254dc2cea9c44dda71/spine-sfml/example/main.cpp#L369 + +### UE4 + +- spine-c is now exposed from the plugin shared library on Windows via \_\_declspec. +- Updated to Unreal Engine 4.18 +- Added C++ example, see https://github.com/EsotericSoftware/spine-runtimes/commit/15011e81b7061495dba45e28b4d3f4efb10d7f40 +- `SkeletonRendererComponent` generates collision meshes by default. +- Disabled generation of collision meshes by `SkeletonRendererComponent`. Both `ProceduralMeshComponent` and `RuntimeMeshComponent` have a bug that generates a new PhysiX file every frame per component. Users are advised to add a separate collision shape to the root scene component of an actor instead. +- Using UE4 `FMemory` allocator by default. This should fix issues on some consoles. +- **Breaking change** moved away from `RuntimeMeshComponent`, as its maintainance has seized, back to `ProceduralMeshComponent`. Existing projects should just work. However, if you run into issues, you may have to remove the old `SpineSkeletonRendererComponent` and add a new one to your existing actors. +- **Breaking change** due to the removal of `RuntimeMeshComponent` and reversal to `ProceduralMeshComponent`, two color tinting is currently not supported. `ProceduralMeshComponent` does not support enough vertex attributes for us to encode the second color in the vertex stream. You can remove the `RuntimeMeshComponent/` directory from your plugins directory and remove the component from any `build.cs` files that may reference it. +- **Breaking change**: Switched from [spine-c](spine-c) to [spine-cpp](spine-cpp) as the underlying Spine runtime. See the [spine-cpp Runtime Guide](https://esotericsoftware.com/spine-cpp) for more information on spine-cpp. +- All C structs and enums `spXXX` have been replaced with their C++ equivalents `spine::XXX` in all public interfaces. +- All instantiations via `new` of C++ classes from spine-cpp should contain `(__FILE__, __LINE__)`. This allows the tracking of instantations and detection of memory leaks via the `spine::DebugExtension`. +- Updated to Unreal Engine 4.20 (samples require 4.17+), see the `spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.build.cs` file on how to compile in 4.20 with the latest UBT API changes. +- Updated to Unreal Engine 4.21 (samples require 4.21). +- **Breaking change**: `UBoneDriverComponent` and `UBoneFollowerComponent` are now `USceneComponent` instead of `UActorComponent`. They either update only themselves, or also the owning `UActor`, depending on whether the new flag `UseComponentTransform` is set. See https://github.com/EsotericSoftware/spine-runtimes/pull/1175 +- Added query methods for slots, bones, skins and animations to `SpineSkeletonComponent` and `UTrackEntry`. These allow you to query these objects by name in both C++ and blueprints. +- Added `Preview Animation` and `Preview Skin` properties to `SpineSkeletonAnimationComponent`. Enter an animation or skin name to live-preview it in the editor. Enter an empty string to reset the animation or skin. + +## C# + +- **Breaking changes** + - The completion event will fire for looped 0 duration animations every frame. + - Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + - Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +- **Additions** + - Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#MixBlend = MixBlend.add` on each track. To specify the blend percentage, set `TrackEntry#Alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + - Support for stretchy IK + - Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + - `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Unity + +- **Runtime and Editor, and Assembly Definition** Files and folders have been reorganized into "Runtime" and "Editor". Each of these have an `.asmdef` file that defines these separately as their own assembly in Unity _(Note: Spine `.asmdef` files are currently deactivated to `.txt` extension, see below)_. For projects not using assembly definition, you may delete the `.asmdef` files. These assembly definitions will be ignored by older versions of Unity that don't support it. + - In this scheme, the entirety of the base spine-csharp runtime is inside the "Runtime" folder, to be compiled in the same assembly as spine-unity so they can continue to share internal members. +- **Spine `.asmdef` files are now deactivated (using `.txt` extension) by default** This prevents problems when updating Spine through unitypackages, overwriting the Timeline reference entry in `spine-unity.asmdef` (added automatically when enabling Unity 2019 Timeline support, see `Timeline Support for Unity 2019`), causing compile errors. In case you want to enable the `.asmdef` files, rename the files: + `Spine/Runtime/spine-unity.txt` to `Spine/Runtime/spine-unity.asmdef` and + `Spine/Editor/spine-unity-editor.txt` to `Spine/Editor/spine-unity-editor.asmdef`. +- **SkeletonAnimator is now SkeletonMecanim** The Spine-Unity Mecanim-driven component `SkeletonAnimator` has been renamed `SkeletonMecanim` to make it more autocomplete-friendly and more obvious at human-glance. The .meta files and guids should remain intact so existing projects and prefabs should not break. However, user code needs to be updated to use `SkeletonMecanim`. +- **SpineAtlasAsset** The existing `AtlasAsset` type has been renamed to `SpineAtlasAsset` to signify that it specifically uses a Spine/libGDX atlas as its source. Serialization should be intact but user code will need to be updated to refer to existing atlases as `SpineAtlasAsset`. + - **AtlasAssetBase** `SpineAtlasAsset` now has an abstract base class called `SpineAtlasAsset`. This is the base class to derive when using alternate atlas sources. Existing SkeletonDataAsset field "atlasAssets" now have the "AtlasAssetBase" type. Serialization should be intact, but user code will need to be updated to refer to the atlas assets accordingly. + - This change is in preparation for alternate atlas options such as Unity's SpriteAtlas. +- **Optional Straight Alpha for shaders** Spine-Unity's included Unity shaders now have a `_STRAIGHT_ALPHA_INPUT` shader_feature, toggled as a checkbox in the Material's inspector. This allows the Material to use a non-premultiplied alpha/straight alpha input texture. + - The following shaders now have the "Straight Alpha Texture" checkbox when used on a material: + - `Spine/Skeleton` + - `Spine/Skeleton Tint Black` + - `Spine/Skeleton Lit` + - `Spine/Skeleton Tint` + - `Spine/Skeleton Fill` + - `Spine/SkeletonGraphic (Premultiply Alpha)` was renamed to `Spine/SkeletonGraphic` + - `Spine/SkeletonGraphic Tint Black (Premultiply Alpha)` was renamed to `Spine/SkeletonGraphic Tint Black` + - `Spine/Skeleton PMA Multiply` + - `Spine/Skeleton PMA Screen` + - Dedicated straight alpha shaders were removed from the runtime. + - `Spine/Straight Alpha/Skeleton Fill` + - `Spine/Straight Alpha/Skeleton Tint` +- **Detection of Incorrect Texture Settings** Especially when atlas textures are exported with setting `Premultiply alpha` enabled, it is important to configure Unity's texture import settings correctly. By default, you will now receive warnings where texture settings are expected to cause incorrect rendering. + - The following rules apply: + - `sRGB (Color Texture)` shall be disabled when `Generate Mip Maps` is enabled, otherwise you will receive white border outlines. + - `Alpha Is Transparency` shall be disabled on `Premultiply alpha` textures, otherwise you will receive light ghosting artifacts in transparent areas. + - These warnings can be disabled in `Edit - Preferences - Spine`. +- **Sprite Mask Support for all Included Shaders** The `Skeleton Animation` and `Skeleton Mecanim` components now provide an additional `Mask Interaction` field in the Inspector, covering identical functionality as Unity's built in `Sprite Renderer` component: + - `Mask Interaction` modes: + - `None` - The sprite will not interact with the masking system. Default behavior. + - `Visible Inside Mask` - The sprite will be visible only in areas where a mask is present. + - `Visible Outside Mask` - The sprite will be visible only in areas where no mask is present. + - `Automatically Generated Materials` When switching `Mask Interaction` modes in the Inspector outside of Play mode, the required additional material assets are generated for the respective `Stencil Compare` parameters - with file suffixes `'_InsideMask'` and `'_OutsideMask'`, placed in the same folder as the original materials. By default all generated materials are kept as references by the `Skeleton Animation` component for switching at runtime. + These materials can be managed and optimized via the `SkeletonAnimation`'s `Advanced` section: + - Using the `Clear` button you can clear the reference to unneeded materials, + - Using the `Delete` button the respective assets are deleted as well as references cleared. Note that other `Skeleton Animation` GameObjects might still reference the materials, so use with caution! + - With the `Set` button you can again assign a link to the respective materials to prepare them for runtime use. If the materials were not present or have been deleted, they are generated again based on the default materials. + - When switching `Mask Interaction` mode at runtime, the previously prepared materials are switched active automatically. When the respective materials have not been prepared, material copies of the default materials are created on the fly. Note that these materials are not shared between similar `Skeleton Animation` GameObjects, so it is recommended to use the generated material assets where possible. + - **Every shader now exposes the `Stencil Compare` parameter** for further customization. This way you have maximum flexibility to use custom mechanisms to switch materials at runtime if you should ever need more than the three materials generated by `Skeleton Animation`'s `Mask Interaction` parameter. Reference `Stencil Compare` values are: + - `CompareFunction.Disabled` for `Mask Interaction - None` + - `CompareFunction.LessEqual` for `Mask Interaction - Visible Inside Mask` + - `CompareFunction.Greater` for `Mask Interaction - Visible Outside Mask` +- **RectMask2D Support for SkeletonGraphic** Both `SkeletonGraphic` shaders '`Spine/SkeletonGraphic`' and '`Spine/SkeletonGraphic Tint Black`' now respect masking areas defined via Unity's `RectMask2D` component. +- **Timeline Support for Unity 2019** using the existing Timeline components. By default, all Spine Timeline components are deactivated in Unity 2019 and **can be activated via the Spine Preferences menu**. This step became necessary because in Unity 2019, Timeline has been moved to a separate Package and is no longer included in the Unity core. Please visit `Edit - Preferences - Spine` and at `Timeline Package Support` hit `Enable` to automatically perform all necessary steps to activate the Timeline components. + This will automatically: + 1. download the Unity Timeline package + 2. activate the Spine Timeline components by setting the compile definition `SPINE_TIMELINE_PACKAGE_DOWNLOADED` for all platforms + 3. modify the `spine-unity.asmdef` file by adding the reference to the Unity Timeline library. +- Added `Create 2D Hinge Chain` functionality at `SkeletonUtilityBone` inspector, previously only `Create 3D Hinge Chain` was available. + +### XNA/MonoGame + +- Added support for any `Effect` to be used by `SkeletonRenderer` +- Added support for `IVertexEffect` to modify vertices of skeletons on the CPU. `IVertexEffect` instances can be set on the `SkeletonRenderer`. See example project. +- Added `SkeletonDebugRenderer` +- Made `MeshBatcher` of SkeletonRenderer accessible via a getter. Allows user to batch their own geometry together with skeleton meshes for maximum batching instead of using XNA SpriteBatcher. + +## Java + +- **Breaking changes** + - Skeleton attachments: Moved update of attached skeleton out of libGDX `SkeletonRenderer`, added overloaded method `Skeleton#updateWorldTransform(Bone)`, used for `SkeletonAttachment`. You now MUST call this new method with the bone of the parent skeleton to which the child skeleton is attached. See `SkeletonAttachmentTest` for and example. + - The completion event will fire for looped 0 duration animations every frame. + - `MixPose` is now called `MixBlend`. + - Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + - Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +- **Additions** + - Added `EventData#audioPath` field. This field contains the file name of the audio file used for the event. + - Added convenience method to add all attachments from one skin to another, see https://github.com/EsotericSoftware/spine-runtimes/commit/a0b7bb6c445efdfac12b0cdee2057afa3eff3ead + - Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + - Support for stretchy IK + - Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + - `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### libGDX + +- Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect` and `VertexEffectTest`. +- Added improved tint-black shader. +- Improved performance by avoiding batch flush when not switching between normal and additive rendering with PMA +- Improvements to skeleton viewer. +- `TwoColorPolygonBatch` implements the `Batch` interface, allowing to the be used with other libGDX classes that require a batcher for drawing, potentially improving performance. See https://github.com/EsotericSoftware/spine-runtimes/commit/a46b3d1d0c135d51f9bef9ca17a5f8e5dda69927 +- Added `SkeletonDrawable` to render skeletons in scene2d UI https://github.com/EsotericSoftware/spine-runtimes/commit/b93686c185e2c9d5466969a8e07eee573ebe4b97 + +## Lua + +- **Breaking changes** + - The completion event will fire for looped 0 duration animations every frame. + - Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + - Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +- **Additions** + - Added `JitterEffect` and `SwirlEffect` and support for vertex effects in Corona and Love + - Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry:setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry.alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. + - Support for stretchy IK + - Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + - `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + +### Love2D + +- Added support for vertex effects. Set an implementation like "JitterEffect" on `Skeleton.vertexEffect`. See `main.lua` for an example. + +### Corona + +- Added support for vertex effects. Set an implementation like "JitterEffect" on `SkeletonRenderer.vertexEffect`. See `main.lua` for an example + +## Typescript/Javascript + +- **Breaking changes** + - The completion event will fire for looped 0 duration animations every frame. + - Skeleton `flipX/flipY` has been replaced with `scaleX/scaleY`. This cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance + - Mix time is no longer affected by `TrackEntry#timeScale`. See https://github.com/EsotericSoftware/spine-runtimes/issues/1194 +- **Additions** + - Added `AssetManager.loadTextureAtlas`. Instead of loading the `.atlas` and corresponding image files manually, you can simply specify the location of the `.atlas` file and AssetManager will load the atlas and all its images automatically. `AssetManager.get("atlasname.atlas")` will then return an instance of `spine.TextureAtlas`. + - Added additive animation blending. When playing back multiple animations on different tracks, where each animation modifies the same skeleton property, the results of tracks with lower indices are discarded, and only the result from the track with the highest index is used. With animation blending, the results of all tracks are mixed together. This allows effects like mixing multiple facial expressions (angry, happy, sad) with percentage mixes. By default the old behaviour is retained (results from lower tracks are discarded). To enable additive blending across animation tracks, call `TrackEntry#setMixBlend(MixBlend.add)` on each track. To specify the blend percentage, set `TrackEntry#alpha`. See http://esotericsoftware.com/forum/morph-target-track-animation-mix-mode-9459 for a discussion. See https://github.com/EsotericSoftware/spine-runtimes/blob/f045d221836fa56191ccda73dd42ae884d4731b8/spine-ts/webgl/tests/test-additive-animation-blending.html for an example. + - Added work-around for iOS WebKit JIT bug, see https://github.com/EsotericSoftware/spine-runtimes/commit/c28bbebf804980f55cdd773fed9ff145e0e7e76c + - Support for stretchy IK + - Support for audio events, see `audioPath`, `volume` and `balance` fields on event (data). + - `TrackEntry` has an additional field called `holdPrevious`. It can be used to counter act a limitation of `AnimationState` resulting in "dipping" of parts of the animation. For a full discussion of the problem and the solution we've implemented, see this [forum thread](http://esotericsoftware.com/forum/Probably-Easy-Animation-mixing-with-multiple-tracks-10682?p=48130&hilit=holdprevious#p48130). + - Added `AssetManager#setRawDataURI(path, data)`. Allows to set raw data URIs for a specific path, which in turn enables embedding assets into JavaScript/HTML. + - `PolygonBatcher` will now disable `CULL_FACE` and restore the state as it was before rendering. + +### WebGL backend + +- Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`, and the example which allows to set effects. +- Added `slotRangeStart` and `slotRangeEnd` parameters to `SkeletonRenderer#draw` and `SceneRenderer#drawSkeleton`. This allows you to render only a range of slots in the draw order. See `spine-ts/webgl/tests/test-slot-range.html` for an example. +- Added improved tint-black shader. +- Added `SceneRenderer#drawTextureUV()`, allowing to draw a texture with manually specified texture coordinates. +- Exposed all renderers in `SceneRenderer`. + +### Canvas backend + +- Added support for shearing and non-uniform scaling inherited from parent bones. +- Added support for alpha tinting. + +### Three.js backend + +- Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`. +- Added support for multi-page atlases + +### Widget backend + +- Added fields `atlasContent`, `atlasPagesContent`, and `jsonContent` to `WidgetConfiguration` allowing you to directly pass the contents of the `.atlas`, atlas page `.png` files, and the `.json` file without having to do a request. See `README.md` and the example for details. +- `SpineWidget.setAnimation()` now takes an additional optional parameter for callbacks when animations are completed/interrupted/etc. + +# 3.6 + +## AS3 + +- **Breaking changes** + + - Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + - Made `Bone` fields `_a`, `_b`, `_c`, `_d`, `_worldX` and `_worldY` public, removed underscore prefix. + - Removed `VertexAttachment.computeWorldVertices` overload, changed `VertexAttachment.computeWorldVertices2` to `VertexAttachment.computeWorldVertices`, added `stride` parameter. + - Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + - Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + - Replaced `r`, `g`, `b`, `a` fields with instances of new `Color` class in `RegionAttachment`, `MeshAttachment`, `Skeleton`, `SkeletonData`, `Slot` and `SlotData`. + - The completion event will fire for looped 0 duration animations every frame. + +- **Additions** + - Added `Skeleton.getBounds` from reference implementation. + - Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + - Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + - Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + - Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + - Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + - `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + - `Animation#apply` and ` Timeline#apply`` now take enums `MixPose`and`MixDirection` instead of booleans + - Added `VertexEffect` and implementations `JitterEffect` and `SwirlEffect`. Allows you to modify vertices before they are submitted for drawing. See Starling changes. + +### Starling + +- Fixed renderer to work with 3.6 changes. +- Added support for two color tinting. +- Added support for clipping. +- Added support for rotated regions in texture atlas loaded via StarlingAtlasAttachmentLoader. +- Added support for vertex effects. See `RaptorExample.as` +- Added 'getTexture()' method to 'StarlingTextureAtlasAttachmentLoader' +- Breaking change: if a skeleton requires two color tinting, you have to enable it via `SkeletonSprite.twoColorTint = true`. In this case the skeleton will use the `TwoColorMeshStyle`, which internally uses a different vertex layout and shader. This means that skeletons with two color tinting enabled will break batching and hence increase the number of draw calls in your app. + +## C + +- **Breaking changes** + - `spVertexAttachment_computeWorldVertices` and `spRegionAttachment_computeWorldVerticeS` now take new parameters to make it possible to directly output the calculated vertex positions to a vertex buffer. Removes the need for additional copies in the backends' respective renderers. + - Removed `spBoundingBoxAttachment_computeWorldVertices`, superseded by `spVertexAttachment_computeWorldVertices`. + - Removed `spPathAttachment_computeWorldVertices` and `spPathAttachment_computeWorldVertices1`, superseded by `spVertexAttachment_computeWorldVertices`. + - Removed `sp_MeshAttachment_computeWorldVertices`, superseded by `spVertexAttachment_computeWorldVertices`. + - Removed `spBone_worldToLocalRotationX` and `spBone_worldToLocalRotationY`. Replaced by `spBone_worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + - Replaced `r`, `g`, `b`, `a` fields with instances of new `spColor` struct in `spRegionAttachment`, `spMeshAttachment`, `spSkeleton`, `spSkeletonData`, `spSlot` and `spSlotData`. + - Removed `spVertexIndex`from public API. + - Listeners on `spAnimationState` or `spTrackEntry` will now be also called in case a track entry is disposed as part of dispoing the `spAnimationState`. + - The completion event will fire for looped 0 duration animations every frame. +- **Additions** + - Added support for local and relative transform constraint calculation, including additional fields in `spTransformConstraintData`. + - Added `spPointAttachment`, additional method `spAtlasAttachmentLoadeR_newPointAttachment`. + - Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + - Added `spBone_localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + - Added two color tinting support, including `spTwoColorTimeline` and additional fields on `spSlot` and `spSlotData`. + - Added `userData` field to `spTrackEntry`, so users can expose data in `spAnimationState` callbacks. + - Modified kvec.h used by SkeletonBinary.c to use Spine's MALLOC/FREE macros. That way there's only one place to inject custom allocators ([extension.h](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-c/spine-c/include/spine/extension.h)) [commit](https://github.com/EsotericSoftware/spine-runtimes/commit/c2cfbc6cb8709daa082726222d558188d75a004f) + - Added macros to define typed dynamic arrays, see `Array.h/.c` + - Added `spClippingAttachment` and respective enum. + - Added `spSkeletonClipper` and `spTriangulator`, used to implement software clipping of attachments. + - `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + - `Animation#apply` and ` Timeline#apply`` now take enums `MixPose`and`MixDirection` instead of booleans + - Added `spVertexEffect` and corresponding implementations `spJitterVertexEffect` and `spSwirlVertexEffect`. Create/dispose through the corresponding `spXXXVertexEffect_create()/dispose()` functions. Set on framework/engine specific renderer. See changes for spine-c based frameworks/engines below. + - Functions in `extension.h` are not prefixed with `_sp` instead of just `_` to avoid interference with other libraries. + - Introduced `SP_API` macro. Every spine-c function is prefixed with this macro. By default, it is an empty string. Can be used to markup spine-c functions with e.g. ``__declspec` when compiling to a dll or linking to that dll. + +### Cocos2d-X + +- Fixed renderer to work with 3.6 changes +- Optimized rendering by removing all per-frame allocation in `SkeletonRenderer`, resulting in 15% performance increase for large numbers of skeletons being rendered per frame. +- Added support for two color tinting. Tinting is enabled/disabled per `SkeletonRenderer`/`SkeletonAnimation` instance. Use `SkeletonRenderer::setTwoColorTint()`. Note that two color tinting requires the use of a non-standard shader and vertex format. This means that skeletons rendered with two color tinting will break batching. However, skeletons with two color tinting enabled and rendered after each other will be batched. +- Updated example to use Cocos2d-x 3.14.1. +- Added mesh debug rendering. Enable/Disable via `SkeletonRenderer::setDebugMeshesEnabled()`. +- Added support for clipping. +- SkeletonRenderer now combines the displayed color of the Node (cascaded from all parents) with the skeleton color for tinting. +- Added support for vertex effects. See `RaptorExample.cpp`. +- Added ETC1 alpha support, thanks @halx99! Does not work when two color tint is enabled. +- Added `spAtlasPage_setCustomTextureLoader()` which let's you do texture loading manually. Thanks @jareguo. +- Added `SkeletonRenderer:setSlotsRange()` and `SkeletonRenderer::createWithSkeleton()`. This allows you to split rendering of a skeleton up into multiple parts, and render other nodes in between. See `SkeletonRendererSeparatorExample.cpp` for an example. + +### Cocos2d-Objc + +- Fixed renderer to work with 3.6 changes +- Added support for two color tinting. Tinting is enabled/disabled per `SkeletonRenderer/SkeletonAnimation.twoColorTint = true`. Note that two color tinted skeletons do not batch with other nodes. +- Added support for clipping. + +### SFML + +- Fixed renderer to work with 3.6 changes. Sadly, two color tinting does not work, as the vertex format in SFML is fixed. +- Added support for clipping. +- Added support for vertex effects. See raptor example. +- Added premultiplied alpha support to `SkeletonDrawable`. + +### Unreal Engine 4 + +- Fixed renderer to work with 3.6 changes +- Added new UPROPERTY to SpineSkeletonRendererComponent called `Color`. This allows to set the tint color of the skeleton in the editor, C++ and Blueprints. Under the hood, the `spSkeleton->color` will be set on every tick of the renderer component. +- Added support for clipping. +- Switched from built-in ProceduralMeshComponent to RuntimeMeshComponent by Koderz (https://github.com/Koderz/UE4RuntimeMeshComponent, MIT). Needed for more flexibility regarding vertex format, should not have an impact on existing code/assets. You need to copy the RuntimeMeshComponentPlugin from our repository in `spine-ue4\Plugins\` to your project as well! +- Added support for two color tinting. All base materials, e.g. SpineUnlitNormalMaterial, now do proper two color tinting. No material parameters have changed. +- Updated to Unreal Engine 4.16.1. Note that 4.16 has a regression which will make it impossible to compile plain .c files! +- spine-c is now exposed from the plugin shared library on Windows via \_\_declspec. + +## C# + +- **Breaking changes** + + - `MeshAttachment.parentMesh` is now a private field to enforce using the `.ParentMesh` setter property in external code. The `MeshAttachment.ParentMesh` property is an appropriate replacement wherever `.parentMesh` was used. + - `Skeleton.GetBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + - Removed `Bone.WorldToLocalRotationX` and `Bone.WorldToLocalRotationY`. Replaced by `Bone.WorldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + - Added `stride` parameter to `VertexAttachment.ComputeWorldVertices`. + - Removed `RegionAttachment.Vertices` field. The vertices array is provided to `RegionAttachment.ComputeWorldVertices` by the API user now. + - Removed `RegionAttachment.UpdateWorldVertices`, added `RegionAttachment.ComputeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + - The completion event will fire for looped 0 duration animations every frame. + +- **Additions** +- Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` +- Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). +- Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. +- Added `PointAttachment`, additional method `NewPointAttachment` in `AttachmentLoader` interface. +- Added `ClippingAttachment`, additional method `NewClippingAttachment` in `AttachmentLoader` interface. +- Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. +- `AnimationState.Apply` returns a bool indicating if any timeline was applied or not. +- `Animation.Apply` and ` Timeline.Apply`` now take enums `MixPose`and`MixDirection` instead of bools. + +### Unity + +- Refactored renderer to work with new 3.6 features. + - **Two color tinting** is currently supported via extra UV2 and UV3 mesh vertex streams. To use Two color tinting, you need to: + - switch on "Tint Black" under "Advanced...", + - use the new `Spine/Skeleton Tint Black` shader, or your own shader that treats the UV2 and UV3 streams similarly. + - Additionally, for SkeletonGraphic, you can use `Spine/SkeletonGraphic Tint Black` (or the bundled SkeletonGraphicTintBlack material) or your own shader that uses UV2 and UV3 streams similarly. **Additional Shader Channels** TexCoord1 and TexCoord2 will need to be enabled from the Canvas component's inspector. These correspond to UV2 and UV3. + - **Clipping** is now supported. Caution: The SkeletonAnimation switches to slightly slower mesh generation code when clipping so limit your use of `ClippingAttachment`s when using on large numbers of skeletons. +- **SkeletonRenderer.initialFlip** Spine components such as SkeletonRenderer, SkeletonAnimation, SkeletonAnimator now has `initialFlipX` and `initialFlipY` fields which are also visible in the inspector under "Advanced...". It will allow you to set and preview a starting flip value for your skeleton component. This is applied immediately when the internal skeleton object is instantiated. +- **[SpineAttribute] Improvements** + - **Icons have been added to SpineAttributeDrawers**. This should make your default inspectors easier to understand at a glance. + - **Added Constraint Attributes** You can now use `[SpineIkConstraint]` `[SpineTransformConstraint]` `[SpinePathConstraint]` + - **SpineAttribute dataField** parameter can also now detect sibling fields within arrays and serializable structs/classes. + - **[SpineAttribute(includeNone:false)]** SpineAttributes now have an `includeNone` optional parameter to specify if you want to include or exclude a none ("") value option in the dropdown menu. Default is `includeNone:true`. + - **[SpineAttachment(skinField:"mySkin")]** The SpineAttachment attribute now has a skinField optional parameter to limit the dropdown items to attachments in a specific skin instead of the just default skin or all the skins in SkeletonData. +- **SkeletonDebugWindow**. Debugging tools have been moved from the SkeletonAnimation and SkeletonUtility component inspectors into its own utility window. You can access "Skeleton Debug" under the `Advanced...` foldout in the SkeletonAnimation inspector, or in SkeletonAnimation's right-click/context menu. + - **Skeleton Baking Window** The old Skeleton Baking feature is also now accessible through the SkeletonDataAsset's right-click/context menu. +- **AttachmentTools source material**. `AttachmentTools` methods can now accept a `sourceMaterial` argument to copy material properties from. +- **AttachmentTools Skin Extensions**. Using AttachmentTools, you can now add entries by slot name by also providing a skeleton argument. Also `Append(Skin)`, `RemoveAttachment` and `Clear` have been added. +- **BoneFollower and SkeletonUtilityBone Add RigidBody Button**. The BoneFollower and SkeletonUtilityBone component inspectors will now offer to add a `Rigidbody` or `Rigidbody2D` if it detects a collider of the appropriate type. Having a rigidbody on a moving transform with a collider fits better with the Unity physics systems and prevents excess calculations. It will not detect colliders on child objects so you have to add Rigidbody components manually accordingly. +- **SkeletonRenderer.OnPostProcessVertices** is a new callback that gives you a reference to the MeshGenerator after it has generated a mesh from the current skeleton pose. You can access `meshGenerator.VertexBuffer` or `meshGenerator.ColorBuffer` to modify these before they get pushed into the UnityEngine.Mesh for rendering. This can be useful for non-shader vertex effects. +- **Examples** + - **Examples now use properties**. The code in the example scripts have been switched over to using properties instead of fields to encourage their use for consistency. This is in anticipation of both users who want to move the Spine folders to the Unity Plugins folder (compiled as a different assembly), and of Unity 2017's ability to manually define different assemblies for shorter compilation times. + - **Mix And Match**. The mix-and-match example scene, code and data have been updated to reflect the current recommended setup for animation-compatible custom equip systems The underlying API has changed since 3.5 and the new API calls in MixAndMatch.cs is recommended. Documentation is in progress. + - **Sample Components**. `AtasRegionAttacher` and `SpriteAttacher` are now part of `Sample Components`, to reflect that they are meant to be used as sample code rather than production. A few other sample components have also been added. New imports of the unitypackage Examples folder will see a "Legacy" folder comprised of old sample components that no longer contain the most up-to-date and recommended workflows, but are kept in case old setups used them for production. +- **Spine folder**. In the unitypackage, the "spine-csharp" and "spine-unity" folders are now inside a "Spine" folder. This change will only affect fresh imports. Importing the unitypackage to update Spine-Unity in your existing project will update the appropriate files however you chose to arrange them, as long as the meta files are intact. +- **Breaking changes** + - The Sprite shaders module was updated to the latest version from the [source](https://github.com/traggett/UnitySpriteShaders/commits/master). Some changes were made to the underlying keyword structure. You may need to review the settings of your lit materials. Particularly, your Fixed Normals settings. + - The `Spine/Skeleton Lit` shader was switched over to non-fixed-function code. It now no longer requires mesh normals and has fixed normals at the shader level. + - The old MeshGenerator classes, interfaces and code in `Spine.Unity.MeshGeneration` are now deprecated. All mesh-generating components now share the class `Spine.Unity.MeshGenerator` defined in `SpineMesh.cs`. MeshGenerator is a serializable class. + - The `SkeletonRenderer.renderMeshes` optimization is currently non-functional. + - Old triangle-winding code has been removed from `SkeletonRenderer`. Please use shaders that have backface culling off. + - Render settings in `SkeletonGraphic` can now be accessed under `SkeletonGraphic.MeshGenerator.settings`. This is visible in the SkeletonGraphic inspector as `Advanced...` + - We will continue to bundle the unitypackage with the empty .cs files of deprecated classes until Spine 3.7 to ensure the upgrade process does not break. + - The [SpineAttachment(slotField:)] optional parameter found property value now acts as a Find(slotName) argument rather than Contains(slotName). + - `SkeletonAnimator` now uses a `SkeletonAnimator.MecanimTranslator` class to translate an Animator's Mecanim State Machine into skeleton poses. This makes code reuse possible for a Mecanim version of SkeletonGraphic. + - `SkeletonAnimator` `autoreset` and the `mixModes` array are now a part of SkeletonAnimator's MecanimTranslator `.Translator`. `autoReset` is set to `true` by default. Old prefabs and scene objects with Skeleton Animator may no longer have correct values set. + - Warnings and conditionals checking for specific Unity 5.2-and-below incompatibility have been removed. + +## XNA/MonoGame + +- Added support for clipping +- Removed `RegionBatcher` and `SkeletonRegionRenderer`, renamed `SkeletonMeshRenderer` to `SkeletonRenderer` +- Added support for two color tint. For it to work, you need to add the `SpineEffect.fx` file to your content project, then load it via `var effect = Content.Load("SpineEffect");`, and set it on the `SkeletonRenderer`. See the example project for code. +- Added support for any `Effect` to be used by `SkeletonRenderer` +- Added support for `IVertexEffect` to modify vertices of skeletons on the CPU. `IVertexEffect` instances can be set on the `SkeletonRenderer`. See example project. +- Added `SkeletonDebugRenderer` +- Made `MeshBatcher` of SkeletonRenderer accessible via a getter. Allows user to batch their own geometry together with skeleton meshes for maximum batching instead of using XNA SpriteBatcher. + +## Java + +- **Breaking changes** + + - `Skeleton.getBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + - Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + - Added `stride` parameter to `VertexAttachment.computeWorldVertices`. + - Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + - Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + - Skeleton attachments: Moved update of attached skeleton out of libGDX `SkeletonRenderer`, added overloaded method `Skeleton#updateWorldTransform(Bone), used for `SkeletonAttachment`. You now MUST call this new method +with the bone of the parent skeleton to which the child skeleton is attached. See `SkeletonAttachmentTest` for and example. + - The completion event will fire for looped 0 duration animations every frame. + +- **Additions** + - Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + - Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + - Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + - Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + - Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + - Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + - `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + - `Animation#apply` and ` Timeline#apply`` now take enums `MixPose`and`MixDirection` instead of booleans + +### libGDX + +- Fixed renderer to work with 3.6 changes +- Added support for two color tinting. Use the new `TwoColorPolygonBatch` together with `SkeletonRenderer` +- Added support for clipping. See `SkeletonClipper`. Used automatically by `SkeletonRenderer`. Does not work when using a `SpriteBatch` with `SkeletonRenderer`. Use `PolygonSpriteBatch` or `TwoColorPolygonBatch` instead. +- Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect` and `VertexEffectTest`. + +## Lua + +- **Breaking changes** + - Removed `Bone:worldToLocalRotationX` and `Bone:worldToLocalRotationY`. Replaced by `Bone:worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + - `VertexAttachment:computeWorldVertices` now takes offsets and stride to allow compositing vertices directly in a vertex buffer to be send to the GPU. The compositing is now performed in the backends' respective renderers. This also affects the subclasses `MeshAttachment`, `BoundingBoxAttachment` and `PathAttachment`. + - Removed `RegionAttachment:updateWorldVertices`, added `RegionAttachment:computeWorldVertices`, which takes offsets and stride to allow compositing vertices directly in a vertex buffer to be send to the GPU. The compositing is now performed in the backends' respective renderers. + - Removed `MeshAttachment.worldVertices` field. Computation is now performed in each backends' respective renderer. The `uv` coordinates are now stored in `MeshAttachment.uvs`. + - Removed `RegionAttachment.vertices` field. Computation is now performed in each backends respective renderer. The `uv` coordinates for each vertex are now stored in the `RegionAttachment.uvs` field. + - The completion event will fire for looped 0 duration animations every frame. +- **Additions** +- Added `Bone:localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). +- Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. +- Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. +- Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` +- Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. +- Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. +- `AnimationState#apply` returns boolean indicating if any timeline was applied or not. +- `Animation#apply` and ` Timeline#apply`` now take enums `MixPose`and`MixDirection` instead of booleans +- Added `JitterEffect` and `SwirlEffect` and support for vertex effects in Corona and Love + +### Love2D + +- Fixed renderer to work with 3.6 changes +- Added support for two color tinting. Enable it via `SkeletonRenderer.new(true)`. +- Added clipping support. +- Added support for vertex effects. Set an implementation like "JitterEffect" on `Skeleton.vertexEffect`. See `main.lua` for an example. + +### Corona + +- Fixed renderer to work with 3.6 changes. Sadly, two color tinting is not supported, as Corona doesn't let us change the vertex format needed and its doesn't allow to modify shaders in the way needed for two color tinting +- Added clipping support. +- Added support for vertex effects. Set an implementation like "JitterEffect" on `SkeletonRenderer.vertexEffect`. See `main.lua` for an example + +## Typescript/Javascript + +- **Breaking changes** + + - `Skeleton.getBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. + - Removed `Bone.worldToLocalRotationX` and `Bone.worldToLocalRotationY`. Replaced by `Bone.worldToLocalRotation` (rotation given relative to x-axis, counter-clockwise, in degrees). + - Removed `VertexAttachment.computeWorldVertices` overload, changed `VertexAttachment.computeWorldVerticesWith` to `VertexAttachment.computeWorldVertices`, added `stride` parameter. + - Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now. + - Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer. + - The completion event will fire for looped 0 duration animations every frame. + - Removed the Spine Widget in favor of [Spine Web Player](https://esotericsoftware.com/spine-player). + +- **Additions** + - Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData` + - Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). + - Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. + - Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. + - Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface. + - Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments. + - `AnimationState#apply` returns boolean indicating if any timeline was applied or not. + - `Animation#apply` and ` Timeline#apply`` now take enums `MixPose`and`MixDirection` instead of booleans + - Added `AssetManager.loadTextureAtlas`. Instead of loading the `.atlas` and corresponding image files manually, you can simply specify the location of the `.atlas` file and AssetManager will load the atlas and all its images automatically. `AssetManager.get("atlasname.atlas")` will then return an instance of `spine.TextureAtlas`. + - Added the [Spine Web Player](https://esotericsoftware.com/spine-player) + +### WebGL backend + +- Fixed WebGL context loss + - Added `Restorable` interface, implemented by any WebGL resource that needs restoration after a context loss. All WebGL resource classes (`Shader`, `Mesh`, `GLTexture`) implement this interface. + - Added `ManagedWebGLRenderingContext`. Handles setup of a `WebGLRenderingContext` given a canvas element and restoration of WebGL resources (`Shader`, `Mesh`, `GLTexture`) on WebGL context loss. WebGL resources register themselves with the `ManagedWebGLRenderingContext`. If the context is informed of a context loss and restoration, the registered WebGL resources' `restore()` method is called. The `restore()` method implementation on each resource type will recreate the GPU side objects. + - All classes that previously took a `WebGLRenderingContext` in the constructor now also allow a `ManagedWebGLRenderingContext`. This ensures existing applications do not break. + - To use automatic context restauration: + 1. Create or fetch a canvas element from the DOM + 2. Instantiate a `ManagedWebGLRenderingContext`, passing the canvas to the constructor. This will setup a `WebGLRenderingContext` internally and manage context loss/restoration. + 3. Pass the `ManagedWebGLRenderingContext` to the constructors of classes that you previously passed a `WebGLRenderingContext` to (`AssetManager`, `GLTexture`, `Mesh`, `Shader`, `PolygonBatcher`, `SceneRenderer`, `ShapeRenderer`, `SkeletonRenderer`, `SkeletonDebugRenderer`). +- Fixed renderer to work with 3.6 changes. +- Added support for two color tinting. +- Improved performance by using `DYNAMIC_DRAW` for vertex buffer objects and fixing bug that copied to much data to the GPU each frame in `PolygonBatcher`/`Mesh`. +- Added two color tinting support, enabled by default. You can disable it via the constructors of `SceneRenderer`, `SkeletonRenderer`and `PolygonBatcher`. Note that you will need to use a shader created via `Shader.newTwoColoredTexturedShader` shader with `SkeletonRenderer` and `PolygonBatcher` if two color tinting is enabled. +- Added clipping support +- Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`, and the example which allows to set effects. +- Added `slotRangeStart` and `slotRangeEnd` parameters to `SkeletonRenderer#draw` and `SceneRenderer#drawSkeleton`. This allows you to render only a range of slots in the draw order. See `spine-ts/webgl/tests/test-slot-range.html` for an example. + +### Canvas backend + +- Fixed renderer to work for 3.6 changes. Sadly, we can't support two color tinting via the Canvas API. +- Added support for shearing and non-uniform scaling inherited from parent bones. +- Added support for alpha tinting. + +### Three.js backend + +- Fixed renderer to work with 3.6 changes. Two color tinting is not supported. +- Added clipping support +- Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`. +- Added support for multi-page atlases + +### Widget backend + +- Fixed WebGL context loss (see WebGL backend changes). Enabled automatically. +- Fixed renderer to work for 3.6 changes. Supports two color tinting & clipping (see WebGL backend changes for details). +- Added fields `atlasContent`, `atlasPagesContent`, and `jsonContent` to `WidgetConfiguration` allowing you to directly pass the contents of the `.atlas`, atlas page `.png` files, and the `.json` file without having to do a request. See `README.md` and the example for details. +- `SpineWidget.setAnimation()` now takes an additional optional parameter for callbacks when animations are completed/interrupted/etc. diff --git a/DateToSpine/third_party/spine-runtimes/4.3/LICENSE b/DateToSpine/third_party/spine-runtimes/4.3/LICENSE new file mode 100644 index 0000000..517ff9f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/LICENSE @@ -0,0 +1,26 @@ +Spine Runtimes License Agreement +Last updated April 5, 2025. Replaces all prior versions. + +Copyright (c) 2013-2025, Esoteric Software LLC + +Integration of the Spine Runtimes into software or otherwise creating +derivative works of the Spine Runtimes is permitted under the terms and +conditions of Section 2 of the Spine Editor License Agreement: +https://esotericsoftware.com/spine-editor-license + +Otherwise, it is permitted to integrate the Spine Runtimes into software +or otherwise create derivative works of the Spine Runtimes (collectively, +"Products"), provided that each user of the Products must obtain their own +Spine Editor license and redistribution of the Products in any form must +include this license and copyright notice. + +THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, +BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/DateToSpine/third_party/spine-runtimes/4.3/Package.swift b/DateToSpine/third_party/spine-runtimes/4.3/Package.swift new file mode 100644 index 0000000..99040d7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/Package.swift @@ -0,0 +1,73 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "spine-ios", + platforms: [ + .iOS(.v13), + .tvOS(.v13), + .macCatalyst(.v13), + .visionOS(.v1), + .macOS(.v10_15), + .watchOS(.v6), + ], + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "SpineC", + targets: ["SpineC"] + ), + .library( + name: "SpineSwift", + targets: ["SpineSwift"] + ), + .library( + name: "SpineiOS", + targets: ["SpineiOSWrapper"] + ), + ], + targets: [ + .target( + name: "SpineiOSWrapper", + dependencies: [ + .target(name: "SpineiOS", condition: .when(platforms: [.iOS, .visionOS, .tvOS, .macCatalyst, .macOS])) + ], + path: "spine-ios/Sources/SpineiOSWrapper" + ), + .target( + name: "SpineiOS", + dependencies: [ + "SpineSwift", + "SpineShadersStructs", + ], + path: "spine-ios/Sources/SpineiOS" + ), + .target( + name: "SpineC", + path: "spine-ios/Sources/SpineC", + sources: [ + "src", + "spine", + ], + linkerSettings: [ + .linkedLibrary("c++") + ] + ), + .target( + name: "SpineSwift", + dependencies: ["SpineC"], + path: "spine-ios/Sources/SpineSwift", + sources: [ + "Generated", + "Extensions", + ] + ), + .systemLibrary( + name: "SpineShadersStructs", + path: "spine-ios/Sources/SpineShadersStructs" + ), + ], + cxxLanguageStandard: .cxx11 +) diff --git a/DateToSpine/third_party/spine-runtimes/4.3/README.md b/DateToSpine/third_party/spine-runtimes/4.3/README.md new file mode 100644 index 0000000..9ad11f2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/README.md @@ -0,0 +1,33 @@ +# Spine Runtimes + +This GitHub project hosts the Spine Runtimes which are needed to use [Spine](http://esotericsoftware.com/) 2D skeletal animation data with various game toolkits. + +## Licensing + +You are welcome to evaluate the Spine Runtimes and the examples we provide in this repository free of charge. + +You can integrate the Spine Runtimes into your software free of charge, but users of your software must have their own [Spine license](https://esotericsoftware.com/spine-purchase). Please make your users aware of this requirement! This option is often chosen by those making development tools, such as an SDK, game toolkit, or software library. + +In order to distribute your software containing the Spine Runtimes to others that don't have a Spine license, you need a [Spine license](https://esotericsoftware.com/spine-purchase) at the time of integration. Then you can distribute your software containing the Spine Runtimes however you like, provided others don't modify it or use it to create new software. If others want to do that, they'll need their own Spine license. + +For the official legal terms governing the Spine Runtimes, please read the [Spine Runtimes License Agreement](http://esotericsoftware.com/spine-runtimes-license) and Section 2 of the [Spine Editor License Agreement](http://esotericsoftware.com/spine-editor-license#s2). + +## Documentation + +See the [Spine Runtimes Guide](http://esotericsoftware.com/spine-runtimes-guide) for detailed information about using the Spine Runtimes. The Spine [documentation page](http://esotericsoftware.com/spine-documentation#runtimes) provides further information about tools and data formats. For runtime specific documentation, refer to the `README.md` file in each runtime directory. + +## Bugs, enhancements, and tasks + +Review our backlog of bugs, enhancements, and tasks in the [spine-runtimes](https://github.com/EsotericSoftware/spine-runtimes/issues) and [spine-editor](https://github.com/EsotericSoftware/spine-editor/issues) issue trackers. Our [roadmap](http://esotericsoftware.com/spine-roadmap) provides a more convenient view of the same issue tracker information. + +## Versioning + +The default branch on GitHub is stable and works with data exported from the latest, non-beta version of the Spine editor. New development is done in an `X.X-beta` branch, which may be a work in progress. Important changes to the runtimes can be reviewed in the [CHANGELOG.md file](CHANGELOG.md). Occasionally the Spine Runtimes are [tagged](https://github.com/EsotericSoftware/spine-runtimes/releases) with the specific Spine editor version they work with. + +It is highly suggested to [freeze](http://esotericsoftware.com/spine-settings#Version) the Spine editor version to match the Spine Runtimes source being used and to update them in lock step. See the [Spine Runtimes Guide](http://esotericsoftware.com/spine-runtime-architecture#Versioning) for more information. + +## Contributing + +In order to merge your contributions, we need a signed [contributor license agreement (CLA)](http://esotericsoftware.com/licenses/cla.txt) from you. You can send a copy of the CLA to contact@esotericsoftware.com. + +When possible, it is best to base your contributions on the current beta branch (`X.X-beta`). Please be sure to follow the style and formatting you find in the respective runtime code to which you are contributing. diff --git a/DateToSpine/third_party/spine-runtimes/4.3/SpineConfig.cmake.in b/DateToSpine/third_party/spine-runtimes/4.3/SpineConfig.cmake.in new file mode 100644 index 0000000..601b05b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/SpineConfig.cmake.in @@ -0,0 +1 @@ +include("@CMAKE_CURRENT_BINARY_DIR@/spine-cpp/spine-cppTargets.cmake") \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/readme.txt b/DateToSpine/third_party/spine-runtimes/4.3/examples/readme.txt new file mode 100644 index 0000000..21ee01a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/examples/readme.txt @@ -0,0 +1,27 @@ +These example projects show off many of Spine's features. Below are a number +of other example resources that may prove useful. + +We have detailed documentation for how many of the example projects are built: +http://esotericsoftware.com/spine-examples + +See our online demos, which render Spine animations right in your browser: +http://esotericsoftware.com/spine-demos + +Learn how to use Spine with the Spine User Guide: +http://esotericsoftware.com/spine-user-guide +And the accompanying Spine User Guide videos: +https://www.youtube.com/playlist?list=PLwGl7Ikd_6GRFo7d0uRu_fN2RIlvkxW7b +And our other videos: +https://www.youtube.com/user/EsotericSoftware/videos + +Learn how to integrate Spine into your software: +http://esotericsoftware.com/spine-runtime-documentation + +Super Spineboy is a full example game using Spine and libgdx: +https://github.com/EsotericSoftware/spine-superspineboy + +Many companies around the world are doing great things with Spine: +http://esotericsoftware.com/spine-showcase + +Tag your tweets using #madewithspine to show up on our Twitter page: +http://esotericsoftware.com/madewithspine diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-ess.json b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-ess.json new file mode 100644 index 0000000..3b64174 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-ess.json @@ -0,0 +1,3672 @@ +{ +"skeleton": { + "hash": "ZIYEf9zI8T0", + "spine": "4.3.75-beta", + "x": -221.2667, + "y": -8.566437, + "width": 470.7179, + "height": 731.5727, + "images": "./images/", + "audio": null +}, +"bones": [ + { "name": "root" }, + { "name": "hip", "parent": "root", "y": 247.47426 }, + { + "name": "torso", + "parent": "hip", + "length": 127.5575, + "rotation": 103.82454, + "x": -1.6175153, + "y": 4.904114, + "color": "e0da19ff" + }, + { + "name": "front-upper-arm", + "parent": "torso", + "length": 69.45225, + "rotation": 168.37637, + "x": 103.75957, + "y": 19.329273, + "color": "00ff04ff" + }, + { + "name": "front-bracer", + "parent": "front-upper-arm", + "length": 40.57009, + "rotation": 18.299496, + "x": 68.8032, + "y": -0.6838684, + "color": "00ff04ff" + }, + { + "name": "front-fist", + "parent": "front-bracer", + "length": 65.3853, + "rotation": 12.433234, + "x": 40.56961, + "y": 0.1988964, + "color": "00ff04ff" + }, + { + "name": "front-thigh", + "parent": "hip", + "length": 74.80652, + "rotation": -95.51192, + "x": -17.45899, + "y": -11.644302, + "color": "00ff04ff" + }, + { + "name": "front-shin", + "parent": "front-thigh", + "length": 128.76756, + "rotation": -2.213562, + "x": 78.69012, + "y": 1.6017075, + "color": "00ff04ff" + }, + { + "name": "front-foot", + "parent": "front-shin", + "length": 91.34218, + "rotation": 77.90523, + "x": 128.7557, + "y": -0.3393288, + "color": "00ff04ff" + }, + { + "name": "rear-upper-arm", + "parent": "torso", + "length": 51.93936, + "rotation": -169.5554, + "x": 92.3564, + "y": -19.22086, + "color": "ff000dff" + }, + { "name": "rear-bracer", "parent": "rear-upper-arm", "length": 34.55841, "rotation": 23.15295, "x": 51.35799, "color": "ff000dff" }, + { + "name": "gun", + "parent": "rear-bracer", + "length": 43.10579, + "rotation": 5.347154, + "x": 34.42189, + "y": -0.4539795, + "color": "ff000dff" + }, + { "name": "gun-tip", "parent": "gun", "rotation": 6.832794, "x": 201.0489, "y": 52.1365, "color": "ff000dff" }, + { + "name": "neck", + "parent": "torso", + "length": 25.453945, + "rotation": -31.53788, + "x": 127.4972, + "y": -0.3085613, + "color": "e0da19ff" + }, + { + "name": "head", + "parent": "neck", + "length": 263.5777, + "rotation": 23.183784, + "x": 27.66327, + "y": -0.25990295, + "color": "e0da19ff" + }, + { + "name": "rear-thigh", + "parent": "hip", + "length": 85.7196, + "rotation": -72.541, + "x": 8.913322, + "y": -5.626694, + "color": "ff000dff" + }, + { + "name": "rear-shin", + "parent": "rear-thigh", + "length": 121.87728, + "rotation": -19.83334, + "x": 86.1, + "y": -1.3253326, + "color": "ff000dff" + }, + { + "name": "rear-foot", + "parent": "rear-shin", + "length": 82.57102, + "rotation": 69.30064, + "x": 121.45904, + "y": -0.7551935, + "color": "ff000dff" + } +], +"slots": [ + { "name": "rear-upper-arm", "bone": "rear-upper-arm", "attachment": "rear-upper-arm" }, + { "name": "rear-bracer", "bone": "rear-bracer", "attachment": "rear-bracer" }, + { "name": "gun", "bone": "gun", "attachment": "gun" }, + { "name": "rear-foot", "bone": "rear-foot", "attachment": "rear-foot" }, + { "name": "rear-thigh", "bone": "rear-thigh", "attachment": "rear-thigh" }, + { "name": "rear-shin", "bone": "rear-shin", "attachment": "rear-shin" }, + { "name": "neck", "bone": "neck", "attachment": "neck" }, + { "name": "torso", "bone": "torso", "attachment": "torso" }, + { "name": "front-upper-arm", "bone": "front-upper-arm", "attachment": "front-upper-arm" }, + { "name": "head", "bone": "head", "attachment": "head" }, + { "name": "eye", "bone": "head", "attachment": "eye-indifferent" }, + { "name": "front-thigh", "bone": "front-thigh", "attachment": "front-thigh" }, + { "name": "front-foot", "bone": "front-foot", "attachment": "front-foot" }, + { "name": "front-shin", "bone": "front-shin", "attachment": "front-shin" }, + { "name": "mouth", "bone": "head", "attachment": "mouth-smile" }, + { "name": "goggles", "bone": "head", "attachment": "goggles" }, + { "name": "front-bracer", "bone": "front-bracer", "attachment": "front-bracer" }, + { "name": "front-fist", "bone": "front-fist", "attachment": "front-fist-closed" }, + { "name": "muzzle", "bone": "gun-tip", "blend": "additive" }, + { "name": "head-bb", "bone": "head" } +], +"skins": [ + { + "name": "default", + "attachments": { + "eye": { + "eye-indifferent": { "x": 85.7211, "y": -28.18056, "rotation": -70.63152, "width": 93, "height": 89 }, + "eye-surprised": { "x": 85.7211, "y": -28.18056, "rotation": -70.63152, "width": 93, "height": 89 } + }, + "front-bracer": { + "front-bracer": { "x": 12.031342, "y": -1.6766033, "rotation": 79.59598, "width": 58, "height": 80 } + }, + "front-fist": { + "front-fist-closed": { "x": 35.49588, "y": 6.004703, "rotation": 67.16275, "width": 75, "height": 82 }, + "front-fist-open": { "x": 39.56648, "y": 7.764904, "rotation": 67.16275, "width": 86, "height": 87 } + }, + "front-foot": { + "front-foot": { "x": 29.518175, "y": 7.83878, "rotation": 18.68585, "width": 126, "height": 69 } + }, + "front-shin": { + "front-shin": { "x": 55.11751, "y": -3.5447235, "rotation": 96.59109, "width": 82, "height": 184 } + }, + "front-thigh": { + "front-thigh": { "x": 42.4751, "y": 4.449414, "rotation": 84.86587, "width": 45, "height": 112 } + }, + "front-upper-arm": { + "front-upper-arm": { "x": 25.195826, "y": 1.1720858, "rotation": 97.89548, "width": 46, "height": 97 } + }, + "goggles": { + "goggles": { "x": 97.07596, "y": 6.542373, "rotation": -70.63152, "width": 261, "height": 166 } + }, + "gun": { + "gun": { "x": 77.30423, "y": 16.40491, "rotation": 60.8259, "width": 210, "height": 203 } + }, + "head": { + "head": { "x": 128.9579, "y": 0.29974365, "rotation": -70.63152, "width": 271, "height": 298 } + }, + "head-bb": { + "head": { + "type": "boundingbox", + "vertexCount": 6, + "vertices": [ -19.14, -70.3, 40.8, -118.07, 257.77, -115.62, 285.16, 57.18, 120.77, 164.95, -5.07, 76.95 ] + } + }, + "mouth": { + "mouth-grind": { "x": 23.68707, "y": -32.23573, "rotation": -70.63152, "width": 93, "height": 59 }, + "mouth-oooo": { "x": 23.68707, "y": -32.23573, "rotation": -70.63152, "width": 93, "height": 59 }, + "mouth-smile": { "x": 23.68707, "y": -32.23573, "rotation": -70.63152, "width": 93, "height": 59 } + }, + "muzzle": { + "muzzle01": { + "x": 159.258, + "y": 5.827022, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15336847, + "width": 133, + "height": 79 + }, + "muzzle02": { + "x": 191.22733, + "y": 5.912605, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15336847, + "width": 135, + "height": 84 + }, + "muzzle03": { + "x": 230.67445, + "y": 6.018195, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15336847, + "width": 166, + "height": 106 + }, + "muzzle04": { + "x": 218.54355, + "y": 5.985696, + "scaleX": 4, + "scaleY": 4, + "rotation": 0.15336847, + "width": 149, + "height": 90 + } + }, + "neck": { + "neck": { "x": 9.7695, "y": -3.0127716, "rotation": -55.22381, "width": 36, "height": 41 } + }, + "rear-bracer": { + "rear-bracer": { "x": 11.151097, "y": -2.2033694, "rotation": 66.17306, "width": 56, "height": 72 } + }, + "rear-foot": { + "rear-foot": { "x": 31.51189, "y": 3.575588, "rotation": 23.073685, "width": 113, "height": 60 } + }, + "rear-shin": { + "rear-shin": { "x": 58.29028, "y": -2.754337, "rotation": 92.37433, "width": 75, "height": 178 } + }, + "rear-thigh": { + "rear-thigh": { "x": 33.10798, "y": -4.11312, "rotation": 72.541, "width": 55, "height": 94 } + }, + "rear-upper-arm": { + "rear-upper-arm": { "x": 21.125124, "y": 4.087035, "rotation": 89.326, "width": 40, "height": 87 } + }, + "torso": { + "torso": { "x": 63.61159, "y": 7.122709, "rotation": -94.53777, "width": 98, "height": 180 } + } + } + } +], +"events": { + "footstep": {} +}, +"animations": { + "aim": { + "bones": { + "front-bracer": { + "rotate": [ + { "value": 9.111553 } + ] + }, + "front-fist": { + "rotate": [ + { "value": 36.07917 } + ] + }, + "gun": { + "rotate": [ + { "value": -0.3051109 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": -26.552755 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "value": 62.30537 } + ] + } + } + }, + "death": { + "slots": { + "eye": { + "attachment": [ + { "name": "eye-surprised" }, + { "time": 0.4666667, "name": "eye-indifferent" }, + { "time": 2.233333, "name": "eye-surprised" }, + { "time": 4.533333, "name": "eye-indifferent" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "name": "mouth-oooo" }, + { "time": 2.233333, "name": "mouth-grind" }, + { "time": 4.533333, "name": "mouth-oooo" } + ] + } + }, + "bones": { + "front-bracer": { + "rotate": [ + { + "value": 21.88077, + "curve": [ 0.04765325, 21.48564, 0.08888888, 20.611794 ] + }, + { + "time": 0.13333334, + "value": 11.48504, + "curve": [ 0.15555555, 6.921661, 0.1777778, -12.781968 ] + }, + { + "time": 0.2, + "value": -19.18962, + "curve": [ 0.22222222, -25.597275, 0.24444444, -26.960876 ] + }, + { + "time": 0.2666667, + "value": -26.960876, + "curve": [ 0.3111111, -26.960876, 0.3555556, -25.038824 ] + }, + { + "time": 0.4, + "value": -15.90193, + "curve": [ 0.4333333, -9.04926, 0.4666667, 21.00781 ] + }, + { + "time": 0.5, + "value": 21.00781, + "curve": [ 0.5333333, 21.00781, 0.5666666, -6.780151 ] + }, + { + "time": 0.6, + "value": -18.226183, + "curve": [ 0.6222222, -25.85687, 0.6444444, -36.22235 ] + }, + { + "time": 0.6666667, + "value": -36.22235, + "curve": [ 0.6888888, -36.22235, 0.719783, 1.225752 ] + }, + { + "time": 0.7333333, + "value": 10.31088, + "curve": [ 0.7607757, 28.71031, 0.8222222, 44.19922 ] + }, + { + "time": 0.8666667, + "value": 44.19922, + "curve": [ 0.9111111, 44.19922, 1, -14.965016 ] + }, + { "time": 1, "value": -18.877235, "curve": "stepped" }, + { + "time": 2.233333, + "value": -18.877235, + "curve": [ 2.388889, -18.877235, 2.5444446, -1.9566765 ] + }, + { + "time": 2.7, + "value": -1.9566765, + "curve": [ 2.811111, -1.9566765, 2.922889, -10.35357 ] + }, + { + "time": 3.033333, + "value": -10.35357, + "curve": [ 3.224122, -10.35357, 3.411111, -1.7629414 ] + }, + { + "time": 3.6, + "value": -1.7629414, + "curve": [ 3.922222, -1.7629414, 4.244444, -1.9566765 ] + }, + { + "time": 4.566666, + "value": -1.9566765, + "curve": [ 4.644444, -1.9566765, 4.722222, 34.30784 ] + }, + { + "time": 4.8, + "value": 34.30784, + "curve": [ 4.844444, 34.30784, 4.888889, -1.064104 ] + }, + { "time": 4.933333, "value": -18.749977 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -2.333191, + "curve": [ 0.04444444, -1.8191817, 0.08888888, -0.7911634 ] + }, + { + "time": 0.13333334, + "value": -0.7911634, + "curve": [ 0.1777778, -0.7911634, 0.22222222, -12.86145 ] + }, + { + "time": 0.2666667, + "value": -12.86145, + "curve": [ 0.3222222, -12.86145, 0.37777776, -5.513781 ] + }, + { + "time": 0.4333333, + "value": -5.513781, + "curve": [ 0.5222222, -5.513781, 0.6111111, -23.932064 ] + }, + { + "time": 0.7, + "value": -23.932064, + "curve": [ 0.7666666, -23.932064, 0.8333333, 6.313117 ] + }, + { + "time": 0.9, + "value": 6.313117, + "curve": [ 0.9777778, 6.313117, 1.1141115, -2.632463 ] + }, + { "time": 1.1333333, "value": -5.629504, "curve": "stepped" }, + { "time": 2.233333, "value": -5.629504 }, + { "time": 2.4333334, "value": -17.372986 }, + { "time": 2.7, "value": 5.728967, "curve": "stepped" }, + { + "time": 3.3666666, + "value": 5.728966, + "curve": [ 3.5, 5.728966, 3.6333334, 1.9331503 ] + }, + { + "time": 3.766667, + "value": 1.9331503, + "curve": [ 3.8666666, 1.9331503, 3.966667, 7.130938 ] + }, + { + "time": 4.066666, + "value": 7.130938, + "curve": [ 4.266667, 7.130938, 4.466666, 5.728966 ] + }, + { + "time": 4.666666, + "value": 5.728966, + "curve": [ 4.677778, 5.728966, 4.732327, 13.732436 ] + }, + { + "time": 4.766667, + "value": 13.89022, + "curve": [ 4.832731, 14.19377, 4.933333, 4.948834 ] + }, + { "time": 4.933333, "value": 3.645131 } + ] + }, + "front-foot": { + "rotate": [ + { + "curve": [ 0.02222222, -21.89989, 0.04444444, -65.69968 ] + }, + { + "time": 0.06666667, + "value": -65.69968, + "curve": [ 0.0888889, -65.69968, 0.11111111, -65.69968 ] + }, + { + "time": 0.13333334, + "value": -64.64592, + "curve": [ 0.22222224, -60.43089, 0.3111111, -52.47852 ] + }, + { + "time": 0.4, + "value": -42.67871, + "curve": [ 0.4333333, -39.00378, 0.4666667, -33.17298 ] + }, + { + "time": 0.5, + "value": -24.221706, + "curve": [ 0.5444444, -12.28667, 0.5888889, 19.980225 ] + }, + { + "time": 0.6333333, + "value": 19.980225, + "curve": [ 0.6555555, 19.980225, 0.6777778, 13.200282 ] + }, + { + "time": 0.7, + "value": 2.445381, + "curve": [ 0.7333333, -13.68697, 0.7666666, -60.68153 ] + }, + { + "time": 0.8, + "value": -60.68153, + "curve": [ 0.8777778, -60.68153, 0.9555555, 0.3794708 ] + }, + { + "time": 1.0333333, + "value": 0.3794708, + "curve": [ 1.0777777, 0.3794708, 1.1222223, -31.76523 ] + }, + { + "time": 1.1666666, + "value": -31.76523, + "curve": [ 1.211111, -31.76523, 1.2555556, -26.73621 ] + }, + { "time": 1.3, "value": -24.221706 } + ] + }, + "front-shin": { + "rotate": [ + { + "curve": [ 0.04444444, 0.09444404, 0.100329, -7.137534 ] + }, + { + "time": 0.13333334, + "value": -14.66588, + "curve": [ 0.16911294, -22.82727, 0.22222222, -43.76862 ] + }, + { + "time": 0.2666667, + "value": -43.76862, + "curve": [ 0.3111111, -43.76862, 0.34441525, -43.26865 ] + }, + { + "time": 0.4, + "value": -33.93763, + "curve": [ 0.4333333, -28.341957, 0.4666667, 4.15356 ] + }, + { + "time": 0.5, + "value": 9.20168, + "curve": [ 0.5333333, 14.249802, 0.5666666, 14.249802 ] + }, + { + "time": 0.6, + "value": 14.249802, + "curve": [ 0.7333333, 14.249802, 0.8666667, 4.727212 ] + }, + { "time": 1, "value": -0.03408289 } + ] + }, + "front-thigh": { + "rotate": [ + { + "curve": [ 0.05230608, 4.37661, 0.08888888, 28.310297 ] + }, + { + "time": 0.13333334, + "value": 48.45476, + "curve": [ 0.1777778, 68.59923, 0.22222222, 99.393 ] + }, + { + "time": 0.2666667, + "value": 120.8668, + "curve": [ 0.3111111, 142.3406, 0.3555556, 169.01576 ] + }, + { + "time": 0.4, + "value": 177.29758, + "curve": [ 0.4333333, 183.50894, 0.4666667, 183.50894 ] + }, + { + "time": 0.5, + "value": 183.50894, + "curve": [ 0.5444444, 183.50894, 0.5888889, 176.5513 ] + }, + { + "time": 0.6333333, + "value": 162.2902, + "curve": [ 0.6777778, 148.0291, 0.7522012, 108.37154 ] + }, + { + "time": 0.7666666, + "value": 97.94228, + "curve": [ 0.8190776, 105.3437, 0.8555555, 110.73914 ] + }, + { + "time": 0.9, + "value": 110.73914, + "curve": [ 0.9444445, 110.73914, 1.0160767, 102.20138 ] + }, + { "time": 1.0333333, "value": 97.92922 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -35.84738, + "curve": [ 0.023699634, -41.485, 0.08888888, -48.7161 ] + }, + { + "time": 0.13333334, + "value": -48.7161, + "curve": [ 0.1777778, -48.7161, 0.22504207, -18.52254 ] + }, + { + "time": 0.2666667, + "value": -2.773605, + "curve": [ 0.3126675, 14.631088, 0.3555556, 29.37593 ] + }, + { + "time": 0.4, + "value": 42.9136, + "curve": [ 0.4111111, 46.29802, 0.4222222, 47.99266 ] + }, + { + "time": 0.4333333, + "value": 47.99266, + "curve": [ 0.4555556, 47.99266, 0.4819134, 40.58284 ] + }, + { + "time": 0.5, + "value": 35.0715, + "curve": [ 0.5333333, 24.914255, 0.5666666, 12.20925 ] + }, + { + "time": 0.6, + "value": 12.362442, + "curve": [ 0.6333333, 12.515633, 0.6666667, 35.68426 ] + }, + { + "time": 0.7, + "value": 35.68426, + "curve": [ 0.7888889, 35.68426, 0.8777778, 20.08158 ] + }, + { "time": 0.9666666, "value": 12.280243, "curve": "stepped" }, + { "time": 2.233333, "value": 12.280243 }, + { + "time": 2.5666666, + "value": 64.62625, + "curve": [ 2.588889, 66.48382, 2.611111, 69.7677 ] + }, + { + "time": 2.6333334, + "value": 70.19897, + "curve": [ 2.7555554, 72.57093, 2.878222, 73.07617 ] + }, + { + "time": 3, + "value": 73.0359, + "curve": [ 3.1892755, 72.97373, 3.3784294, 69.17685 ] + }, + { + "time": 3.5666666, + "value": 68.75519, + "curve": [ 3.734545, 68.38184, 3.902088, 72.60416 ] + }, + { + "time": 4.066666, + "value": 72.12396, + "curve": [ 4.224143, 71.6807, 4.377777, 72.12396 ] + }, + { + "time": 4.533333, + "value": 64.62625, + "curve": [ 4.622222, 60.34185, 4.711111, 42.62797 ] + }, + { "time": 4.8, "value": 31.6288 }, + { "time": 4.933333, "value": 10.71814 } + ] + }, + "gun": { + "rotate": [ + { "value": -2.788574 }, + { "time": 0.13333334, "value": -24.581026 } + ] + }, + "head": { + "rotate": [ + { + "value": -2.827988, + "curve": [ 0.04444444, -2.827988, 0.10522826, -14.973117 ] + }, + { + "time": 0.13333334, + "value": -21.88994, + "curve": [ 0.1583337, -28.04268, 0.2, -34.87368 ] + }, + { + "time": 0.23333333, + "value": -34.87368, + "curve": [ 0.2666667, -34.87368, 0.3, -34.21945 ] + }, + { + "time": 0.3333333, + "value": -33.32942, + "curve": [ 0.3555556, -32.73607, 0.3742754, -30.68751 ] + }, + { + "time": 0.4, + "value": -27.69693, + "curve": [ 0.4333333, -23.8218, 0.4666667, -10.63761 ] + }, + { + "time": 0.5, + "value": -10.63761, + "curve": [ 0.5222222, -10.63761, 0.5444444, -16.824955 ] + }, + { + "time": 0.5666666, + "value": -23.053745, + "curve": [ 0.5888889, -29.282536, 0.6111111, -49.33072 ] + }, + { + "time": 0.6333333, + "value": -55.91973, + "curve": [ 0.6777778, -69.09776, 0.7222222, -82.35488 ] + }, + { + "time": 0.7666666, + "value": -82.35488, + "curve": [ 0.786938, -78.35807, 0.9121876, -75.47412 ] + }, + { "time": 1, "value": -78.89935 }, + { + "time": 2.233333, + "value": -78.71664, + "curve": [ 2.289037, -78.71664, 2.344741, -66.24176 ] + }, + { + "time": 2.4, + "value": -58.39633, + "curve": [ 2.4336295, -53.72244, 2.467779, -52.1219 ] + }, + { + "time": 2.5, + "value": -51.96085, + "curve": [ 2.682782, -51.04724, 2.855555, -50.86477 ] + }, + { + "time": 3.033333, + "value": -50.86477, + "curve": [ 3.343341, -50.86477, 3.7119074, -53.09013 ] + }, + { + "time": 3.9333334, + "value": -55.93963, + "curve": [ 4.200474, -59.37741, 4.463112, -65.16606 ] + }, + { + "time": 4.533333, + "value": -69.07012, + "curve": [ 4.598495, -72.6929, 4.635026, -81.73537 ] + }, + { "time": 4.666666, "value": -85.28828 } + ], + "scale": [ + { + "time": 0.5, + "curve": [ 0.511111, 1, 0.5222222, 1.04094, 0.511111, 1, 0.5222222, 0.9533112 ] + }, + { + "time": 0.5333333, + "x": 1.04094, + "y": 0.9533112, + "curve": [ 0.5555555, 1.04094, 0.588889, 1.0375007, 0.5444444, 0.9533112, 0.588889, 0.9587328 ] + }, + { + "time": 0.6, + "x": 1.032634, + "y": 0.9664048, + "curve": [ 0.6333333, 1.0180334, 0.6666667, 0.989027, 0.6333333, 0.9894206, 0.6666667, 1.0139714 ] + }, + { + "time": 0.7, + "x": 0.989027, + "y": 1.0139714, + "curve": [ 0.7333333, 0.989027, 0.8, 1, 0.7333333, 1.0139714, 0.8, 1 ] + }, + { "time": 0.8333333 } + ] + }, + "hip": { + "translate": [ + { + "curve": [ 0.0806267, -41.13551, 0.17777777, -93.26612, 0.0376058, 78.72787, 0.15625, 168.4939 ] + }, + { + "time": 0.2666667, + "x": -137.7373, + "y": 169.656, + "curve": [ 0.3333333, -171.0907, 0.4, -202.8361, 0.3770834, 170.81807, 0.4666667, 29.156723 ] + }, + { + "time": 0.4666667, + "x": -233.4738, + "y": -76.62965, + "curve": [ 0.5, -248.7926, 0.5333333, -265.1634, 0.5212254, -158.3386, 0.5158661, -167.8958 ] + }, + { + "time": 0.5666666, + "x": -275.6068, + "y": -209.2767, + "curve": [ 0.5888889, -282.5691, 0.6083231, -285.1396, 0.5715881, -213.8729, 0.6111111, -216.23175 ] + }, + { + "time": 0.6333333, + "x": -285.6908, + "y": -216.23175, + "curve": [ 0.7129657, -287.4459, 0.7888889, -288.0775, 0.7111111, -216.23175, 0.8115123, -213.4927 ] + }, + { + "time": 0.8666667, + "x": -288.4433, + "y": -209.2767, + "curve": [ 0.9111111, -288.6523, 0.965, -288.6523, 0.91948, -209.2767, 0.967, -209.2767 ] + }, + { "time": 1, "x": -288.6523, "y": -209.2767 } + ] + }, + "neck": { + "rotate": [ + { + "value": -2.827988, + "curve": [ 0.03333333, -2.827988, 0.1, 12.354408 ] + }, + { + "time": 0.13333334, + "value": 12.354408, + "curve": [ 0.15833333, 12.354408, 0.2666667, 2.1809025 ] + }, + { + "time": 0.3333333, + "value": -8.480679, + "curve": [ 0.3888889, -17.36533, 0.44444445, -46.28429 ] + }, + { + "time": 0.5, + "value": -46.28429, + "curve": [ 0.5222222, -46.28429, 0.5509756, -12.177864 ] + }, + { + "time": 0.5666666, + "value": -2.9142685, + "curve": [ 0.5905015, 11.157253, 0.6111111, 20.8206 ] + }, + { + "time": 0.6333333, + "value": 23.427155, + "curve": [ 0.7555555, 37.76319, 0.8777778, 47.90275 ] + }, + { + "time": 1, + "value": 47.9135, + "curve": [ 1.4111112, 47.94965, 1.9348704, 47.94965 ] + }, + { + "time": 2.233333, + "value": 47.94965, + "curve": [ 2.322222, 47.94965, 2.4317274, 19.533627 ] + }, + { + "time": 2.5, + "value": 18.505486, + "curve": [ 2.666357, 16.000256, 2.766667, 14.585823 ] + }, + { + "time": 2.9, + "value": 14.585823, + "curve": [ 3.1555555, 14.585823, 3.4253654, 14.719418 ] + }, + { + "time": 3.666667, + "value": 15.234604, + "curve": [ 4.026068, 16.00194, 4.27963, 17.210606 ] + }, + { + "time": 4.466666, + "value": 18.505486, + "curve": [ 4.527323, 18.709293, 4.610005, 45.04741 ] + }, + { "time": 4.666666, "value": 47.94965 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": 10.362316 }, + { "time": 0.13333334, "value": -23.12078 }, + { "time": 0.2666667, "value": -23.117826 }, + { "time": 0.4, "value": -23.16442, "curve": "stepped" }, + { "time": 0.4333333, "value": -23.16442 }, + { "time": 0.5666666, "value": -23.20364 } + ] + }, + "rear-foot": { + "rotate": [ + { + "curve": [ 0.04444444, 0, 0.11438052, -5.440399 ] + }, + { + "time": 0.13333334, + "value": -11.625336, + "curve": [ 0.15780975, -19.612804, 0.22222222, -57.58895 ] + }, + { + "time": 0.2666667, + "value": -57.58895, + "curve": [ 0.3111111, -57.58895, 0.3555556, -45.59673 ] + }, + { + "time": 0.4, + "value": -45.59673, + "curve": [ 0.4333333, -45.59673, 0.4666667, -65.98876 ] + }, + { + "time": 0.5, + "value": -65.98876, + "curve": [ 0.5222222, -65.98876, 0.5444444, -21.704247 ] + }, + { + "time": 0.5666666, + "value": -21.704247, + "curve": [ 0.6, -21.704247, 0.6333333, -47.61348 ] + }, + { + "time": 0.6666667, + "value": -47.61348, + "curve": [ 0.7222222, -47.61348, 0.7777778, -25.675274 ] + }, + { + "time": 0.8333333, + "value": -15.601372, + "curve": [ 0.8777778, -7.542251, 0.9222222, 6.785583 ] + }, + { + "time": 0.9666666, + "value": 6.785583, + "curve": [ 1.022222, 6.785583, 1.0926592, 2.2258835 ] + }, + { + "time": 1.1333333, + "value": -6.817798, + "curve": [ 1.1651403, -13.889915, 1.177963, -28.53307 ] + }, + { + "time": 1.2, + "value": -28.53307, + "curve": [ 1.2666667, -28.53307, 1.3333334, -23.772514 ] + }, + { "time": 1.4, "value": -23.772514 } + ] + }, + "rear-shin": { + "rotate": [ + { + "curve": [ 0.04444444, -19.5857, 0.08888888, -58.7571 ] + }, + { + "time": 0.13333334, + "value": -58.7571, + "curve": [ 0.1777778, -58.7571, 0.22222222, -54.53332 ] + }, + { + "time": 0.2666667, + "value": -47.84583, + "curve": [ 0.3111111, -41.15834, 0.3555556, -33.23767 ] + }, + { + "time": 0.4, + "value": -18.632143, + "curve": [ 0.4333333, -7.677995, 0.4666667, 28.8332 ] + }, + { + "time": 0.5, + "value": 28.8332, + "curve": [ 0.5333333, 28.8332, 0.5666666, 15.166332 ] + }, + { + "time": 0.6, + "value": 15.166332, + "curve": [ 0.6333333, 15.166332, 0.6666667, 16.16775 ] + }, + { + "time": 0.7, + "value": 18.37433, + "curve": [ 0.7444445, 21.316437, 0.7888889, 27.27072 ] + }, + { + "time": 0.8333333, + "value": 30.6124, + "curve": [ 0.8777778, 33.95408, 0.9222222, 38.42441 ] + }, + { + "time": 0.9666666, + "value": 38.42441, + "curve": [ 1.011111, 38.42441, 1.079456, 17.38622 ] + }, + { "time": 1.1, "value": 9.10776 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "curve": [ 0.04444444, 21.881306, 0.08888888, 41.0123 ] + }, + { + "time": 0.13333334, + "value": 65.64391, + "curve": [ 0.1777778, 90.27553, 0.22222222, 127.14987 ] + }, + { + "time": 0.2666667, + "value": 147.78967, + "curve": [ 0.3111111, 168.42947, 0.3555556, 189.48274 ] + }, + { + "time": 0.4, + "value": 189.48274, + "curve": [ 0.4333333, 189.48274, 0.47272015, 161.80136 ] + }, + { + "time": 0.5, + "value": 142.56204, + "curve": [ 0.5417124, 113.14404, 0.5890308, 83.0406 ] + }, + { + "time": 0.6, + "value": 78.14767, + "curve": [ 0.6129926, 83.0406, 0.7333333, 108.15988 ] + }, + { + "time": 0.8, + "value": 108.15988, + "curve": [ 0.8777778, 108.15988, 1.0094314, 88.70855 ] + }, + { "time": 1.0333333, "value": 82.7022 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": -44.69556, + "curve": [ 0.04444444, -44.69556, 0.08888888, 52.29729 ] + }, + { + "time": 0.13333334, + "value": 52.29729, + "curve": [ 0.1777778, 52.29729, 0.2274992, 48.52106 ] + }, + { + "time": 0.2666667, + "value": 41.26524, + "curve": [ 0.3321974, 29.12554, 0.3555556, 21.32808 ] + }, + { + "time": 0.4, + "value": 21.32808, + "curve": [ 0.5111112, 21.32808, 0.5765158, 177.3239 ] + }, + { + "time": 0.6666667, + "value": 178.37254, + "curve": [ 0.7026742, 178.7914, 0.8222222, 158.2047 ] + }, + { "time": 0.9, "value": 158.2047 } + ], + "translate": [ + { "time": 0.4 }, + { "time": 0.9, "x": -32.41095, "y": 0.6460266 } + ] + }, + "torso": { + "rotate": [ + { + "value": -8.61538, + "curve": [ 0.03105691, -16.413063, 0.1, -26.52448 ] + }, + { + "time": 0.13333334, + "value": -26.52448, + "curve": [ 0.16666667, -26.52448, 0.2331514, 3.446968 ] + }, + { + "time": 0.2666667, + "value": 21.92246, + "curve": [ 0.3262331, 54.75878, 0.4222222, 108.5424 ] + }, + { + "time": 0.5, + "value": 108.5424, + "curve": [ 0.5222222, 108.5424, 0.5589602, 79.42354 ] + }, + { + "time": 0.5666666, + "value": 76.6731, + "curve": [ 0.5774248, 72.83357, 0.6333333, 68.67604 ] + }, + { + "time": 0.6666667, + "value": 68.67604, + "curve": [ 0.7333333, 68.67604, 0.8, 74.71478 ] + }, + { "time": 0.8666667, "value": 74.71478, "curve": "stepped" }, + { + "time": 2.333333, + "value": 74.71478, + "curve": [ 2.58, 74.71478, 2.789609, 72.33188 ] + }, + { + "time": 2.966667, + "value": 72.00104, + "curve": [ 3.4394035, 71.11778, 3.668485, 70.88917 ] + }, + { + "time": 4, + "value": 71.2912, + "curve": [ 4.188636, 71.51996, 4.285642, 72.54675 ] + }, + { "time": 4.666666, "value": 74.71478 } + ] + } + } + }, + "hit": { + "slots": { + "front-fist": { + "attachment": [ + { "time": 0.16666667, "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "name": "mouth-grind" }, + { "time": 0.3333333, "name": "mouth-smile" } + ] + } + }, + "bones": { + "front-bracer": { + "rotate": [ + { "value": 36.99312 }, + { "time": 0.3333333, "value": -28.6463 } + ] + }, + "front-fist": { + "rotate": [ + { "value": 13.591016 }, + { "time": 0.3333333, "value": 7.556878 } + ] + }, + "front-foot": { + "rotate": [ + { "value": 5.400009 }, + { "time": 0.3333333, "value": -16.268566 } + ] + }, + "front-shin": { + "rotate": [ + { "value": -96.6282 }, + { "time": 0.3333333, "value": -15.132477 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 90.94447, + "curve": [ 0.07571428, 75.2907, 0.1442857, 32.0294 ] + }, + { "time": 0.3333333, "value": 32.02941 } + ], + "translate": [ + { "x": 7.211654, "y": -4.002517 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -310.9298, + "curve": [ 0.1267361, -397.1531, 0.24826387, -472.5985 ] + }, + { "time": 0.3333333, "value": -472.5985 } + ], + "translate": [ + { "x": 7.231369, "y": -13.132236 } + ] + }, + "gun": { + "rotate": [ + { "value": 14.982923 }, + { "time": 0.3333333, "value": 39.75595 } + ] + }, + "head": { + "rotate": [ + { "value": 10.21898 }, + { "time": 0.3333333, "value": -41.30352 } + ] + }, + "hip": { + "translate": [ + { "x": -75.54526, "y": -78.03895 }, + { "time": 0.23333333, "x": -36.48128, "y": 12.424912 }, + { "time": 0.3333333, "x": -36.48128, "y": -2.995102 } + ] + }, + "neck": { + "rotate": [ + { "value": 35.38671 }, + { "time": 0.23333333, "value": 24.94708 } + ] + }, + "rear-bracer": { + "rotate": [ + {}, + { "time": 0.3333333, "value": 40.03007 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": 2.67334 }, + { "time": 0.3333333, "value": -10.314632 } + ] + }, + "rear-shin": { + "rotate": [ + { "value": 7.996297 }, + { "time": 0.3333333, "value": -67.54288 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 40.5171, + "curve": [ 0.09857143, 55.81052, 0.1966667, 90.52415 ] + }, + { "time": 0.3333333, "value": 90.7669 } + ], + "translate": [ + { "x": -1.9603825, "y": -0.3220158 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 271.0247, + "curve": [ 0.11425311, 297.6275, 0.2267213, 322.9662 ] + }, + { "time": 0.3333333, "value": 344.1574 } + ], + "translate": [ + { "time": 0.3333333, "x": -0.0969696, "y": -0.4601879 } + ] + }, + "torso": { + "rotate": [ + { "value": 56.42499 }, + { "time": 0.3333333, "value": 8.890213 } + ] + } + } + }, + "idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-bracer": { + "rotate": [ + { + "value": 35.20196, + "curve": [ 0.08614543, 36.02967, 0.5142749, 40.31417 ] + }, + { + "time": 0.6666667, + "value": 40.30441, + "curve": [ 0.8590339, 40.2921, 0.9693015, 32.2449 ] + }, + { + "time": 1.2, + "value": 32.31207, + "curve": [ 1.400866, 32.37055, 1.561119, 34.14052 ] + }, + { "time": 1.6666666, "value": 35.20196 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -6.849997, + "curve": [ 0.1808034, -5.229439, 0.5000536, -3.9733105 ] + }, + { + "time": 0.6666667, + "value": -3.894995, + "curve": [ 0.8401266, -3.813463, 1.0415212, -9.892107 ] + }, + { + "time": 1.2666667, + "value": -9.757078, + "curve": [ 1.4280664, -9.66028, 1.5369933, -8.301444 ] + }, + { "time": 1.6666666, "value": -6.849997 } + ], + "scale": [ + { + "curve": [ 0.16666667, 1, 0.5, 0.8859755, 0.16666667, 1, 0.5, 1.1009042 ] + }, + { + "time": 0.6666667, + "x": 0.8859755, + "y": 1.1009042, + "curve": [ 0.9166667, 0.8859755, 1.4166666, 1, 0.9166667, 1.1009042, 1.4166666, 1 ] + }, + { "time": 1.6666666 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 4.829063, + "curve": [ 0.15714332, 4.877132, 0.3723805, 10.017288 ] + }, + { + "time": 0.6666667, + "value": 10.049973, + "curve": [ 1.261546, 10.045224, 1.319688, 5.13523 ] + }, + { "time": 1.6666666, "value": 5.135231 } + ], + "scale": [ + { "x": 0.7550893, "y": 1.309609 } + ] + }, + "front-shin": { + "rotate": [ + { "value": -19.59419 } + ], + "scale": [ + { + "curve": [ 0.15714332, 0.9999414, 0.3723805, 0.9940548, 0.15714332, 1, 0.3723805, 1 ] + }, + { + "time": 0.6666667, + "x": 0.994015, + "curve": [ 1.261546, 0.9940207, 1.319688, 1, 1.261546, 1, 1.319688, 1 ] + }, + { "time": 1.6666666 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 0.6482467, + "curve": [ 0.15714332, 0.5994586, 0.3723805, -4.306915 ] + }, + { + "time": 0.6666667, + "value": -4.340088, + "curve": [ 1.261546, -4.335269, 1.319688, 0.6482467 ] + }, + { "time": 1.6666666, "value": 0.6482467 } + ], + "translate": [ + { "x": -13.39598, "y": 6.697418 } + ], + "scale": [ + { + "x": 0.9450903, + "curve": [ 0.15714332, 0.9448118, 0.3723805, 0.9167997, 0.15714332, 1, 0.3723805, 1 ] + }, + { + "time": 0.6666667, + "x": 0.9166103, + "curve": [ 1.261546, 0.9166378, 1.319688, 0.9450903, 1.261546, 1, 1.319688, 1 ] + }, + { "time": 1.6666666, "x": 0.9450903 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -59.85017, + "curve": [ 0.3285714, -59.85017, 0.4466667, -64.99493 ] + }, + { + "time": 0.6666667, + "value": -64.99493, + "curve": [ 0.9966667, -64.99493, 1.4166666, -59.85017 ] + }, + { "time": 1.6666666, "value": -59.85017 } + ], + "translate": [ + { + "x": -7.120605, + "y": -8.239807, + "curve": [ 0.16666667, -7.120605, 0.5, -3.664642, 0.16666667, -8.239807, 0.5, -5.931425 ] + }, + { + "time": 0.6666667, + "x": -3.664642, + "y": -5.931425, + "curve": [ 0.9166667, -3.664642, 1.4166666, -7.120605, 0.9166667, -5.931425, 1.4166666, -8.239807 ] + }, + { "time": 1.6666666, "x": -7.120605, "y": -8.239807 } + ] + }, + "gun": { + "rotate": [ + { + "curve": [ 0.16666667, 0, 0.5806666, -12.704934 ] + }, + { + "time": 0.8666667, + "value": -12.704934, + "curve": [ 1.1306666, -12.704934, 1.4366664, -0.1142168 ] + }, + { "time": 1.6666666 } + ] + }, + "head": { + "rotate": [ + { + "value": -5.512752, + "curve": [ 0.16666667, -5.512752, 0.7, -3.120014 ] + }, + { + "time": 0.8666667, + "value": -3.120014, + "curve": [ 1.1166667, -3.120014, 1.4166666, -5.512752 ] + }, + { "time": 1.6666666, "value": -5.512752 } + ], + "scale": [ + { + "curve": [ 0.21666667, 1, 0.546, 0.99599, 0.21666667, 1, 0.546, 1.007131 ] + }, + { + "time": 0.8666667, + "x": 0.99599, + "y": 1.007131, + "curve": [ 1.1706666, 0.99599, 1.4666667, 1, 1.1706666, 1.007131, 1.4666667, 1 ] + }, + { "time": 1.6666666 } + ] + }, + "hip": { + "translate": [ + { + "x": -6.636276, + "y": -23.01602, + "curve": [ 0.15714332, -6.509955, 0.3723805, 6.193538, 0.15714332, -23.13332, 0.3723805, -34.92935 ] + }, + { + "time": 0.6666667, + "x": 6.27943, + "y": -35.00911, + "curve": [ 1.261546, 6.266953, 1.319688, -6.636278, 1.261546, -34.99752, 1.319688, -23.01602 ] + }, + { "time": 1.6666666, "x": -6.636276, "y": -23.01602 } + ] + }, + "neck": { + "rotate": [ + { + "curve": [ 0.16666667, 0, 0.5, 2.392738 ] + }, + { + "time": 0.6666667, + "value": 2.392738, + "curve": [ 0.9166667, 2.392738, 1.4166666, 0 ] + }, + { "time": 1.6666666 } + ], + "translate": [ + { "x": -1.8856354, "y": -4.760834 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": -17.161516, + "curve": [ 0.16666667, -17.161516, 0.4466667, -4.096819 ] + }, + { + "time": 0.6666667, + "value": -4.096819, + "curve": [ 0.9966667, -4.096819, 1.4166666, -17.161516 ] + }, + { "time": 1.6666666, "value": -17.161516 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -7.650287, + "curve": [ 0.15714332, -7.540795, 0.3723805, 3.77645 ] + }, + { + "time": 0.6666667, + "value": 3.850899, + "curve": [ 1.261546, 3.840084, 1.319688, -7.344117 ] + }, + { "time": 1.6666666, "value": -7.344116 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -24.136686, + "curve": [ 0.15714332, -24.33175, 0.3723805, -43.64235 ] + }, + { + "time": 0.6666667, + "value": -43.77499, + "curve": [ 1.261546, -43.75572, 1.319688, -23.830513 ] + }, + { "time": 1.6666666, "value": -23.830515 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 30.509033, + "curve": [ 0.15714332, 30.60334, 0.3723805, 40.0871 ] + }, + { + "time": 0.6666667, + "value": 40.15123, + "curve": [ 1.261546, 40.14191, 1.319688, 30.509033 ] + }, + { "time": 1.6666666, "value": 30.509033 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 39.07769, + "curve": [ 0.3698095, 38.66915, 0.55, 32.29218 ] + }, + { + "time": 0.7333333, + "value": 32.29218, + "curve": [ 0.9666666, 32.29218, 1.4333333, 39.07769 ] + }, + { "time": 1.6666666, "value": 39.07769 } + ], + "translate": [ + { + "x": -1.8345642, + "y": -6.477024, + "curve": [ 0.16666667, -1.8345642, 0.5, 0.3473206, 0.16666667, -6.477024, 0.4466667, -4.923374 ] + }, + { + "time": 0.6666667, + "x": 0.3473206, + "y": -4.923374, + "curve": [ 0.9166667, 0.3473206, 1.4166666, -1.8345642, 0.9166667, -4.923374, 1.4166666, -6.477024 ] + }, + { "time": 1.6666666, "x": -1.8345642, "y": -6.477024 } + ] + }, + "torso": { + "rotate": [ + { + "value": -16.109444, + "curve": [ 0.05703678, -15.697838, 0.2675635, -14.614166 ] + }, + { + "time": 0.4333333, + "value": -14.60328, + "curve": [ 0.5914692, -14.592892, 0.7300568, -15.811089 ] + }, + { + "time": 0.8333333, + "value": -16.625565, + "curve": [ 0.9147995, -17.268036, 1.0743365, -18.04142 ] + }, + { + "time": 1.2333333, + "value": -18.02047, + "curve": [ 1.3847555, -18.00052, 1.6189284, -16.568924 ] + }, + { "time": 1.6666666, "value": -16.109444 } + ], + "translate": [ + { "x": -6.495994 } + ], + "scale": [ + { + "curve": [ 0.15614077, 0.996003, 0.5250046, 0.9935031, 0.10606003, 1.0024865, 0.5250046, 1.0104884 ] + }, + { + "time": 0.8333333, + "x": 0.9935031, + "y": 1.0104884, + "curve": [ 1.1499954, 0.9935031, 1.5196174, 0.997364, 1.1499954, 1.0104884, 1.5192473, 1.0037645 ] + }, + { "time": 1.6666666 } + ] + } + } + }, + "jump": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" }, + { "time": 0.1, "name": "front-fist-closed" }, + { "time": 0.8333333, "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-bracer": { + "rotate": [ + { + "value": 20.536366, + "curve": [ 0.054479, 32.22879, 0.1920287, 55.84296 ] + }, + { + "time": 0.23333333, + "value": 62.57772, + "curve": [ 0.2903467, 71.87382, 0.3750252, 79.28102 ] + }, + { + "time": 0.4333333, + "value": 79.18405, + "curve": [ 0.5546791, 78.98224, 0.6837272, 27.53711 ] + }, + { + "time": 0.7333333, + "value": 13.280796, + "curve": [ 0.785987, -1.851322, 0.8744862, -24.76372 ] + }, + { + "time": 1, + "value": -25.451767, + "curve": [ 1.164866, -26.35554, 1.303476, 9.098476 ] + }, + { "time": 1.3333334, "value": 20.536366 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16143, + "curve": [ 0.11426024, -39.59057, 0.3, -45.60855 ] + }, + { + "time": 0.4, + "value": -45.60855, + "curve": [ 0.4416667, -45.60855, 0.5367003, -21.53749 ] + }, + { + "time": 0.5666666, + "value": -15.396365, + "curve": [ 0.5918796, -10.22935, 0.6916011, 11.892562 ] + }, + { + "time": 0.7333333, + "value": 11.73226, + "curve": [ 0.7830127, 11.541427, 0.8309314, 1.8034153 ] + }, + { + "time": 0.8666667, + "value": -5.78305, + "curve": [ 0.8969967, -12.221985, 0.9008168, -14.216885 ] + }, + { + "time": 0.9333333, + "value": -14.51377, + "curve": [ 0.9742595, -14.88744, 0.9759359, 10.380578 ] + }, + { + "time": 1, + "value": 10.547044, + "curve": [ 1.027373, 10.7364, 1.0228404, -8.439857 ] + }, + { + "time": 1.0333333, + "value": -8.417142, + "curve": [ 1.059476, -8.360548, 1.073571, 10.116536 ] + }, + { + "time": 1.1, + "value": 10.219346, + "curve": [ 1.168007, 10.483893, 1.269697, -36.06642 ] + }, + { "time": 1.3333334, "value": -36.16143 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 15.881874, + "curve": [ 0, 13.332153, 0.05, -26.644875 ] + }, + { + "time": 0.06666667, + "value": -26.644875, + "curve": [ 0.19166666, -26.644875, 0.4416667, -11.77327 ] + }, + { + "time": 0.5666666, + "value": -11.77327, + "curve": [ 0.6916666, -11.77327, 0.9416666, -19.36478 ] + }, + { + "time": 1.0666667, + "value": -19.36478, + "curve": [ 1.0892178, -19.36478, 1.1270255, -67.74357 ] + }, + { + "time": 1.1666666, + "value": -63.62297, + "curve": [ 1.1780022, -62.50552, 1.188889, 5.83041 ] + }, + { + "time": 1.2, + "value": 11.391548, + "curve": [ 1.2222222, 22.513824, 1.2444444, 22.513824 ] + }, + { + "time": 1.2666667, + "value": 22.513824, + "curve": [ 1.288889, 22.513824, 1.3333334, 16.45131 ] + }, + { "time": 1.3333334, "value": 15.881874 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -74.18883, + "curve": [ 0, -51.13796, 0.04227064, -12.53828 ] + }, + { + "time": 0.16666667, + "value": -12.284243, + "curve": [ 0.284518, -12.320733, 0.3888889, -51.95743 ] + }, + { + "time": 0.5, + "value": -51.95743, + "curve": [ 0.6333333, -51.95743, 0.7666666, -40.17094 ] + }, + { + "time": 0.9, + "value": -30.59048, + "curve": [ 0.9666666, -25.800253, 1.0333333, -16.01426 ] + }, + { + "time": 1.1, + "value": -8.845377, + "curve": [ 1.1222223, -6.45575, 1.1444443, -1.9149498 ] + }, + { + "time": 1.1666666, + "value": -1.9149498, + "curve": [ 1.1777778, -1.9149498, 1.188889, -58.18646 ] + }, + { + "time": 1.2, + "value": -72.70922, + "curve": [ 1.211111, -87.23198, 1.2222222, -89.0515 ] + }, + { + "time": 1.2333333, + "value": -89.0515, + "curve": [ 1.2731713, -89.0515, 1.308165, -79.55212 ] + }, + { "time": 1.3333334, "value": -74.18883 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 55.07567, + "curve": [ 0.007130125, 46.6568, 0.04317886, 26.299644 ] + }, + { + "time": 0.06666667, + "value": 22.83655, + "curve": [ 0.0995464, 17.988686, 0.16537325, 15.78083 ] + }, + { + "time": 0.23333333, + "value": 15.70864, + "curve": [ 0.3091745, 15.628075, 0.4111111, 36.55978 ] + }, + { + "time": 0.5, + "value": 36.55978, + "curve": [ 0.6555556, 36.55978, 0.8111111, 33.4092 ] + }, + { + "time": 0.9666666, + "value": 26.42671, + "curve": [ 1.011111, 24.43171, 1.0555556, 9.627315 ] + }, + { + "time": 1.1, + "value": 9.627315, + "curve": [ 1.1222223, 9.627315, 1.1444443, 9.627315 ] + }, + { + "time": 1.1666666, + "value": 12.329086, + "curve": [ 1.1777778, 13.679972, 1.188889, 47.61562 ] + }, + { + "time": 1.2, + "value": 56.84734, + "curve": [ 1.211111, 66.07905, 1.2219068, 67.69607 ] + }, + { + "time": 1.2333333, + "value": 67.7194, + "curve": [ 1.2605002, 67.77487, 1.322246, 58.12479 ] + }, + { "time": 1.3333334, "value": 55.07567 } + ], + "translate": [ + { + "x": -5.134582, + "y": 11.552978, + "curve": [ 0.4222222, -5.134582, 0.7333333, -5.24807, 0.4222222, 11.552978, 0.7333333, 11.552978 ] + }, + { + "time": 1.1, + "x": -5.24807, + "y": 11.552978, + "curve": [ 1.1333333, -5.24807, 1.167037, -4.544554, 1.1333333, 11.552978, 1.1666666, -1.071207 ] + }, + { + "time": 1.2, + "x": -3.978987, + "y": -1.071207, + "curve": [ 1.2112963, -3.793068, 1.2224075, -3.6224136, 1.211111, -1.071207, 1.2224075, 5.215895 ] + }, + { + "time": 1.2333333, + "x": -3.4965496, + "y": 5.728848, + "curve": [ 1.244537, -3.3706856, 1.288889, -3.676304, 1.244537, 6.241801, 1.283023, 5.143962 ] + }, + { + "time": 1.3, + "x": -4.100271, + "y": 5.225724, + "curve": [ 1.311111, -4.524238, 1.322222, -4.985481, 1.320264, 5.323314, 1.322222, 9.776308 ] + }, + { "time": 1.3333334, "x": -5.134582, "y": 11.552978 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -40.20753, + "curve": [ 0.0536731, -35.4564, 0.15, -31.119186 ] + }, + { + "time": 0.2, + "value": -31.119186, + "curve": [ 0.3083333, -31.119186, 0.5466946, -80.11781 ] + }, + { + "time": 0.6333333, + "value": -96.56404, + "curve": [ 0.6965202, -108.5585, 0.796608, -112.53702 ] + }, + { + "time": 0.8666667, + "value": -112.59852, + "curve": [ 1.1365902, -112.8355, 1.2737077, -49.19292 ] + }, + { "time": 1.3333334, "value": -40.20753 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.364543, + "curve": [ 0.022356797, 16.282055, 0.15, 30.81017 ] + }, + { + "time": 0.2, + "value": 30.81017, + "curve": [ 0.2583333, 30.81017, 0.375, 13.257755 ] + }, + { + "time": 0.4333333, + "value": 13.257755, + "curve": [ 0.5083333, 13.257755, 0.6584936, 15.046124 ] + }, + { + "time": 0.7333333, + "value": 14.982923, + "curve": [ 0.7894168, 14.935562, 0.8279614, 13.620555 ] + }, + { + "time": 0.8666667, + "value": 12.72069, + "curve": [ 0.8868754, 12.250854, 0.9843205, 9.831252 ] + }, + { + "time": 1.0333333, + "value": 8.599857, + "curve": [ 1.0447482, 8.31307, 1.0826218, 7.5548 ] + }, + { + "time": 1.1333333, + "value": 7.128548, + "curve": [ 1.1752198, 6.776476, 1.2833333, 6.182274 ] + }, + { "time": 1.3333334, "value": 6.182274 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.143766, + "curve": [ 0.06306307, 13.100246, 0.22222222, -20.77876 ] + }, + { + "time": 0.3333333, + "value": -20.77876, + "curve": [ 0.4666667, -20.77876, 0.6, 7.262495 ] + }, + { + "time": 0.7333333, + "value": 11.442162, + "curve": [ 0.8111111, 13.8803, 0.8888889, 13.8803 ] + }, + { + "time": 0.9666666, + "value": 13.8803, + "curve": [ 1.0444444, 13.8803, 1.1222223, 7.559704 ] + }, + { + "time": 1.2, + "value": 7.559704, + "curve": [ 1.2444444, 7.559704, 1.288889, 11.282413 ] + }, + { "time": 1.3333334, "value": 13.143766 } + ], + "scale": [ + { + "curve": [ 0.04056496, 1, 0.05244635, 0.9616517, 0.04056496, 1, 0.05244635, 1.1370772 ] + }, + { + "time": 0.1, + "x": 0.9541517, + "y": 1.1370772, + "curve": [ 0.2021565, 0.9616517, 0.3177854, 1, 0.2021565, 1.1370772, 0.2518122, 1.0023715 ] + }, + { "time": 0.4666667 }, + { + "time": 1.0666667, + "x": 1.00178, + "curve": [ 1.0916667, 1.00178, 1.126085, 1.1728513, 1.0916667, 1, 1.128311, 0.9745202 ] + }, + { + "time": 1.1666666, + "x": 1.173767, + "y": 0.9733993, + "curve": [ 1.2036642, 1.174602, 1.233349, 0.958515, 1.206164, 0.972245, 1.226671, 1.0624334 ] + }, + { + "time": 1.2666667, + "x": 0.9582605, + "y": 1.0626047, + "curve": [ 1.283691, 0.9581305, 1.311111, 1, 1.28767, 1.0626947, 1.311111, 1 ] + }, + { "time": 1.3333334 } + ] + }, + "hip": { + "translate": [ + { + "y": -45.45778, + "curve": [ 0.04166667, -0.0852939, 0.15, 15.21902, 0.03129127, 44.98263, 0.12330207, 289.72595 ] + }, + { + "time": 0.2, + "x": 15.21902, + "y": 415.8538, + "curve": [ 0.3315271, 15.21902, 0.5392024, -34.51724, 0.2711933, 532.9294, 0.4828083, 753.8663 ] + }, + { + "time": 0.7666666, + "x": -34.51724, + "y": 754.963, + "curve": [ 0.8875864, -34.51724, 1.0574986, -21.949486, 1.0490158, 754.5415, 1.0975217, 379.8363 ] + }, + { + "time": 1.1333333, + "x": -15.66561, + "y": 266.7697, + "curve": [ 1.1441567, -14.768756, 1.187973, -10.528233, 1.150137, 213.71597, 1.171716, -61.31535 ] + }, + { + "time": 1.2333333, + "x": -6.5328, + "y": -61.33868, + "curve": [ 1.2715176, -3.2195106, 1.3106667, 0.04639988, 1.2905277, -61.36034, 1.296268, -44.80271 ] + }, + { "time": 1.3333334, "y": -45.45778 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.884876, + "curve": [ 0.10369815, 11.816757, 0.1789163, 11.152155 ] + }, + { + "time": 0.2, + "value": 10.077812, + "curve": [ 0.2546602, 7.292541, 0.4045541, -8.148415 ] + }, + { + "time": 0.4333333, + "value": -9.350786, + "curve": [ 0.5083333, -12.484213, 0.5950779, -13.13547 ] + }, + { + "time": 0.6666667, + "value": -12.605598, + "curve": [ 0.7137053, -12.257435, 0.8148956, -5.572529 ] + }, + { + "time": 0.8333333, + "value": -4.081579, + "curve": [ 0.882925, -0.0714054, 1.011111, 10.602404 ] + }, + { + "time": 1.1, + "value": 15.013464, + "curve": [ 1.1777778, 18.87314, 1.2786733, 20.643595 ] + }, + { "time": 1.3333334, "value": 20.730635 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 28.284866, + "curve": [ 0.02212139, 25.120243, 0.18745896, -0.8935051 ] + }, + { + "time": 0.2, + "value": -2.518879, + "curve": [ 0.2570979, -9.918992, 0.3723359, -17.379135 ] + }, + { + "time": 0.4333333, + "value": -17.410477, + "curve": [ 0.5404287, -17.465504, 0.659186, -16.91498 ] + }, + { + "time": 0.7666666, + "value": -12.098708, + "curve": [ 0.9074817, -5.788708, 1.02477, 14.578896 ] + }, + { + "time": 1.1, + "value": 20.57702, + "curve": [ 1.1912643, 27.85358, 1.2833333, 29.665577 ] + }, + { "time": 1.3333334, "value": 29.665577 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -7.141128, + "curve": [ 0.04444444, -17.31849, 0.08888888, -37.67321 ] + }, + { + "time": 0.13333334, + "value": -37.67321, + "curve": [ 0.3111111, -37.67321, 0.520668, -26.72044 ] + }, + { + "time": 0.6666667, + "value": -15.710236, + "curve": [ 0.775613, -7.494261, 0.9111111, 14.924957 ] + }, + { + "time": 1.0333333, + "value": 14.924957, + "curve": [ 1.1333333, 14.924957, 1.2333333, 0.2142334 ] + }, + { "time": 1.3333334, "value": -7.141128 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -115.63992, + "curve": [ 0.06674182, -117.17092, 0.125, -117.14553 ] + }, + { + "time": 0.16666667, + "value": -117.14553, + "curve": [ 0.225, -117.14553, 0.3323854, -108.76366 ] + }, + { + "time": 0.4, + "value": -107.15474, + "curve": [ 0.4798223, -105.25534, 0.6848591, -103.48536 ] + }, + { + "time": 0.7666666, + "value": -101.96748, + "curve": [ 0.8257901, -100.87048, 0.9185745, -92.3025 ] + }, + { + "time": 1, + "value": -92.2841, + "curve": [ 1.1131337, -92.25854, 1.2974604, -114.21733 ] + }, + { "time": 1.3333334, "value": -115.63992 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 12.807907, + "curve": [ 0.06666667, 12.807907, 0.2416681, 67.87932 ] + }, + { + "time": 0.2666667, + "value": 74.10752, + "curve": [ 0.3144626, 86.0155, 0.4544868, 92.22735 ] + }, + { + "time": 0.5666666, + "value": 92.23942, + "curve": [ 0.7529982, 92.25944, 0.9659008, 67.9441 ] + }, + { + "time": 1, + "value": 61.31865, + "curve": [ 1.0389384, 53.75296, 1.2178437, 12.682728 ] + }, + { "time": 1.3333334, "value": 12.807907 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.50333, + "curve": [ 0.04802571, 36.09633, 0.16843162, 20.44992 ] + }, + { + "time": 0.3, + "value": 20.44989, + "curve": [ 0.47593585, 20.449875, 0.5709888, 33.75796 ] + }, + { + "time": 0.6, + "value": 38.67331, + "curve": [ 0.642064, 45.80016, 0.6806553, 57.44073 ] + }, + { + "time": 0.7333333, + "value": 62.90692, + "curve": [ 0.828676, 72.80023, 0.9955254, 77.61066 ] + }, + { + "time": 1.0333333, + "value": 80.3669, + "curve": [ 1.0823636, 83.94128, 1.1476828, 90.60106 ] + }, + { + "time": 1.2, + "value": 90.60106, + "curve": [ 1.2475935, 90.46378, 1.288889, 44.58169 ] + }, + { "time": 1.3333334, "value": 40.50333 } + ] + }, + "torso": { + "rotate": [ + { + "value": -45.56914, + "curve": [ 0.0224493, -44.6064, 0.030192604, -39.06304 ] + }, + { + "time": 0.06666667, + "value": -35.29085, + "curve": [ 0.12008706, -29.766033, 0.2801849, -19.95289 ] + }, + { + "time": 0.4333333, + "value": -19.951965, + "curve": [ 0.6730827, -19.950523, 0.8707536, -22.3845 ] + }, + { + "time": 0.9666666, + "value": -27.08225, + "curve": [ 1.094143, -33.32597, 1.176246, -44.92588 ] + }, + { "time": 1.3333334, "value": -45.56914 } + ], + "translate": [ + { "x": -3.786807, "y": -0.7673931 } + ] + } + }, + "events": [ + { "time": 1.2, "name": "footstep" } + ] + }, + "run": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" } + ] + } + }, + "bones": { + "front-bracer": { + "rotate": [ + { + "value": 7.493057, + "curve": [ 0.03168082, 2.146717, 0.0888624, -2.820983 ] + }, + { + "time": 0.13333334, + "value": -2.8009176, + "curve": [ 0.18554536, -2.777354, 0.22147074, 26.29081 ] + }, + { + "time": 0.23333333, + "value": 32.369, + "curve": [ 0.24664006, 39.18712, 0.2860968, 61.44734 ] + }, + { + "time": 0.3333333, + "value": 61.58177, + "curve": [ 0.3705727, 61.68774, 0.4199115, 55.79158 ] + }, + { + "time": 0.4666667, + "value": 49.67855, + "curve": [ 0.5333333, 40.96217, 0.6434567, 13.388206 ] + }, + { "time": 0.6666667, "value": 7.493057 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -10.95817, + "curve": [ 0.0142863, -13.59649, 0.03571006, -43.26606 ] + }, + { + "time": 0.06666667, + "value": -43.36955, + "curve": [ 0.10190062, -43.48734, 0.18198346, -28.460545 ] + }, + { + "time": 0.2, + "value": -23.04251, + "curve": [ 0.23049556, -13.871703, 0.2638955, 3.857522 ] + }, + { + "time": 0.3333333, + "value": 3.699075, + "curve": [ 0.3797016, 3.6420546, 0.4888889, -21.28619 ] + }, + { + "time": 0.5666666, + "value": -21.28619, + "curve": [ 0.6, -21.28619, 0.6333333, -10.95817 ] + }, + { "time": 0.6666667, "value": -10.95817 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 11.758484, + "curve": [ 0.008156544, 11.758484, 0.02022221, 19.96558 ] + }, + { + "time": 0.03333333, + "value": 20.38487, + "curve": [ 0.04423693, 20.723335, 0.0557601, 17.20728 ] + }, + { + "time": 0.06666667, + "value": 11.963722, + "curve": [ 0.0793307, 6.005581, 0.0888889, -24.55862 ] + }, + { + "time": 0.1, + "value": -25.802433, + "curve": [ 0.14444445, -30.777676, 0.18888888, -30.777676 ] + }, + { + "time": 0.23333333, + "value": -30.777676, + "curve": [ 0.2666667, -30.777676, 0.3, -29.20442 ] + }, + { + "time": 0.3333333, + "value": -24.639263, + "curve": [ 0.3888889, -17.03067, 0.44444445, -0.2713623 ] + }, + { + "time": 0.5, + "value": 5.743561, + "curve": [ 0.5555555, 11.758484, 0.6333333, 11.758484 ] + }, + { "time": 0.6666667, "value": 11.758484 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -66.44398, + "curve": [ 0.011185185, -66.44398, 0.02222222, -65.105 ] + }, + { + "time": 0.03333333, + "value": -58.00462, + "curve": [ 0.04444444, -50.90422, 0.05555556, -28.78206 ] + }, + { + "time": 0.06666667, + "value": -23.84164, + "curve": [ 0.07777777, -18.90122, 0.0888889, -18.90122 ] + }, + { + "time": 0.1, + "value": -18.90122, + "curve": [ 0.14444445, -18.90122, 0.18888888, -66.54582 ] + }, + { + "time": 0.23333333, + "value": -85.80315, + "curve": [ 0.2666667, -100.24614, 0.3, -120.00215 ] + }, + { + "time": 0.3333333, + "value": -120.00215, + "curve": [ 0.3666667, -120.00215, 0.4, -116.76721 ] + }, + { + "time": 0.4333333, + "value": -103.61938, + "curve": [ 0.4555556, -94.85416, 0.4778889, -73.53894 ] + }, + { + "time": 0.5, + "value": -54.26298, + "curve": [ 0.5222778, -34.98701, 0.5444444, -5.076866 ] + }, + { + "time": 0.5666666, + "value": -5.076866, + "curve": [ 0.5888889, -5.076866, 0.6111111, -31.556675 ] + }, + { + "time": 0.6333333, + "value": -45.19381, + "curve": [ 0.6444444, -52.01238, 0.6555555, -66.44398 ] + }, + { "time": 0.6666667, "value": -66.44398 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 49.77412, + "curve": [ 0.007070781, 49.71073, 0.02222222, 41.98567 ] + }, + { + "time": 0.03333333, + "value": 32.2634, + "curve": [ 0.04444444, 22.54112, 0.05555556, 0.10305786 ] + }, + { + "time": 0.06666667, + "value": -8.559517, + "curve": [ 0.07777777, -17.22209, 0.0888889, -19.04588 ] + }, + { + "time": 0.1, + "value": -19.71205, + "curve": [ 0.14444445, -22.37673, 0.18888888, -22.37673 ] + }, + { + "time": 0.23333333, + "value": -22.37673, + "curve": [ 0.2666667, -22.37673, 0.3, 36.56873 ] + }, + { + "time": 0.3333333, + "value": 54.693, + "curve": [ 0.3666667, 72.81727, 0.4, 86.3689 ] + }, + { + "time": 0.4333333, + "value": 86.3689, + "curve": [ 0.4777778, 86.3689, 0.5222222, 46.94118 ] + }, + { + "time": 0.5666666, + "value": 46.94118, + "curve": [ 0.5888889, 46.94118, 0.6516049, 49.3427 ] + }, + { "time": 0.6666667, "value": 49.77412 } + ], + "translate": [ + { + "x": -7.864105, + "y": 10.344667, + "curve": [ 0.03590325, -7.847552, 0.12284817, -6.705404, 0.05555556, 10.344667, 0.1075726, 9.73772 ] + }, + { + "time": 0.16666667, + "x": -5.70233, + "y": 7.98743, + "curve": [ 0.2195182, -4.492474, 0.2954673, -0.7813912, 0.23623653, 5.926863, 0.2795449, 3.223648 ] + }, + { + "time": 0.3333333, + "x": 1.6807823, + "y": 3.19467, + "curve": [ 0.3579407, 3.2808304, 0.448605, 9.985603, 0.3841316, 3.1587524, 0.4489366, 4.982999 ] + }, + { + "time": 0.5, + "x": 9.994194, + "y": 6.760218, + "curve": [ 0.5555555, 10.00348, 0.6111111, -7.864105, 0.5555555, 8.693786, 0.6111111, 10.344667 ] + }, + { "time": 0.6666667, "x": -7.864105, "y": 10.344667 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": 324.2116, + "curve": [ 0.05055879, 363.1453, 0.14481726, 449.6619 ] + }, + { + "time": 0.23333333, + "value": 449.6619, + "curve": [ 0.2797953, 450.0657, 0.3235971, 419.5053 ] + }, + { + "time": 0.3333333, + "value": 411.1141, + "curve": [ 0.3576108, 390.1904, 0.4447371, 293.1321 ] + }, + { + "time": 0.5666666, + "value": 292.2291, + "curve": [ 0.5989908, 291.9897, 0.6333333, 298.5427 ] + }, + { "time": 0.6666667, "value": 324.2116 } + ] + }, + "gun": { + "rotate": [ + { + "value": 18.245386, + "curve": [ 0.03330681, 19.237165, 0.08747823, 20.251215 ] + }, + { + "time": 0.13333334, + "value": 20.186804, + "curve": [ 0.168223, 20.32252, 0.25445935, -8.823136 ] + }, + { + "time": 0.2666667, + "value": -11.87723, + "curve": [ 0.2907614, -17.905375, 0.3436026, -24.105413 ] + }, + { + "time": 0.4, + "value": -23.880844, + "curve": [ 0.4478289, -23.690395, 0.5327503, -15.46561 ] + }, + { "time": 0.5666666, "value": -8.685678 }, + { "time": 0.6666667, "value": 18.245386 } + ] + }, + "gun-tip": { + "rotate": [ + { "time": 0.4333333, "value": 12.929344 } + ] + }, + "head": { + "rotate": [ + { + "value": 8.926323, + "curve": [ 0.03333333, 7.961286, 0.06497238, 6.029284 ] + }, + { + "time": 0.1, + "value": 6.031214, + "curve": [ 0.14605942, 6.033665, 0.18888888, 10.778542 ] + }, + { + "time": 0.23333333, + "value": 10.778542, + "curve": [ 0.2666667, 10.778542, 0.30857885, 9.9427 ] + }, + { + "time": 0.3333333, + "value": 8.927942, + "curve": [ 0.3576169, 7.932484, 0.3879337, 6.096312 ] + }, + { + "time": 0.4333333, + "value": 6.096905, + "curve": [ 0.4856776, 6.097572, 0.5444444, 10.762506 ] + }, + { + "time": 0.6, + "value": 10.762506, + "curve": [ 0.6222222, 10.762506, 0.651986, 9.578316 ] + }, + { "time": 0.6666667, "value": 8.926323 } + ], + "scale": [ + { + "x": 0.9919838, + "y": 1.0097017, + "curve": [ 0.03634993, 0.9909303, 0.06835206, 0.9908737, 0.01364684, 1.0131445, 0.08333333, 1.0259862 ] + }, + { + "time": 0.1, + "x": 0.990646, + "y": 1.0259862, + "curve": [ 0.12777777, 0.990646, 0.2054961, 1.037544, 0.12777777, 1.0259862, 0.19723263, 0.9822814 ] + }, + { + "time": 0.23333333, + "x": 1.037546, + "y": 0.9823953, + "curve": [ 0.2718352, 1.0375488, 0.3052763, 1.007659, 0.26181215, 0.9824851, 0.310745, 0.9947102 ] + }, + { + "time": 0.3333333, + "curve": [ 0.3506023, 0.995286, 0.4166667, 0.9812972, 0.358576, 1.0059115, 0.4166667, 1.0263615 ] + }, + { + "time": 0.4333333, + "x": 0.9812972, + "y": 1.0263615, + "curve": [ 0.4666667, 0.9812972, 0.5333333, 1.0373653, 0.4666667, 1.0263615, 0.5333333, 0.9822722 ] + }, + { + "time": 0.5666666, + "x": 1.0373653, + "y": 0.9822722, + "curve": [ 0.5916666, 1.0373653, 0.6355573, 0.992962, 0.5916666, 0.9822722, 0.6400051, 1.003939 ] + }, + { "time": 0.6666667, "x": 0.9919838, "y": 1.009641 } + ] + }, + "hip": { + "translate": [ + { + "x": 0.6303943, + "y": -34.1915, + "curve": [ 0.04166667, 0.3891938, 0.1176159, 7.619495, 0.04166667, -33.83137, 0.08361745, 20.03601 ] + }, + { + "time": 0.16666667, + "x": 7.607398, + "y": 20.35568, + "curve": [ 0.1942442, 7.600595, 0.21030916, 5.061855, 0.20362726, 20.65172, 0.21742456, -8.689377 ] + }, + { + "time": 0.23333333, + "x": 1.6768702, + "y": -18.475845, + "curve": [ 0.27868885, -4.991243, 0.2966124, -5.63762, 0.2538157, -31.075775, 0.2916608, -34.54651 ] + }, + { + "time": 0.3333333, + "x": -5.755511, + "y": -35.00304, + "curve": [ 0.3786888, -5.901124, 0.4511913, 6.801747, 0.3841243, -35.55946, 0.4158855, 17.59712 ] + }, + { + "time": 0.5, + "x": 6.613358, + "y": 17.013046, + "curve": [ 0.5363964, 6.472878, 0.5448888, 3.56219, 0.5326953, 16.74632, 0.54835, -8.713715 ] + }, + { + "time": 0.5666666, + "x": 0.3517065, + "y": -18.81471, + "curve": [ 0.5966279, -4.065155, 0.6333333, 0.8233548, 0.5843817, -28.583954, 0.6333333, -34.4796 ] + }, + { "time": 0.6666667, "x": 0.6303943, "y": -34.1915 } + ] + }, + "neck": { + "rotate": [ + { + "value": 10.22865, + "curve": [ 0.02355112, 9.74595, 0.075, 9.74365 ] + }, + { + "time": 0.1, + "value": 9.74365, + "curve": [ 0.125, 9.74365, 0.20833333, 13.35947 ] + }, + { + "time": 0.23333333, + "value": 13.35947, + "curve": [ 0.2583333, 13.35947, 0.3, 10.87806 ] + }, + { + "time": 0.3333333, + "value": 10.298557, + "curve": [ 0.3666667, 9.719053, 0.4083333, 9.719053 ] + }, + { + "time": 0.4333333, + "value": 9.719053, + "curve": [ 0.4583333, 9.719053, 0.5416667, 13.35947 ] + }, + { + "time": 0.5666666, + "value": 13.35947, + "curve": [ 0.5916666, 13.35947, 0.6333333, 10.91184 ] + }, + { "time": 0.6666667, "value": 10.22865 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": 17.026924 }, + { + "time": 0.23333333, + "value": -13.074486, + "curve": [ 0.2520901, -16.075047, 0.2973188, -19.369314 ] + }, + { + "time": 0.3333333, + "value": -19.37952, + "curve": [ 0.4346901, -19.408234, 0.5219483, 38.96215 ] + }, + { + "time": 0.5666666, + "value": 38.86711, + "curve": [ 0.6189629, 38.75598, 0.6253778, 24.635723 ] + }, + { "time": 0.6666667, "value": 17.026924 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -27.81013, + "curve": [ 0.0782963, -27.81013, 0.15555555, 17.704796 ] + }, + { + "time": 0.23333333, + "value": 17.704796, + "curve": [ 0.2555555, 17.704796, 0.2777778, 12.797485 ] + }, + { + "time": 0.3, + "value": 12.797485, + "curve": [ 0.3111111, 12.797485, 0.3222222, 17.92608 ] + }, + { + "time": 0.3333333, + "value": 20.49037, + "curve": [ 0.34448, 20.49037, 0.3556049, 36.90861 ] + }, + { + "time": 0.3666667, + "value": 33.48662, + "curve": [ 0.3778437, 30.03595, 0.3889681, 28.84283 ] + }, + { + "time": 0.4, + "value": 19.93106, + "curve": [ 0.4112096, 10.89967, 0.4223245, -5.84376 ] + }, + { + "time": 0.4333333, + "value": -8.17887, + "curve": [ 0.4782578, -17.388214, 0.5226768, 4.881155 ] + }, + { + "time": 0.5666666, + "value": 2.2075195, + "curve": [ 0.6002236, 0.1905651, 0.6334452, -27.81013 ] + }, + { "time": 0.6666667, "value": -27.81013 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -99.90867, + "curve": [ 0.04761905, -99.45025, 0.06666667, -87.25387 ] + }, + { + "time": 0.1, + "value": -72.40804, + "curve": [ 0.14444445, -52.6136, 0.18888888, 4.01216 ] + }, + { + "time": 0.23333333, + "value": 4.01216, + "curve": [ 0.2555555, 4.01216, 0.2777778, -32.39618 ] + }, + { + "time": 0.3, + "value": -46.26676, + "curve": [ 0.3111111, -53.20205, 0.3222222, -58.40546 ] + }, + { + "time": 0.3333333, + "value": -58.40546, + "curve": [ 0.3666667, -58.40546, 0.4, -2.86392 ] + }, + { + "time": 0.4333333, + "value": -2.86392, + "curve": [ 0.4777778, -2.86392, 0.5222222, -61.56073 ] + }, + { + "time": 0.5666666, + "value": -80.04544, + "curve": [ 0.6, -93.90897, 0.631746, -99.8673 ] + }, + { "time": 0.6666667, "value": -99.90867 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 17.72141, + "curve": [ 0.025362134, 28.513855, 0.06666667, 54.37655 ] + }, + { + "time": 0.1, + "value": 54.37655, + "curve": [ 0.14444445, 54.37655, 0.1888889, 19.309536 ] + }, + { + "time": 0.23333333, + "value": 19.30953, + "curve": [ 0.2539683, 19.30953, 0.2777778, 32.87431 ] + }, + { + "time": 0.3, + "value": 32.87431, + "curve": [ 0.3111111, 32.87431, 0.3222222, 32.87431 ] + }, + { + "time": 0.3333333, + "value": 28.234955, + "curve": [ 0.3444444, 23.595596, 0.3555556, 4.076466 ] + }, + { + "time": 0.3666667, + "value": -3.5993805, + "curve": [ 0.3888889, -18.951075, 0.4111111, -38.4275 ] + }, + { + "time": 0.4333333, + "value": -40.84766, + "curve": [ 0.4777778, -45.688, 0.5222222, -45.688 ] + }, + { + "time": 0.5666666, + "value": -45.688, + "curve": [ 0.6, -45.688, 0.6333333, -7.236103 ] + }, + { "time": 0.6666667, "value": 17.72141 } + ], + "translate": [ + { + "x": -13.5929, + "y": 3.213442, + "curve": [ 0.01329846, -12.846372, 0.18333334, -8.545134, 0.02999618, 4.054101, 0.18333334, 6.169795 ] + }, + { + "time": 0.23333333, + "x": -8.545134, + "y": 6.169795, + "curve": [ 0.3083333, -8.545134, 0.4916667, -19.75406, 0.3083333, 6.169795, 0.4916667, 0.6147775 ] + }, + { + "time": 0.5666666, + "x": -19.75406, + "y": 0.6147775, + "curve": [ 0.5916666, -19.75406, 0.6333333, -15.464117, 0.5916666, 0.6147775, 0.6333333, 2.279258 ] + }, + { "time": 0.6666667, "x": -13.5929, "y": 3.213442 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 35.31964, + "curve": [ 0.028292393, 18.55806, 0.1277068, -79.86003 ] + }, + { + "time": 0.23333333, + "value": -79.86928, + "curve": [ 0.380056, -79.88212, 0.4030929, 63.25032 ] + }, + { + "time": 0.5666666, + "value": 64.13361, + "curve": [ 0.6073362, 64.35324, 0.6333333, 55.0677 ] + }, + { "time": 0.6666667, "value": 35.31966 } + ], + "translate": [ + { + "x": -4.580894, + "y": 0.933937, + "curve": [ 0.04393777, -5.373317, 0.16938667, -5.475494, 0.04393777, 2.631696, 0.16938667, 2.850609 ] + }, + { + "time": 0.23333333, + "x": -5.475494, + "y": 2.850609, + "curve": [ 0.34626475, -5.475494, 0.4753447, -2.684357, 0.34626475, 2.850609, 0.4753447, -3.129387 ] + }, + { + "time": 0.5666666, + "x": -2.684357, + "y": -3.129387, + "curve": [ 0.6106853, -2.684357, 0.6333333, -3.979724, 0.6106853, -3.129387, 0.6333333, -0.35406625 ] + }, + { "time": 0.6666667, "x": -4.580894, "y": 0.933937 } + ] + }, + "torso": { + "rotate": [ + { + "value": -38.65314, + "curve": [ 0.021855975, -39.16014, 0.06666667, -41.39799 ] + }, + { + "time": 0.1, + "value": -41.39799, + "curve": [ 0.15555556, -41.39799, 0.2111111, -37.60319 ] + }, + { + "time": 0.2666667, + "value": -37.60319, + "curve": [ 0.2888889, -37.60319, 0.31524625, -38.2 ] + }, + { + "time": 0.3333333, + "value": -38.63306, + "curve": [ 0.3687939, -39.48209, 0.434, -41.38488 ] + }, + { + "time": 0.4666667, + "value": -41.38785, + "curve": [ 0.5115555, -41.39176, 0.5555555, -37.68753 ] + }, + { + "time": 0.6, + "value": -37.68753, + "curve": [ 0.6222222, -37.68753, 0.6518018, -38.3005 ] + }, + { "time": 0.6666667, "value": -38.65314 } + ] + } + }, + "drawOrder": [ + { + "offsets": [ + { "slot": "head", "offset": -2 } + ] + } + ], + "events": [ + { "time": 0.2666667, "name": "footstep" }, + { "time": 0.6, "name": "footstep" } + ] + }, + "shoot": { + "slots": { + "muzzle": { + "rgba": [ + { "time": 0.3666667, "color": "ffffff00" } + ], + "attachment": [ + { "time": 0.13333334, "name": "muzzle01" }, + { "time": 0.2, "name": "muzzle02" }, + { "time": 0.2666667, "name": "muzzle03" }, + { "time": 0.3333333, "name": "muzzle04" }, + { "time": 0.3666667 } + ] + } + }, + "bones": { + "gun": { + "rotate": [ + { "value": 1.9090242, "curve": "stepped" }, + { + "time": 0.1, + "value": 1.9090242, + "curve": [ 0.1129129, 4.949258, 0.12222222, 6.556416 ] + }, + { + "time": 0.13333334, + "value": 6.556416, + "curve": [ 0.16666667, 6.556416, 0.2, -0.9698362 ] + }, + { + "time": 0.23333333, + "value": -0.9698362, + "curve": [ 0.2888889, -0.9698362, 0.3444444, 0.9494039 ] + }, + { "time": 0.4, "value": 1.9090242 } + ], + "translate": [ + { "x": 7.95324, "y": 5.8488, "curve": "stepped" }, + { + "time": 0.1, + "x": 7.95324, + "y": 5.8488, + "curve": [ 0.16666667, 7.95324, 0.20357153, -9.302124, 0.16666667, 5.8488, 0.20357153, -1.4109497 ] + }, + { + "time": 0.3, + "x": -9.302124, + "y": -1.4109497, + "curve": [ 0.3333333, -9.302124, 0.3666667, 7.95324, 0.3333333, -1.4109497, 0.3666667, 5.8488 ] + }, + { "time": 0.4, "x": 7.95324, "y": 5.8488 } + ] + }, + "gun-tip": { + "translate": [ + { "time": 0.13333334 }, + { "time": 0.23333333, "x": 32.30524, "y": 2.941681 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": -30.47487 } + ], + "translate": [ + { + "time": 0.1, + "curve": [ 0.15585586, -4.393783, 0.20357153, -5.998596, 0.16666667, -3.379834, 0.20357153, -3.7177734 ] + }, + { "time": 0.3, "x": -5.998596, "y": -3.7177734 }, + { "time": 0.4 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "value": 62.30537 } + ], + "translate": [ + { + "time": 0.1, + "curve": [ 0.16666667, 0, 0.20357153, 2.811493, 0.1603571, 11.739444, 0.23017855, 11.69847 ] + }, + { "time": 0.3, "x": 2.811493, "y": 11.52748 }, + { "time": 0.4 } + ] + } + } + }, + "walk": { + "bones": { + "front-bracer": { + "rotate": [ + { + "value": 13.566517, + "curve": [ 0.021665983, 9.70724, 0.1470159, -15.397473 ] + }, + { + "time": 0.3666667, + "value": -15.302825, + "curve": [ 0.4572524, -15.277073, 0.6349344, 30.8047 ] + }, + { + "time": 0.8, + "value": 30.91521, + "curve": [ 0.8937238, 30.822296, 0.9800564, 18.353865 ] + }, + { "time": 1, "value": 13.566517 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -28.72383, + "curve": [ 0.02368659, -31.7421, 0.1760204, -43.39537 ] + }, + { + "time": 0.3666667, + "value": -43.59644, + "curve": [ 0.4030356, -43.64886, 0.4704281, -40.14865 ] + }, + { + "time": 0.5, + "value": -35.63085, + "curve": [ 0.5466347, -28.591816, 0.624065, -4.573129 ] + }, + { + "time": 0.7333333, + "value": -4.592627, + "curve": [ 0.8906477, -4.620701, 0.9538756, -24.27828 ] + }, + { "time": 1, "value": -28.48091 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 2.729469, + "curve": [ 0.01282918, 4.280014, 0.01937586, 5.266845 ] + }, + { + "time": 0.03333333, + "value": 5.152214, + "curve": [ 0.04530869, 5.053871, 0.0631222, -4.106606 ] + }, + { + "time": 0.06666667, + "value": -6.669121, + "curve": [ 0.1110445, -6.723576, 0.1476413, 3.7818146 ] + }, + { "time": 0.16666667, "value": 4.66513 }, + { "time": 0.2666667, "value": 7.05716 }, + { "time": 0.3333333, "value": 8.972183 }, + { "time": 0.4, "value": 11.154686 }, + { + "time": 0.5333333, + "value": 21.621986, + "curve": [ 0.5722665, 21.621986, 0.5872717, 17.194595 ] + }, + { + "time": 0.6, + "value": 13.765045, + "curve": [ 0.638737, 3.327629, 0.71253, -20.850117 ] + }, + { + "time": 0.7333333, + "value": -27.29794, + "curve": [ 0.756695, -34.53865, 0.7661038, -37.12764 ] + }, + { + "time": 0.8, + "value": -38.00618, + "curve": [ 0.8277124, -38.72444, 0.9760505, -2.1584854 ] + }, + { "time": 1, "value": 2.729469 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -6.793827, + "curve": [ 0.028333334, -6.793827, 0.08721972, -49.3215 ] + }, + { + "time": 0.1, + "value": -51.41688, + "curve": [ 0.10916332, -52.91925, 0.13713828, -55.36942 ] + }, + { + "time": 0.16666667, + "value": -55.355, + "curve": [ 0.18763776, -55.34476, 0.23751643, -44.96193 ] + }, + { + "time": 0.2666667, + "value": -40.54677, + "curve": [ 0.28395575, -37.92812, 0.3647001, -23.139524 ] + }, + { + "time": 0.4333333, + "value": -22.847954, + "curve": [ 0.5236502, -22.4644, 0.5845393, -48.23822 ] + }, + { + "time": 0.6, + "value": -54.49775, + "curve": [ 0.6176404, -61.63981, 0.7141188, -97.50536 ] + }, + { + "time": 0.7333333, + "value": -102.64905, + "curve": [ 0.748986, -106.83922, 0.7683412, -109.78356 ] + }, + { + "time": 0.8, + "value": -109.78032, + "curve": [ 0.8175621, -109.77852, 0.8590287, -94.43874 ] + }, + { + "time": 0.8666667, + "value": -87.74427, + "curve": [ 0.8737715, -81.51704, 0.9687337, -6.793827 ] + }, + { "time": 1, "value": -6.793827 } + ], + "scale": [ + {}, + { "time": 0.03333333, "x": 0.9834621 }, + { "time": 0.1, "x": 0.9670942, "y": 0.9810548 }, + { "time": 0.4333333 }, + { "time": 0.5333333, "x": 0.9583819, "y": 0.951171 }, + { "time": 0.6333333 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 41.4104, + "curve": [ 0.03318726, 41.51518, 0.075, 57.36004 ] + }, + { + "time": 0.1, + "value": 57.36004, + "curve": [ 0.14166667, 57.36004, 0.24909316, 30.798454 ] + }, + { + "time": 0.2666667, + "value": 26.810616, + "curve": [ 0.3139528, 16.080307, 0.377779, 5.395645 ] + }, + { + "time": 0.4, + "value": 2.747543, + "curve": [ 0.4545327, -3.751221, 0.5396798, -12.388138 ] + }, + { + "time": 0.6, + "value": -12.388138, + "curve": [ 0.6333335, -12.388138, 0.721709, 21.06674 ] + }, + { + "time": 0.7333333, + "value": 25.70877, + "curve": [ 0.7511036, 32.80505, 0.8235406, 63.51709 ] + }, + { + "time": 0.8666667, + "value": 63.79029, + "curve": [ 0.9134613, 64.08673, 0.9477198, 41.49128 ] + }, + { "time": 1, "value": 41.4104 } + ], + "translate": [ + { + "x": 17.154694, + "y": -0.0851593, + "curve": [ 0.17816044, 17.1408, 0.2949699, -4.258095, 0.008833333, -0.0851593, 0.475, 0.021209717 ] + }, + { + "time": 0.5, + "x": -4.263954, + "y": 0.021209717, + "curve": [ 0.7050302, -4.26981, 0.875, 17.16444, 0.525, 0.021209717, 0.875, -0.0851593 ] + }, + { "time": 1, "x": 17.154694, "y": -0.0851593 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -14.272247, + "curve": [ 0.0214478, -18.07887, 0.05789917, -19.404175 ] + }, + { + "time": 0.1, + "value": -19.404175, + "curve": [ 0.2377866, -19.68686, 0.33747205, 7.779631 ] + }, + { + "time": 0.3666667, + "value": 16.196716, + "curve": [ 0.39864385, 25.41603, 0.4965658, 60.19389 ] + }, + { + "time": 0.6, + "value": 60.26086, + "curve": [ 0.7185024, 60.12991, 0.8452276, 27.61441 ] + }, + { + "time": 0.8666667, + "value": 22.449387, + "curve": [ 0.8918752, 16.37623, 0.9666666, -8.356144 ] + }, + { "time": 1, "value": -14.272247 } + ] + }, + "gun": { + "rotate": [ + { + "value": -14.673275, + "curve": [ 0.08551843, -14.673275, 0.20198414, 8.30991 ] + }, + { + "time": 0.23333333, + "value": 12.136024, + "curve": [ 0.2789693, 17.70582, 0.3914901, 25.794325 ] + }, + { + "time": 0.5, + "value": 25.77012, + "curve": [ 0.6313128, 25.740833, 0.6943456, 4.530927 ] + }, + { + "time": 0.7333333, + "value": -0.6513629, + "curve": [ 0.7676219, -5.209029, 0.9023453, -14.40159 ] + }, + { "time": 1, "value": -14.673275 } + ] + }, + "gun-tip": { + "rotate": [ + { "time": 0.23333333, "value": 0.1086235 } + ] + }, + "head": { + "rotate": [ + { + "value": -12.234505, + "curve": [ 0.06143671, -12.234504, 0.19128084, -7.449013 ] + }, + { + "time": 0.2666667, + "value": -7.434601, + "curve": [ 0.3406891, -7.42045, 0.4206042, -12.234505 ] + }, + { + "time": 0.5, + "value": -12.234505, + "curve": [ 0.5671493, -12.26333, 0.6940113, -7.456505 ] + }, + { + "time": 0.7666666, + "value": -7.472237, + "curve": [ 0.8529694, -7.490928, 0.942855, -12.234505 ] + }, + { "time": 1, "value": -12.234505 } + ], + "scale": [ + { + "curve": [ 0.03916667, 1, 0.08446944, 0.9912923, 0.03916667, 1, 0.08446944, 1.0190994 ] + }, + { + "time": 0.13333334, + "x": 0.9912923, + "y": 1.0190994, + "curve": [ 0.20465556, 0.9912923, 0.3176702, 1.0191765, 0.20465556, 1.0190994, 0.3367928, 0.9916709 ] + }, + { + "time": 0.4, + "x": 1.0190022, + "y": 0.9915339, + "curve": [ 0.4560374, 1.018884, 0.4936612, 1.001296, 0.483147, 0.9913536, 0.49272755, 0.9987176 ] + }, + { + "time": 0.5, + "curve": [ 0.5076706, 0.9984317, 0.5844694, 0.9912923, 0.5099203, 1.001749, 0.5844694, 1.0190994 ] + }, + { + "time": 0.6333333, + "x": 0.9912923, + "y": 1.0190994, + "curve": [ 0.7046556, 0.9912923, 0.8176701, 1.0191765, 0.7046556, 1.0190994, 0.8367927, 0.9916709 ] + }, + { + "time": 0.9, + "x": 1.0190022, + "y": 0.9915339, + "curve": [ 0.9560374, 1.018884, 0.9553667, 1, 0.9831469, 0.9913536, 0.9553667, 1 ] + }, + { "time": 1 } + ] + }, + "hip": { + "rotate": [ + { "value": 0.9422989 } + ], + "translate": [ + { + "x": -2.8556595, + "y": -13.858932, + "curve": [ 0.025, -2.84362, 0.0672245, -2.815521, 0.02826383, -19.13565, 0.05413223, -31.191 ] + }, + { + "time": 0.1, + "x": -2.609104, + "y": -31.360916, + "curve": [ 0.14349824, -2.335156, 0.20189807, -1.788381, 0.1520444, -31.157455, 0.21322107, -14.811488 ] + }, + { + "time": 0.2666667, + "x": -1.2142082, + "y": -7.122375, + "curve": [ 0.3076929, -0.8572894, 0.3451087, -0.5055015, 0.3060169, -1.6301517, 0.3410871, 3.152566 ] + }, + { + "time": 0.3666667, + "x": -0.3309364, + "y": 3.1525726, + "curve": [ 0.4099607, 0.01963806, 0.458473, 0.25751495, 0.4266791, 3.304947, 0.48069695, -6.751709 ] + }, + { + "time": 0.5, + "x": 0.2593346, + "y": -10.585007, + "curve": [ 0.553076, 0.2616577, 0.5589796, 0.1951599, 0.5192444, -14.406647, 0.5481416, -31.737053 ] + }, + { + "time": 0.6, + "x": -0.16674805, + "y": -31.5625, + "curve": [ 0.6321317, -0.450234, 0.6828745, -0.9390647, 0.6460296, -31.407566, 0.6876432, -17.4635 ] + }, + { + "time": 0.7333333, + "x": -1.4046334, + "y": -8.623154, + "curve": [ 0.7832278, -1.8519446, 0.8328046, -2.278311, 0.7695741, -1.611121, 0.8313638, 3.51029 ] + }, + { + "time": 0.8666667, + "x": -2.45504, + "y": 3.4846344, + "curve": [ 0.900976, -2.634102, 0.9666666, -2.871712, 0.9130171, 3.4509735, 0.9666666, -7.635769 ] + }, + { "time": 1, "x": -2.8556595, "y": -13.858932 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.7811, + "curve": [ 0.02514851, 17.929705, 0.07101186, 18.4591 ] + }, + { + "time": 0.13333334, + "value": 18.457026, + "curve": [ 0.1866547, 18.455263, 0.2853263, 17.33772 ] + }, + { + "time": 0.3666667, + "value": 17.33654, + "curve": [ 0.4048635, 17.336, 0.4699174, 17.59838 ] + }, + { + "time": 0.5, + "value": 17.789774, + "curve": [ 0.5176707, 17.9022, 0.5816134, 18.46532 ] + }, + { + "time": 0.6333333, + "value": 18.46029, + "curve": [ 0.7092406, 18.45292, 0.8148, 17.319715 ] + }, + { + "time": 0.8666667, + "value": 17.322073, + "curve": [ 0.9082929, 17.323965, 0.9711425, 17.56992 ] + }, + { "time": 1, "value": 17.7811 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.059132, + "curve": [ 0.04404857, 11.161348, 0.06296488, 11.485394 ] + }, + { + "time": 0.1, + "value": 11.48998, + "curve": [ 0.21508875, 11.49362, 0.3358774, 2.9205174 ] + }, + { + "time": 0.3666667, + "value": 0.8411312, + "curve": [ 0.4164524, -2.521204, 0.4980461, -10.835702 ] + }, + { + "time": 0.6, + "value": -10.82903, + "curve": [ 0.7620489, -10.713412, 0.8446016, -3.045681 ] + }, + { + "time": 0.8666667, + "value": -1.341797, + "curve": [ 0.9168805, 2.535763, 0.977475, 8.81012 ] + }, + { "time": 1, "value": 10.059132 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": 26.22378 }, + { + "time": 0.03333333, + "value": 28.93897, + "curve": [ 0.05, 28.93897, 0.08065994, 17.618355 ] + }, + { + "time": 0.1, + "value": 12.678444, + "curve": [ 0.12127, 7.24559, 0.2386952, -22.96467 ] + }, + { + "time": 0.2666667, + "value": -26.3071, + "curve": [ 0.2985902, -30.12179, 0.36421835, -35.51531 ] + }, + { + "time": 0.4, + "value": -35.37854, + "curve": [ 0.4181065, -35.30932, 0.4849723, 1.136505 ] + }, + { + "time": 0.5, + "value": 6.16732, + "curve": [ 0.5027245, 7.079414, 0.5185979, 11.268929 ] + }, + { + "time": 0.5333333, + "value": 11.150063, + "curve": [ 0.544865, 11.057053, 0.551859, 11.267353 ] + }, + { "time": 0.5666666, "value": 3.6860504 }, + { "time": 0.6, "value": 3.546654 }, + { "time": 0.7, "value": 10.769646 }, + { "time": 1, "value": 26.22378 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": 6.84202, + "curve": [ 0.025, 6.84202, 0.09287377, -24.565344 ] + }, + { + "time": 0.1, + "value": -28.076286, + "curve": [ 0.12120705, -38.52457, 0.2044225, -92.35046 ] + }, + { + "time": 0.2666667, + "value": -91.67556, + "curve": [ 0.3094006, -91.21856, 0.378913, -77.6213 ] + }, + { + "time": 0.4, + "value": -68.9121, + "curve": [ 0.4298476, -56.58465, 0.4743385, 2.284277 ] + }, + { + "time": 0.5, + "value": 2.634779, + "curve": [ 0.5375747, 3.147999, 0.567422, -35.4275 ] + }, + { + "time": 0.6, + "value": -35.18227, + "curve": [ 0.634055, -34.93403, 0.665215, -34.17461 ] + }, + { + "time": 0.7, + "value": -30.63782, + "curve": [ 0.7181486, -28.79255, 0.8570787, -8.344112 ] + }, + { + "time": 0.8666667, + "value": -6.834051, + "curve": [ 0.9148397, 0.7530212, 0.9666666, 6.84202 ] + }, + { "time": 1, "value": 6.84202 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": -40.72435, + "curve": [ 0.026275603, -42.95508, 0.075, -42.9971 ] + }, + { + "time": 0.1, + "value": -42.9971, + "curve": [ 0.14166667, -42.9971, 0.23880793, 8.23489 ] + }, + { + "time": 0.2666667, + "value": 18.9876, + "curve": [ 0.2839028, 25.640297, 0.3666667, 38.7167 ] + }, + { + "time": 0.4, + "value": 38.7167, + "curve": [ 0.425, 38.7167, 0.475, 18.69822 ] + }, + { + "time": 0.5, + "value": 18.69822, + "curve": [ 0.525, 18.69822, 0.575, 31.727283 ] + }, + { + "time": 0.6, + "value": 31.727283, + "curve": [ 0.6333333, 31.727283, 0.7187072, 15.196022 ] + }, + { + "time": 0.7333333, + "value": 11.207256, + "curve": [ 0.7666666, 2.11668, 0.8510178, -15.28556 ] + }, + { + "time": 0.8666667, + "value": -18.460236, + "curve": [ 0.9053861, -26.315323, 0.9506328, -35.33224 ] + }, + { "time": 1, "value": -40.72435 } + ], + "translate": [ + { + "x": -17.706324, + "y": -4.631317, + "curve": [ 0.02781926, -19.312107, 0.04017545, -20.22317, 0.02684741, -4.631317, 0.03616554, 1.7059302 ] + }, + { + "time": 0.06666667, + "x": -20.7212, + "y": 1.5961218, + "curve": [ 0.08156063, -21.00121, 0.0865388, -20.92668, 0.08245562, 1.5392787, 0.09143005, 0.2920971 ] + }, + { + "time": 0.1, + "x": -20.94829, + "y": 0.06439924, + "curve": [ 0.1620024, -21.04781, 0.4, 7.791963, 0.19384554, -2.429021, 0.40004575, -1.8982906 ] + }, + { + "time": 0.5, + "x": 7.791963, + "y": -1.9355936, + "curve": [ 0.5186916, 7.775457, 0.5415693, 7.33385, 0.51692, -1.941908, 0.54024, 5.54656 ] + }, + { + "time": 0.5666666, + "x": 6.447131, + "y": 5.396249, + "curve": [ 0.58735, 5.737756, 0.72131, -0.9529097, 0.5873305, 5.284654, 0.7324497, -3.7436066 ] + }, + { + "time": 0.7666666, + "x": -3.606809, + "y": -4.142118, + "curve": [ 0.8550767, -8.758493, 0.94225, -14.37288, 0.813618, -4.688942, 0.9438541, -4.631317 ] + }, + { "time": 1, "x": -17.706324, "y": -4.631317 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 28.27774, + "curve": [ 0.03390831, 30.940815, 0.06758396, 32.04713 ] + }, + { + "time": 0.1, + "value": 31.88103, + "curve": [ 0.1942905, 31.013386, 0.3364573, -0.11212158 ] + }, + { + "time": 0.3666667, + "value": -7.11055, + "curve": [ 0.4211193, -19.725266, 0.5301549, -46.211 ] + }, + { + "time": 0.6, + "value": -45.74681, + "curve": [ 0.7075172, -45.03224, 0.8438387, -13.561066 ] + }, + { + "time": 0.8666667, + "value": -6.483352, + "curve": [ 0.9088265, 6.58815, 0.9575854, 24.209595 ] + }, + { "time": 1, "value": 28.27774 } + ] + }, + "torso": { + "rotate": [ + { + "value": -20.71889, + "curve": [ 0.01313806, -20.488815, 0.07101186, -19.11654 ] + }, + { + "time": 0.13333334, + "value": -19.118614, + "curve": [ 0.1866547, -19.120377, 0.2853263, -22.22281 ] + }, + { + "time": 0.3666667, + "value": -22.22399, + "curve": [ 0.4048635, -22.22453, 0.4907901, -20.91794 ] + }, + { + "time": 0.5, + "value": -20.71021, + "curve": [ 0.5102433, -20.47918, 0.5816134, -19.056824 ] + }, + { + "time": 0.6333333, + "value": -19.06185, + "curve": [ 0.7092406, -19.06922, 0.8148, -22.21988 ] + }, + { + "time": 0.8666667, + "value": -22.21752, + "curve": [ 0.9082929, -22.21563, 0.9811512, -21.099266 ] + }, + { "time": 1, "value": -20.71889 } + ] + } + }, + "events": [ + { "name": "footstep" }, + { "time": 0.5333333, "name": "footstep" } + ] + } +} +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-ess.skel b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-ess.skel new file mode 100644 index 0000000..2438f67 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-ess.skel differ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-pma.atlas b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-pma.atlas new file mode 100644 index 0000000..c421589 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-pma.atlas @@ -0,0 +1,85 @@ +spineboy-pma.png + size: 1024, 256 + filter: Linear, Linear + pma: true + scale: 0.5 +crosshair + bounds: 186, 17, 45, 45 +eye-indifferent + bounds: 137, 17, 47, 45 +eye-surprised + bounds: 623, 45, 47, 45 +front-bracer + bounds: 613, 3, 29, 40 +front-fist-closed + bounds: 278, 2, 38, 41 +front-fist-open + bounds: 233, 18, 43, 44 +front-foot + bounds: 72, 39, 63, 35 +front-shin + bounds: 952, 41, 41, 92 +front-thigh + bounds: 995, 120, 23, 56 +front-upper-arm + bounds: 995, 69, 23, 49 +goggles + bounds: 167, 64, 131, 83 +gun + bounds: 300, 45, 105, 102 +head + bounds: 29, 76, 136, 149 +hoverboard-board + bounds: 167, 149, 246, 76 +hoverboard-thruster + bounds: 674, 8, 30, 32 +hoverglow-small + bounds: 813, 60, 137, 38 +mouth-grind + bounds: 416, 13, 47, 30 +mouth-oooo + bounds: 367, 13, 47, 30 +mouth-smile + bounds: 318, 13, 47, 30 +muzzle-glow + bounds: 706, 15, 25, 25 +muzzle-ring + bounds: 2, 120, 25, 105 +muzzle01 + bounds: 554, 50, 67, 40 +muzzle02 + bounds: 484, 48, 68, 42 +muzzle03 + bounds: 685, 42, 83, 53 +muzzle04 + bounds: 407, 45, 75, 45 +muzzle05 + bounds: 2, 36, 68, 38 +neck + bounds: 2, 97, 18, 21 +portal-bg + bounds: 550, 92, 133, 133 +portal-flare1 + bounds: 484, 16, 56, 30 +portal-flare2 + bounds: 810, 27, 57, 31 +portal-flare3 + bounds: 869, 28, 58, 30 +portal-shade + bounds: 415, 92, 133, 133 +portal-streaks1 + bounds: 685, 97, 126, 128 +portal-streaks2 + bounds: 813, 100, 125, 125 +rear-bracer + bounds: 644, 7, 28, 36 +rear-foot + bounds: 554, 18, 57, 30 +rear-shin + bounds: 770, 6, 38, 89 +rear-thigh + bounds: 991, 178, 28, 47 +rear-upper-arm + bounds: 995, 23, 20, 44 +torso + bounds: 940, 135, 49, 90 diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-pma.png b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-pma.png new file mode 100644 index 0000000..92a8b2b Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-pma.png differ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-pro.json b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-pro.json new file mode 100644 index 0000000..4a58fec --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-pro.json @@ -0,0 +1,8798 @@ +{ +"skeleton": { + "hash": "lWe/fmfjp2E", + "spine": "4.3.75-beta", + "x": -188.6338, + "y": -7.939564, + "width": 418.4499, + "height": 686.2023, + "images": "./images/", + "audio": null +}, +"bones": [ + { "name": "root", "rotation": 0.04774475 }, + { "name": "hip", "parent": "root", "y": 247.26994 }, + { "name": "crosshair", "parent": "root", "x": 302.8308, "y": 569.4487, "color": "ff3f00ff", "icon": "circle" }, + { + "name": "aim-constraint-target", + "parent": "hip", + "length": 26.241163, + "rotation": 19.610935, + "x": 1.0154866, + "y": 5.621841, + "color": "abe323ff" + }, + { "name": "rear-foot-target", "parent": "root", "x": 61.90829, "y": 0.4211426, "color": "ff3f00ff", "icon": "ik" }, + { "name": "rear-leg-target", "parent": "rear-foot-target", "x": -33.90897, "y": 37.33794, "color": "ff3f00ff", "icon": "ik" }, + { + "name": "rear-thigh", + "parent": "hip", + "length": 85.7196, + "rotation": -72.541, + "x": 8.913322, + "y": -5.626694, + "color": "ff000dff" + }, + { + "name": "rear-shin", + "parent": "rear-thigh", + "length": 121.87728, + "rotation": -19.83334, + "x": 86.1, + "y": -1.3253326, + "color": "ff000dff" + }, + { + "name": "rear-foot", + "parent": "rear-shin", + "length": 51.58182, + "rotation": 45.7786, + "x": 121.45904, + "y": -0.7551935, + "color": "ff000dff" + }, + { + "name": "back-foot-tip", + "parent": "rear-foot", + "length": 50.3016, + "rotation": -0.8520164, + "x": 51.16588, + "y": 0.23815536, + "inherit": "noRotationOrReflection", + "color": "ff000dff" + }, + { "name": "board-ik", "parent": "root", "x": -131.77533, "y": 69.08683, "color": "4c56ffff", "icon": "arrows" }, + { "name": "clipping", "parent": "root" }, + { + "name": "hoverboard-controller", + "parent": "root", + "rotation": -0.28445435, + "x": -329.6916, + "y": 69.8234, + "color": "ff0004ff", + "icon": "arrowsB" + }, + { "name": "exhaust1", "parent": "hoverboard-controller", "rotation": 3.0205064, "x": -249.68484, "y": 53.39082 }, + { "name": "exhaust2", "parent": "hoverboard-controller", "rotation": 26.335474, "x": -191.6049, "y": -22.92239 }, + { + "name": "exhaust3", + "parent": "hoverboard-controller", + "rotation": -12.341045, + "x": -236.02995, + "y": 80.54244, + "scaleX": 0.7846764, + "scaleY": 0.7846764 + }, + { "name": "portal-root", "parent": "root", "x": 12.90161, "y": 328.5393, "scaleX": 2.033383, "scaleY": 2.033383 }, + { "name": "flare1", "parent": "portal-root", "x": -6.344906, "y": -161.57274, "icon": "particles" }, + { "name": "flare10", "parent": "portal-root", "x": -6.344906, "y": -161.57274, "icon": "particles" }, + { "name": "flare2", "parent": "portal-root", "x": -6.344906, "y": -161.57274, "icon": "particles" }, + { "name": "flare3", "parent": "portal-root", "x": -6.344906, "y": -161.57274, "icon": "particles" }, + { "name": "flare4", "parent": "portal-root", "x": -6.344906, "y": -161.57274, "icon": "particles" }, + { "name": "flare5", "parent": "portal-root", "x": -6.344906, "y": -161.57274, "icon": "particles" }, + { "name": "flare6", "parent": "portal-root", "x": -6.344906, "y": -161.57274, "icon": "particles" }, + { "name": "flare7", "parent": "portal-root", "x": -6.344906, "y": -161.57274, "icon": "particles" }, + { "name": "flare8", "parent": "portal-root", "x": -6.344906, "y": -161.57274, "icon": "particles" }, + { "name": "flare9", "parent": "portal-root", "x": -6.344906, "y": -161.57274, "icon": "particles" }, + { + "name": "torso", + "parent": "hip", + "length": 42.51916, + "rotation": 103.82454, + "x": -1.6175156, + "y": 4.904114, + "color": "e0da19ff" + }, + { "name": "torso2", "parent": "torso", "length": 42.51916, "x": 42.51916, "color": "e0da19ff" }, + { "name": "torso3", "parent": "torso2", "length": 42.51916, "x": 42.51916, "color": "e0da19ff" }, + { "name": "front-shoulder", "parent": "torso3", "rotation": 255.891, "x": 18.721344, "y": 19.329266, "color": "00ff04ff" }, + { "name": "front-upper-arm", "parent": "front-shoulder", "length": 69.45225, "rotation": -87.51462, "color": "00ff04ff" }, + { + "name": "front-bracer", + "parent": "front-upper-arm", + "length": 40.57009, + "rotation": 18.2995, + "x": 68.80316, + "y": -0.6838742, + "color": "00ff04ff" + }, + { + "name": "front-fist", + "parent": "front-bracer", + "length": 65.3853, + "rotation": 12.433234, + "x": 40.56961, + "y": 0.1988964, + "color": "00ff04ff" + }, + { "name": "front-foot-target", "parent": "root", "x": -13.529625, "y": 0.04014587, "color": "ff3f00ff", "icon": "ik" }, + { "name": "front-leg-target", "parent": "front-foot-target", "x": -28.39997, "y": 29.062645, "color": "ff3f00ff", "icon": "ik" }, + { + "name": "front-thigh", + "parent": "hip", + "length": 74.80652, + "rotation": -95.51192, + "x": -17.45899, + "y": -11.644302, + "color": "00ff04ff" + }, + { + "name": "front-shin", + "parent": "front-thigh", + "length": 128.76756, + "rotation": -2.213562, + "x": 78.69012, + "y": 1.6017075, + "color": "00ff04ff" + }, + { + "name": "front-foot", + "parent": "front-shin", + "length": 41.00884, + "rotation": 51.26577, + "x": 128.7557, + "y": -0.3393288, + "color": "00ff04ff" + }, + { + "name": "front-foot-tip", + "parent": "front-foot", + "length": 56.02933, + "rotation": -1.675728, + "x": 41.42462, + "y": -0.08879948, + "inherit": "noRotationOrReflection", + "color": "00ff04ff" + }, + { "name": "back-shoulder", "parent": "torso3", "rotation": -104.109, "x": 7.318115, "y": -19.22088, "color": "ff000dff" }, + { "name": "rear-upper-arm", "parent": "back-shoulder", "length": 51.93936, "rotation": -65.44643, "color": "ff000dff" }, + { "name": "rear-bracer", "parent": "rear-upper-arm", "length": 34.55841, "rotation": 23.15295, "x": 51.35799, "color": "ff000dff" }, + { + "name": "gun", + "parent": "rear-bracer", + "length": 43.10579, + "rotation": -5.427727, + "x": 34.42189, + "y": -0.4539795, + "color": "ff000dff" + }, + { "name": "gun-tip", "parent": "gun", "rotation": 7.099831, "x": 200.77574, "y": 52.49873, "color": "ff0000ff" }, + { + "name": "neck", + "parent": "torso3", + "length": 25.453945, + "rotation": -31.53788, + "x": 42.45889, + "y": -0.3085632, + "color": "e0da19ff" + }, + { + "name": "head", + "parent": "neck", + "length": 131.79367, + "rotation": 26.09855, + "x": 27.66327, + "y": -0.25990295, + "color": "e0da19ff" + }, + { + "name": "hair1", + "parent": "head", + "length": 47.22975, + "rotation": -49.1028, + "x": 149.82922, + "y": -59.77055, + "color": "e0da19ff" + }, + { + "name": "hair2", + "parent": "hair1", + "length": 55.56698, + "rotation": 50.41702, + "x": 47.22934, + "y": 0.1868286, + "color": "e0da19ff" + }, + { + "name": "hair3", + "parent": "head", + "length": 62.22058, + "rotation": -32.16711, + "x": 164.1381, + "y": 3.684761, + "color": "e0da19ff" + }, + { + "name": "hair4", + "parent": "hair3", + "length": 80.28074, + "rotation": 83.70933, + "x": 62.22061, + "y": -0.03564453, + "color": "e0da19ff" + }, + { "name": "hoverboard-thruster-front", "parent": "hoverboard-controller", "rotation": -29.20415, "x": 95.77119, "y": -2.9910965, "inherit": "noRotationOrReflection" }, + { "name": "hoverboard-thruster-rear", "parent": "hoverboard-controller", "rotation": -29.20415, "x": -76.4717, "y": -4.877556, "inherit": "noRotationOrReflection" }, + { "name": "hoverglow-front", "parent": "hoverboard-thruster-front", "rotation": 0.17448044, "x": -1.775383, "y": -37.78541 }, + { "name": "hoverglow-rear", "parent": "hoverboard-thruster-rear", "rotation": 0.17448044, "x": 1.0581818, "y": -35.65678 }, + { + "name": "muzzle", + "parent": "rear-bracer", + "rotation": 3.0575485, + "x": 242.3435, + "y": 34.26361, + "color": "ffb900ff", + "icon": "muzzleFlash" + }, + { "name": "muzzle-ring", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring2", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring3", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring4", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "portal", "parent": "portal-root" }, + { "name": "portal-shade", "parent": "portal-root" }, + { "name": "portal-streaks1", "parent": "portal-root" }, + { "name": "portal-streaks2", "parent": "portal-root" }, + { "name": "side-glow1", "parent": "hoverboard-controller", "x": -110.55987, "y": 2.619972, "color": "000effff" }, + { + "name": "side-glow2", + "parent": "hoverboard-controller", + "x": -110.55987, + "y": 2.619972, + "scaleX": 0.738047, + "scaleY": 0.738047, + "color": "000effff" + }, + { "name": "head-control", "parent": "head", "x": 110.2114, "color": "00a220ff", "icon": "arrows" } +], +"slots": [ + { "name": "portal-bg", "bone": "portal" }, + { "name": "portal-shade", "bone": "portal-shade" }, + { "name": "portal-streaks2", "bone": "portal-streaks2", "blend": "additive" }, + { "name": "portal-streaks1", "bone": "portal-streaks1", "blend": "additive" }, + { "name": "portal-flare8", "bone": "flare8", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare9", "bone": "flare9", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare10", "bone": "flare10", "color": "c3cbffff", "blend": "additive" }, + { "name": "clipping", "bone": "clipping" }, + { "name": "exhaust3", "bone": "exhaust3", "color": "5eb4ffff", "blend": "additive" }, + { "name": "hoverboard-thruster-rear", "bone": "hoverboard-thruster-rear" }, + { "name": "hoverboard-thruster-front", "bone": "hoverboard-thruster-front" }, + { "name": "hoverboard-board", "bone": "hoverboard-controller" }, + { "name": "side-glow1", "bone": "side-glow1", "color": "ff8686ff", "blend": "additive" }, + { "name": "side-glow3", "bone": "side-glow1", "color": "ff8686ff", "blend": "additive" }, + { "name": "side-glow2", "bone": "side-glow2", "color": "ff8686ff", "blend": "additive" }, + { "name": "hoverglow-front", "bone": "hoverglow-front", "color": "5eb4ffff", "blend": "additive" }, + { "name": "hoverglow-rear", "bone": "hoverglow-rear", "color": "5eb4ffff", "blend": "additive" }, + { "name": "exhaust1", "bone": "exhaust2", "color": "5eb4ffff", "blend": "additive" }, + { "name": "exhaust2", "bone": "exhaust1", "color": "5eb4ffff", "blend": "additive" }, + { "name": "rear-upper-arm", "bone": "rear-upper-arm", "attachment": "rear-upper-arm" }, + { "name": "rear-bracer", "bone": "rear-bracer", "attachment": "rear-bracer" }, + { "name": "gun", "bone": "gun", "attachment": "gun" }, + { "name": "rear-foot", "bone": "rear-foot", "attachment": "rear-foot" }, + { "name": "rear-thigh", "bone": "rear-thigh", "attachment": "rear-thigh" }, + { "name": "rear-shin", "bone": "rear-shin", "attachment": "rear-shin" }, + { "name": "neck", "bone": "neck", "attachment": "neck" }, + { "name": "torso", "bone": "torso", "attachment": "torso" }, + { "name": "front-upper-arm", "bone": "front-upper-arm", "attachment": "front-upper-arm" }, + { "name": "head", "bone": "head", "attachment": "head" }, + { "name": "eye", "bone": "head", "attachment": "eye-indifferent" }, + { "name": "front-thigh", "bone": "front-thigh", "attachment": "front-thigh" }, + { "name": "front-foot", "bone": "front-foot", "attachment": "front-foot" }, + { "name": "front-shin", "bone": "front-shin", "attachment": "front-shin" }, + { "name": "mouth", "bone": "head", "attachment": "mouth-smile" }, + { "name": "goggles", "bone": "head", "attachment": "goggles" }, + { "name": "front-bracer", "bone": "front-bracer", "attachment": "front-bracer" }, + { "name": "front-fist", "bone": "front-fist", "attachment": "front-fist-closed" }, + { "name": "muzzle", "bone": "muzzle" }, + { "name": "head-bb", "bone": "head" }, + { "name": "portal-flare1", "bone": "flare1", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare2", "bone": "flare2", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare3", "bone": "flare3", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare4", "bone": "flare4", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare5", "bone": "flare5", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare6", "bone": "flare6", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare7", "bone": "flare7", "color": "c3cbffff", "blend": "additive" }, + { "name": "crosshair", "bone": "crosshair" }, + { "name": "muzzle-glow", "bone": "gun-tip", "color": "ffffff00", "blend": "additive" }, + { "name": "muzzle-ring", "bone": "muzzle-ring", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring2", "bone": "muzzle-ring2", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring3", "bone": "muzzle-ring3", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring4", "bone": "muzzle-ring4", "color": "d8baffff", "blend": "additive" } +], +"constraints": [ + { + "type": "transform", + "name": "shoulder", + "source": "front-shoulder", + "bones": [ "back-shoulder" ], + "x": 40.16696, + "y": -1.6619568, + "properties": { + "x": { + "to": { + "x": { "max": 100 } + } + }, + "y": { + "to": { + "y": { "max": 100 } + } + } + }, + "mixX": -1 + }, + { + "type": "ik", + "name": "board-ik", + "target": "board-ik", + "bones": [ "hoverboard-controller" ] + }, + { + "type": "transform", + "name": "front-foot-board-transform", + "source": "hoverboard-controller", + "bones": [ "front-foot-target" ], + "x": -69.8, + "y": 20.7, + "properties": { + "rotate": { + "to": { + "rotate": { "max": 100 } + } + }, + "x": { + "to": { + "x": { "max": 100 } + } + }, + "y": { + "to": { + "y": { "max": 100 } + } + }, + "scaleX": { + "to": { + "scaleX": {} + } + }, + "scaleY": { + "to": { + "scaleY": {} + } + }, + "shearY": { + "to": { + "shearY": { "max": 100 } + } + } + }, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "type": "transform", + "name": "rear-foot-board-transform", + "source": "hoverboard-controller", + "bones": [ "rear-foot-target" ], + "x": 86.6, + "y": 21.3, + "properties": { + "rotate": { + "to": { + "rotate": { "max": 100 } + } + }, + "x": { + "to": { + "x": { "max": 100 } + } + }, + "y": { + "to": { + "y": { "max": 100 } + } + }, + "scaleX": { + "to": { + "scaleX": {} + } + }, + "scaleY": { + "to": { + "scaleY": {} + } + }, + "shearY": { + "to": { + "shearY": { "max": 100 } + } + } + }, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "type": "ik", + "name": "front-leg-ik", + "target": "front-leg-target", + "bones": [ "front-thigh", "front-shin" ], + "bendPositive": false + }, + { + "type": "ik", + "name": "rear-leg-ik", + "target": "rear-leg-target", + "bones": [ "rear-thigh", "rear-shin" ], + "bendPositive": false + }, + { + "type": "ik", + "name": "front-foot-ik", + "target": "front-foot-target", + "bones": [ "front-foot" ] + }, + { + "type": "ik", + "name": "rear-foot-ik", + "target": "rear-foot-target", + "bones": [ "rear-foot" ] + }, + { + "type": "ik", + "name": "aim-torso-ik", + "target": "crosshair", + "bones": [ "aim-constraint-target" ] + }, + { + "type": "transform", + "name": "aim-torso-transform", + "source": "aim-constraint-target", + "bones": [ "torso" ], + "rotation": 69.5, + "properties": { + "rotate": { + "to": { + "rotate": { "max": 100 } + } + } + }, + "mixRotate": 0 + }, + { + "type": "transform", + "name": "aim-head-transform", + "source": "aim-constraint-target", + "bones": [ "head" ], + "rotation": 84.3, + "properties": { + "rotate": { + "to": { + "rotate": { "max": 100 } + } + } + }, + "mixRotate": 0 + }, + { + "type": "transform", + "name": "aim-front-arm-transform", + "source": "aim-constraint-target", + "bones": [ "front-upper-arm" ], + "rotation": -180, + "properties": { + "rotate": { + "to": { + "rotate": { "max": 100 } + } + } + }, + "mixRotate": 0 + }, + { + "type": "ik", + "name": "aim-ik", + "target": "crosshair", + "bones": [ "rear-upper-arm" ], + "mix": 0 + }, + { + "type": "transform", + "name": "toes-board", + "source": "hoverboard-controller", + "bones": [ "front-foot-tip", "back-foot-tip" ], + "properties": { + "rotate": { + "to": { + "rotate": { "max": 100 } + } + } + }, + "mixRotate": 0 + } +], +"skins": [ + { + "name": "default", + "attachments": { + "clipping": { + "clipping": { + "type": "clipping", + "end": "head-bb", + "vertexCount": 3, + "vertices": [ 18.89, -228.46, 1471.52, 140.96, 34.01, 930.06 ], + "color": "ce3a3aff" + } + }, + "crosshair": { + "crosshair": { "width": 89, "height": 89 } + }, + "exhaust1": { + "hoverglow-small": { "scaleX": 0.4629046, "scaleY": 0.8129372, "rotation": -83.07078, "width": 274, "height": 75 } + }, + "exhaust2": { + "hoverglow-small": { + "x": 0.01145935, + "y": -0.762207, + "scaleX": 0.4208314, + "scaleY": 0.84027, + "rotation": -89.24866, + "width": 274, + "height": 75 + } + }, + "exhaust3": { + "hoverglow-small": { "scaleX": 0.4629046, "scaleY": 0.8129372, "rotation": -83.07078, "width": 274, "height": 75 } + }, + "eye": { + "eye-indifferent": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2.0, 66.0, -36.8, -91.35, 0.3, 46.0, 73.41, -91.35, 0.7, 2.0, 66.0, -87.05, -13.11, 0.70968, 46.0, 23.16, -13.11, 0.29032, 2.0, 66.0, -12.18, 34.99, 0.82818, 46.0, 98.03, 34.99, 0.17182, 2.0, 66.0, 38.07, -43.25, 0.59781, 46.0, 148.28, -43.25, 0.40219 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93.0, + "height": 89.0 + }, + "eye-surprised": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 2.0, 66.0, -46.74, -89.7, 0.3, 46.0, 63.47, -89.7, 0.7, 2.0, 66.0, -77.58, -1.97, 0.71, 46.0, 32.63, -1.97, 0.29, 2.0, 66.0, 6.38, 27.55, 0.83, 46.0, 116.59, 27.55, 0.17, 2.0, 66.0, 37.22, -60.19, 0.6, 46.0, 147.44, -60.19, 0.4 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93.0, + "height": 89.0 + } + }, + "front-bracer": { + "front-bracer": { "x": 12.031342, "y": -1.6766033, "rotation": 79.59598, "width": 58, "height": 80 } + }, + "front-fist": { + "front-fist-closed": { "x": 35.49588, "y": 6.004703, "rotation": 67.16275, "width": 75, "height": 82 }, + "front-fist-open": { "x": 39.56648, "y": 7.764904, "rotation": 67.16275, "width": 86, "height": 87 } + }, + "front-foot": { + "front-foot": { + "type": "mesh", + "uvs": [ 0.5941728, 0.2342187, 0.6225744, 0.3033564, 0.6500988, 0.370359, 0.6763742, 0.3840358, 0.7206807, 0.4070982, 0.762645, 0.4289414, 1, 0.70375, 1, 1, 0.6551704, 1, 0.4692325, 0.99999, 0, 1, 0, 0.39196765, 0.17845653, 0, 0.49795625, 0 ], + "triangles": [ 8, 9, 3, 4, 8, 3, 5, 8, 4, 6, 8, 5, 8, 6, 7, 11, 1, 10, 0, 12, 13, 0, 11, 12, 0, 1, 11, 9, 2, 3, 1, 2, 10, 9, 10, 2 ], + "vertices": [ 2.0, 38.0, 18.17, 41.57, 0.7896, 39.0, 12.46, 46.05, 0.2104, 2.0, 38.0, 24.08, 40.76, 0.71228, 39.0, 16.12, 41.34, 0.28772, 2.0, 38.0, 29.81, 39.98, 0.55344, 39.0, 19.67, 36.78, 0.44656, 2.0, 38.0, 32.81, 41.67, 0.38554, 39.0, 23.0, 35.89, 0.61446, 2.0, 38.0, 37.86, 44.52, 0.25567, 39.0, 28.61, 34.4, 0.74433, 2.0, 38.0, 42.65, 47.22, 0.17384, 39.0, 33.92, 32.99, 0.82616, 1.0, 39.0, 64.15, 14.56, 1.0, 1.0, 39.0, 64.51, -5.87, 1.0, 1.0, 39.0, 21.08, -6.64, 1.0, 2.0, 38.0, 44.67, -6.77, 0.5684, 39.0, -2.34, -6.97, 0.4316, 1.0, 38.0, 3.1, -48.81, 1.0, 1.0, 38.0, -26.73, -19.31, 1.0, 1.0, 38.0, -30.15, 15.69, 1.0, 1.0, 38.0, -1.84, 44.32, 1.0 ], + "hull": 14, + "edges": [ 14, 16, 16, 18, 18, 20, 4, 18, 20, 22, 24, 26, 22, 24, 12, 14, 10, 12, 2, 4, 2, 20, 4, 6, 6, 16, 2, 0, 0, 26, 6, 8, 8, 10 ], + "width": 126.0, + "height": 69.0 + } + }, + "front-shin": { + "front-shin": { + "type": "mesh", + "uvs": [ 0.9003066, 0.05784649, 1, 0.1282812, 1, 0.2161885, 0.9025038, 0.31002015, 0.7873623, 0.356837, 0.7808133, 0.3987374, 0.7721526, 0.4541477, 0.7709815, 0.5157218, 0.8409413, 0.6375107, 0.9309526, 0.7490994, 0.9553094, 0.779295, 0.7812642, 0.876786, 0.561297, 1, 0.2686955, 1, 0, 1, 0.002785478, 0.9611154, 0.013583113, 0.810383, 0.028220676, 0.6060464, 0.08324055, 0.45142215, 0.189084, 0.3188221, 0.2957713, 0.23980266, 0.30235705, 0.14941014, 0.3787467, 0.05902038, 0.5328437, 0, 0.70538, 0, 0.4109394, 0.7196821, 0.4074273, 0.5475082, 0.4109395, 0.4535952, 0.4724029, 0.3518559, 0.3336712, 0.2782907, 0.5022565, 0.3166385, 0.6532811, 0.6750735, 0.6076225, 0.5271604, 0.600598, 0.4512473, 0.6274673, 0.3754273, 0.6572972, 0.3384985, 0.2784303, 0.3292395, 0.18967116, 0.4520299, 0.16508563, 0.585856, 0.18264666, 0.768204, 0.5053195, 0.24634285, 0.594734, 0.1796745, 0.6016121, 0.10610936, 0.513917, 0.04327252, 0.7219777, 0.28848955, 0.8234288, 0.2026636, 0.8681361, 0.11377233, 0.7959167, 0.04633762, 0.4485757, 0.15515275, 0.2546583, 0.962187, 0.5316866, 0.9447962, 0.7531003, 0.8323971 ], + "triangles": [ 24, 0, 47, 43, 23, 24, 47, 43, 24, 43, 22, 23, 42, 43, 47, 46, 47, 0, 42, 47, 46, 46, 0, 1, 48, 22, 43, 48, 43, 42, 21, 22, 48, 41, 48, 42, 45, 42, 46, 41, 42, 45, 46, 1, 2, 45, 46, 2, 40, 48, 41, 48, 20, 21, 29, 48, 40, 29, 20, 48, 44, 41, 45, 40, 41, 44, 3, 45, 2, 44, 45, 3, 30, 29, 40, 35, 30, 40, 36, 19, 20, 36, 20, 29, 44, 35, 40, 28, 29, 30, 4, 44, 3, 35, 44, 4, 34, 30, 35, 5, 35, 4, 34, 28, 30, 33, 28, 34, 37, 19, 36, 18, 19, 37, 27, 29, 28, 27, 28, 33, 36, 29, 27, 37, 36, 27, 5, 34, 35, 6, 34, 5, 33, 34, 6, 6, 32, 33, 7, 32, 6, 26, 37, 27, 38, 18, 37, 38, 37, 26, 17, 18, 38, 31, 32, 7, 31, 7, 8, 32, 25, 26, 38, 26, 25, 27, 33, 32, 32, 26, 27, 39, 38, 25, 17, 38, 39, 16, 17, 39, 51, 31, 8, 51, 8, 9, 11, 51, 9, 11, 9, 10, 31, 50, 25, 31, 25, 32, 50, 31, 51, 49, 39, 25, 49, 25, 50, 15, 16, 39, 49, 15, 39, 13, 49, 50, 14, 15, 49, 13, 14, 49, 12, 50, 51, 12, 51, 11, 13, 50, 12 ], + "vertices": [ -23.66, 19.37, -11.73, 28.98, 4.34, 30.83, 22.41, 24.87, 32.05, 16.48, 39.77, 16.83, 49.98, 17.3, 61.25, 18.5, 82.85, 26.78, 102.4, 36.46, 107.69, 39.09, 127.15, 26.97, 151.74, 11.65, 154.49, -12.18, 157.02, -34.07, 149.89, -34.66, 122.23, -36.97, 84.75, -40.09, 55.97, -38.88, 30.73, -33.05, 15.29, -26.03, -1.3, -27.41, -18.54, -23.09, -30.78, -11.79, -32.4, 2.27, 101.92, -6.52, 70.48, -10.44, 53.28, -12.14, 34.11, -9.28, 21.96, -22.13, 27.39, -7.59, 91.48, 12.28, 64.88, 5.44, 51.07, 3.26, 36.95, 3.85, 29.92, 5.5, 31.8, -25.56, 55.08, -30.19, 79.77, -29.37, 112.93, -24.09, 14.51, -8.83, 1.48, -2.95, -12.03, -3.94, -22.69, -12.41, 20.17, 9.71, 3.53, 16.16, -13.14, 17.93, -24.78, 10.62, -1.62, -15.37, 147.71, -14.13, 141.93, 8.07, 119.3, 23.74 ], + "hull": 25, + "edges": [ 8, 6, 6, 4, 4, 2, 2, 0, 0, 48, 46, 48, 46, 44, 44, 42, 42, 40, 40, 38, 38, 36, 36, 34, 32, 34, 50, 52, 52, 54, 54, 56, 40, 58, 58, 60, 8, 10, 20, 22, 22, 24, 62, 64, 64, 66, 66, 68, 8, 70, 70, 60, 68, 70, 58, 72, 72, 74, 74, 76, 76, 78, 24, 26, 26, 28, 58, 80, 80, 82, 82, 84, 84, 86, 86, 44, 70, 88, 88, 90, 90, 92, 92, 94, 94, 48, 80, 88, 88, 6, 82, 90, 90, 4, 84, 92, 92, 2, 86, 94, 94, 0, 56, 60, 10, 12, 12, 14, 14, 16, 28, 30, 30, 32, 26, 98, 98, 78, 30, 98, 24, 100, 100, 50, 98, 100, 22, 102, 102, 62, 100, 102, 16, 18, 18, 20, 102, 18 ], + "width": 82.0, + "height": 184.0 + } + }, + "front-thigh": { + "front-thigh": { "x": 42.4751, "y": 4.449414, "rotation": 84.86587, "width": 45, "height": 112 } + }, + "front-upper-arm": { + "front-upper-arm": { "x": 28.306147, "y": 7.371247, "rotation": 97.89548, "width": 46, "height": 97 } + }, + "goggles": { + "goggles": { + "type": "mesh", + "uvs": [ 0.5365332, 0.04113967, 0.7292194, 0.16035686, 0.9166696, 0.3322266, 0.9704648, 0.3132907, 1, 0.4805304, 0.9575552, 0.5732991, 0.8882532, 0.6327984, 0.868775, 0.7896234, 0.7740368, 0.867495, 0.7262804, 1, 0.6071384, 0.9386266, 0.4960078, 0.88138, 0.4155779, 0.7502696, 0.32547185, 0.700845, 0.278201, 0.5825681, 0.17209916, 0.6328146, 0.1722854, 0.7507118, 0.10780662, 0.798978, 0, 0.32304054, 0, 0.12475555, 0.07372671, 0.07343647, 0.15423247, 0.10733794, 0.2316526, 0.13994002, 0.3031334, 0.022563254, 0.3480239, 0, 0.42978895, 0.6918342, 0.3947595, 0.5104154, 0.3948817, 0.3151182, 0.4587819, 0.2319774, 0.5650132, 0.2810853, 0.6996078, 0.392161, 0.8203935, 0.5420369, 0.8573792, 0.623428, 0.911071, 0.5140726, 0.726388, 0.3214668, 0.5876366, 0.19609463, 0.4807451, 0.11268945, 0.3782299, 0.05501315, 0.3286954, 0.1786646, 0.3189974, 0.3049975, 0.3603568, 0.5379894, 0.40327474, 0.7007243, 0.3005859, 0.5583792, 0.2195666, 0.2815032, 0.09963368, 0.2894289, 0.5686289, 0.4368027, 0.4911002, 0.3715615, 0.5118472, 0.5209291, 0.6701805, 0.5930374, 0.7619046, 0.6857483, 0.7329629, 0.4335494 ], + "triangles": [ 18, 44, 15, 21, 19, 20, 17, 18, 15, 44, 19, 21, 2, 3, 4, 18, 19, 44, 2, 33, 34, 33, 2, 4, 5, 33, 4, 5, 6, 33, 7, 32, 6, 31, 50, 33, 32, 31, 33, 6, 32, 33, 31, 49, 50, 49, 31, 32, 49, 32, 7, 8, 49, 7, 33, 50, 34, 17, 15, 16, 9, 48, 8, 49, 48, 50, 50, 48, 45, 47, 45, 48, 50, 45, 30, 45, 47, 46, 45, 46, 29, 30, 45, 29, 30, 29, 34, 30, 34, 50, 47, 26, 46, 25, 10, 11, 12, 25, 11, 41, 12, 42, 42, 44, 43, 43, 21, 22, 41, 40, 25, 41, 42, 40, 29, 35, 34, 40, 26, 25, 25, 26, 47, 37, 24, 0, 36, 37, 0, 42, 43, 39, 42, 39, 40, 28, 38, 36, 40, 39, 26, 28, 27, 38, 26, 39, 27, 37, 38, 23, 39, 43, 38, 38, 37, 36, 27, 39, 38, 43, 22, 38, 37, 23, 24, 22, 23, 38, 36, 0, 35, 28, 36, 35, 29, 28, 35, 27, 28, 46, 26, 27, 46, 35, 0, 1, 34, 35, 1, 12, 41, 25, 47, 10, 25, 44, 21, 43, 42, 14, 44, 14, 15, 44, 13, 14, 42, 12, 13, 42, 46, 28, 29, 47, 48, 10, 48, 9, 10, 49, 8, 48, 2, 34, 1 ], + "vertices": [ 2.0, 66.0, 61.88, 22.81, 0.832, 46.0, 172.09, 22.81, 0.168, 2.0, 66.0, 59.89, -31.19, 0.6855, 46.0, 170.1, -31.19, 0.3145, 2.0, 66.0, 49.2, -86.8, 0.32635, 46.0, 159.41, -86.8, 0.67365, 2.0, 66.0, 56.82, -99.01, 0.01217, 46.0, 167.03, -99.01, 0.98783, 1.0, 46.0, 143.4, -115.48, 1.0, 2.0, 66.0, 15.0, -110.14, 0.0041, 46.0, 125.21, -110.14, 0.9959, 2.0, 66.0, -0.32, -96.36, 0.07948, 46.0, 109.89, -96.36, 0.92052, 2.0, 66.0, -26.56, -100.19, 0.01905, 46.0, 83.65, -100.19, 0.98095, 2.0, 66.0, -46.96, -81.16, 0.4921, 46.0, 63.26, -81.16, 0.50791, 2.0, 66.0, -71.84, -76.69, 0.56923, 46.0, 38.37, -76.69, 0.43077, 2.0, 66.0, -72.54, -43.98, 0.74145, 46.0, 37.67, -43.98, 0.25855, 2.0, 66.0, -73.2, -13.47, 0.87929, 46.0, 37.01, -13.47, 0.12071, 2.0, 66.0, -59.63, 13.55, 0.864, 46.0, 50.58, 13.55, 0.136, 2.0, 66.0, -59.69, 38.45, 0.85289, 46.0, 50.52, 38.45, 0.14711, 2.0, 66.0, -45.26, 56.6, 0.74392, 46.0, 64.95, 56.6, 0.25608, 2.0, 66.0, -62.31, 79.96, 0.624, 46.0, 47.9, 79.96, 0.376, 2.0, 66.0, -80.76, 73.42, 0.616, 46.0, 29.45, 73.42, 0.384, 2.0, 66.0, -93.9, 86.64, 0.288, 46.0, 16.31, 86.64, 0.712, 1.0, 46.0, 81.51, 139.38, 1.0, 1.0, 46.0, 112.56, 150.3, 1.0, 2.0, 66.0, 16.76, 134.97, 0.02942, 46.0, 126.97, 134.97, 0.97058, 2.0, 66.0, 18.42, 113.28, 0.36147, 46.0, 128.63, 113.28, 0.63853, 2.0, 66.0, 20.02, 92.43, 0.7135, 46.0, 130.23, 92.43, 0.2865, 2.0, 66.0, 44.58, 81.29, 0.69603, 46.0, 154.79, 81.29, 0.30397, 2.0, 66.0, 52.0, 71.48, 0.848, 46.0, 162.21, 71.48, 0.152, 2.0, 66.0, -49.25, 13.27, 0.8, 46.0, 60.96, 13.27, 0.2, 2.0, 66.0, -23.88, 31.88, 0.896, 46.0, 86.33, 31.88, 0.104, 2.0, 66.0, 6.72, 42.6, 0.928, 46.0, 116.93, 42.6, 0.072, 2.0, 66.0, 25.26, 31.44, 0.8, 46.0, 135.47, 31.44, 0.2, 2.0, 66.0, 26.77, 2.59, 0.75, 46.0, 136.98, 2.59, 0.25, 2.0, 66.0, 21.02, -36.66, 0.54887, 46.0, 131.23, -36.66, 0.45113, 2.0, 66.0, 8.01, -74.65, 0.36029, 46.0, 118.22, -74.65, 0.63971, 2.0, 66.0, -1.52, -88.24, 0.1253, 46.0, 108.69, -88.24, 0.8747, 2.0, 66.0, 20.25, -95.44, 0.08687, 46.0, 130.46, -95.44, 0.91313, 2.0, 66.0, 34.42, -39.36, 0.72613, 46.0, 144.63, -39.36, 0.27387, 2.0, 66.0, 42.03, 1.7, 0.824, 46.0, 152.25, 1.7, 0.176, 2.0, 66.0, 45.85, 32.6, 0.856, 46.0, 156.06, 32.6, 0.144, 1.0, 66.0, 46.01, 61.02, 1.0, 1.0, 66.0, 22.35, 66.41, 1.0, 1.0, 66.0, 1.73, 61.84, 1.0, 2.0, 66.0, -31.17, 38.83, 0.928, 46.0, 79.04, 38.83, 0.072, 2.0, 66.0, -52.94, 19.31, 0.79073, 46.0, 57.27, 19.31, 0.20927, 2.0, 66.0, -39.54, 52.42, 0.912, 46.0, 70.67, 52.42, 0.088, 2.0, 66.0, -3.2, 87.61, 0.744, 46.0, 107.02, 87.61, 0.256, 2.0, 66.0, -14.82, 116.7, 0.6368, 46.0, 95.4, 116.7, 0.3632, 2.0, 66.0, 2.7, -6.87, 0.856, 46.0, 112.91, -6.87, 0.144, 2.0, 66.0, 6.21, 15.8, 0.744, 46.0, 116.42, 15.8, 0.256, 2.0, 66.0, -15.39, 2.47, 0.856, 46.0, 94.82, 2.47, 0.144, 2.0, 66.0, -12.98, -40.48, 0.72102, 46.0, 97.24, -40.48, 0.27898, 2.0, 66.0, -19.55, -68.16, 0.59162, 46.0, 90.66, -68.16, 0.40838, 2.0, 66.0, 17.44, -47.15, 0.53452, 46.0, 127.65, -47.15, 0.46548 ], + "hull": 25, + "edges": [ 36, 34, 34, 32, 32, 30, 30, 28, 28, 26, 26, 24, 24, 22, 18, 16, 16, 14, 14, 12, 12, 10, 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 48, 48, 46, 46, 44, 36, 38, 40, 38, 24, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 62, 64, 64, 12, 8, 66, 66, 68, 68, 70, 70, 72, 72, 74, 74, 76, 76, 78, 78, 80, 80, 82, 82, 24, 24, 84, 84, 86, 86, 44, 40, 42, 42, 44, 42, 88, 88, 30, 58, 90, 90, 92, 92, 94, 18, 20, 20, 22, 94, 20, 18, 96, 96, 98, 60, 100, 100, 62, 98, 100 ], + "width": 261.0, + "height": 166.0 + } + }, + "gun": { + "gun": { "x": 77.30423, "y": 16.40491, "rotation": 60.8259, "width": 210, "height": 203 } + }, + "head": { + "head": { + "type": "mesh", + "uvs": [ 0.7591877, 0.06107302, 0.883922, 0.1789253, 0.901741, 0.3085628, 0.9422393, 0.19660294, 1, 0.2658415, 1, 0.4219956, 0.9586356, 0.4699281, 0.9211802, 0.5133307, 0.8595705, 0.5346962, 0.7838808, 0.6560519, 0.7438444, 0.748384, 0.8511593, 0.7515119, 0.8482836, 0.8256396, 0.817809, 0.853675, 0.7559887, 0.859065, 0.7623688, 0.9046774, 0.6587524, 1, 0.3833651, 1, 0.18579765, 0.854039, 0.12741707, 0.810908, 0.0602479, 0.6920902, 0, 0.5855156, 0, 0.4102103, 0.08529866, 0.20691523, 0.24243174, 0.14504284, 0.4999999, 0.14209673, 0.5032388, 0.0743304, 0.4173836, 0, 0.5761362, 0, 0.8505914, 0.3608683, 0.734311, 0.43206275, 0.6848055, 0.31270725, 0.7216468, 0.1671771, 0.5593148, 0.04153975, 0.4476396, 0.2289488, 0.23925595, 0.2655932, 0.7127154, 0.440357, 0.5699295, 0.3829953, 0.4167824, 0.3351074, 0.2929996, 0.3149697, 0.7080164, 0.4450182, 0.5667631, 0.3897649, 0.41520515, 0.3441631, 0.2875353, 0.3301711, 0.8898812, 0.501767, 0.3038886, 0.7346256, 0.2646026, 0.6567476, 0.2141429, 0.6158368, 0.1461256, 0.6219387, 0.10315738, 0.6663608, 0.10357737, 0.7255686, 0.1450546, 0.7916364, 0.20263426, 0.8135515, 0.2787257, 0.8015873, 0.349468, 0.737601, 0.23073055, 0.5707305, 0.08878042, 0.607067, 0.2946068, 0.8129002, 0.7300557, 0.8788308, 0.6980495, 0.873483, 0.661655, 0.7968106, 0.2246777, 0.698241, 0.14552385, 0.6740475 ], + "triangles": [ 50, 49, 62, 34, 25, 31, 39, 35, 34, 38, 39, 34, 37, 38, 34, 42, 39, 38, 43, 39, 42, 32, 2, 31, 31, 37, 34, 42, 38, 37, 41, 42, 37, 43, 22, 39, 30, 31, 29, 36, 37, 31, 30, 36, 31, 40, 41, 37, 36, 40, 37, 36, 30, 44, 55, 22, 43, 55, 48, 56, 47, 48, 55, 46, 55, 54, 42, 55, 43, 47, 55, 46, 62, 49, 48, 61, 47, 46, 62, 48, 47, 61, 62, 47, 46, 54, 45, 42, 41, 55, 61, 46, 45, 55, 41, 54, 61, 51, 50, 61, 50, 62, 60, 41, 40, 54, 41, 60, 53, 61, 45, 52, 51, 61, 57, 53, 45, 57, 45, 54, 53, 52, 61, 52, 19, 51, 57, 18, 52, 57, 52, 53, 17, 54, 60, 57, 54, 17, 18, 57, 17, 19, 50, 51, 33, 27, 28, 26, 27, 33, 0, 33, 28, 32, 33, 0, 32, 0, 1, 33, 25, 26, 33, 32, 25, 31, 25, 32, 2, 32, 1, 2, 3, 4, 29, 31, 2, 2, 4, 5, 29, 2, 5, 6, 29, 5, 30, 29, 6, 44, 30, 6, 18, 19, 52, 49, 56, 48, 34, 24, 25, 35, 23, 24, 35, 24, 34, 39, 22, 35, 22, 23, 35, 7, 44, 6, 8, 36, 44, 40, 36, 8, 8, 44, 7, 56, 21, 22, 55, 56, 22, 9, 40, 8, 20, 21, 56, 20, 56, 49, 9, 60, 40, 10, 60, 9, 20, 50, 19, 12, 10, 11, 13, 10, 12, 14, 60, 10, 13, 14, 10, 59, 60, 14, 58, 59, 14, 58, 14, 15, 16, 17, 60, 59, 16, 60, 15, 16, 59, 15, 59, 58, 20, 49, 50 ], + "vertices": [ 2.0, 50.0, 41.97, -41.8, 0.94074, 66.0, 165.41, -22.6, 0.05926, 4.0, 48.0, 73.47, 27.54, 0.26795, 50.0, -5.75, -51.71, 0.4738, 49.0, 112.99, -11.41, 0.12255, 66.0, 143.5, -66.13, 0.1357, 4.0, 48.0, 38.23, 10.99, 0.6831, 50.0, -41.01, -35.22, 0.07866, 49.0, 92.73, -44.66, 0.04872, 66.0, 108.65, -83.49, 0.18952, 2.0, 48.0, 73.35, 10.89, 0.8455, 66.0, 143.77, -82.78, 0.1545, 2.0, 48.0, 58.59, -10.38, 0.91607, 66.0, 129.5, -104.39, 0.08393, 3.0, 46.0, 195.82, -119.82, 0.104, 47.0, 75.49, -4.55, 0.09191, 48.0, 14.36, -24.8, 0.80409, 4.0, 46.0, 178.62, -113.98, 0.19022, 47.0, 59.82, -13.72, 0.33409, 48.0, -2.7, -18.57, 0.46643, 66.0, 68.41, -113.98, 0.00926, 4.0, 46.0, 163.06, -108.69, 0.18724, 47.0, 45.64, -22.03, 0.3133, 48.0, -18.14, -12.93, 0.47469, 66.0, 52.84, -108.69, 0.02477, 2.0, 46.0, 151.52, -95.05, 0.91122, 66.0, 41.31, -95.05, 0.08878, 2.0, 46.0, 110.61, -87.69, 0.70564, 66.0, 0.4, -87.69, 0.29436, 2.0, 46.0, 81.05, -86.58, 0.63951, 66.0, -29.16, -86.58, 0.36049, 2.0, 46.0, 89.82, -114.32, 0.57, 66.0, -20.39, -114.32, 0.43, 2.0, 46.0, 68.72, -120.91, 0.57, 66.0, -41.49, -120.91, 0.43, 2.0, 46.0, 58.1, -115.9, 0.57, 66.0, -52.11, -115.9, 0.43, 2.0, 46.0, 51.03, -100.63, 0.64242, 66.0, -59.18, -100.63, 0.35758, 2.0, 46.0, 38.79, -106.76, 0.81659, 66.0, -71.43, -106.76, 0.18341, 2.0, 46.0, 2.68, -89.7, 0.77801, 66.0, -107.53, -89.7, 0.22199, 2.0, 46.0, -22.07, -19.3, 0.823, 66.0, -132.28, -19.3, 0.177, 2.0, 46.0, 1.2, 45.63, 0.51204, 66.0, -109.01, 45.63, 0.48796, 2.0, 46.0, 8.07, 64.81, 0.60869, 66.0, -102.14, 64.81, 0.39131, 2.0, 46.0, 35.44, 93.73, 0.80009, 66.0, -74.77, 93.73, 0.19991, 2.0, 46.0, 59.98, 119.66, 0.93554, 66.0, -50.23, 119.66, 0.06446, 2.0, 46.0, 109.26, 136.99, 0.99895, 66.0, -0.95, 136.99, 0.00105, 1.0, 46.0, 174.07, 135.27, 1.0, 3.0, 46.0, 205.59, 101.22, 0.80778, 49.0, -16.84, 104.63, 0.15658, 66.0, 95.38, 101.22, 0.03564, 3.0, 50.0, 58.94, 30.5, 0.43491, 49.0, 38.36, 61.89, 0.28116, 66.0, 119.35, 35.65, 0.28393, 2.0, 50.0, 75.56, 19.01, 0.92164, 66.0, 138.68, 41.52, 0.07836, 1.0, 50.0, 106.7, 26.9, 1.0, 1.0, 50.0, 83.79, -9.51, 1.0, 5.0, 47.0, 44.51, 27.24, 0.15139, 48.0, 19.12, 19.33, 0.44847, 50.0, -46.82, -15.19, 0.05757, 49.0, 72.19, -48.24, 0.1149, 66.0, 89.35, -75.58, 0.22767, 3.0, 47.0, 7.42, 19.08, 0.37772, 49.0, 34.32, -45.24, 0.09918, 66.0, 58.9, -52.89, 0.52311, 2.0, 49.0, 45.94, -9.07, 0.4826, 66.0, 87.99, -28.45, 0.5174, 2.0, 50.0, 20.62, -16.35, 0.7435, 66.0, 132.21, -23.49, 0.2565, 2.0, 50.0, 75.74, 0.94, 0.97172, 66.0, 152.95, 30.42, 0.02828, 4.0, 46.0, 200.45, 40.46, 0.18809, 50.0, 44.6, 56.29, 0.05831, 49.0, 11.15, 50.46, 0.14366, 66.0, 90.24, 40.46, 0.60994, 2.0, 46.0, 171.41, 90.12, 0.48644, 66.0, 61.2, 90.12, 0.51356, 2.0, 46.0, 164.84, -48.18, 0.43217, 66.0, 54.62, -48.18, 0.56783, 4.0, 46.0, 168.13, -6.02, 0.01949, 47.0, -28.65, 49.02, 0.02229, 49.0, 8.54, -6.09, 0.12791, 66.0, 57.92, -6.02, 0.83031, 2.0, 46.0, 167.84, 37.87, 0.15, 66.0, 57.63, 37.87, 0.85, 2.0, 46.0, 162.36, 71.5, 0.24107, 66.0, 52.15, 71.5, 0.75893, 2.0, 46.0, 163.11, -47.44, 0.41951, 66.0, 52.9, -47.44, 0.58049, 2.0, 46.0, 165.94, -5.87, 0.16355, 66.0, 55.73, -5.87, 0.83645, 2.0, 46.0, 165.14, 37.38, 0.15, 66.0, 54.93, 37.38, 0.85, 2.0, 46.0, 157.6, 71.4, 0.21735, 66.0, 47.39, 71.4, 0.78265, 3.0, 46.0, 163.5, -99.54, 0.61812, 47.0, 39.01, -15.71, 0.30445, 66.0, 53.29, -99.54, 0.07744, 2.0, 46.0, 45.38, 27.24, 0.16741, 66.0, -64.83, 27.24, 0.83259, 2.0, 46.0, 63.74, 44.98, 0.15, 66.0, -46.47, 44.98, 0.85, 2.0, 46.0, 70.7, 61.92, 0.22175, 66.0, -39.51, 61.92, 0.77825, 2.0, 46.0, 62.88, 78.71, 0.38, 66.0, -47.34, 78.71, 0.62, 2.0, 46.0, 46.53, 85.3, 0.51, 66.0, -63.68, 85.3, 0.49, 2.0, 46.0, 29.92, 79.34, 0.388, 66.0, -80.29, 79.34, 0.612, 2.0, 46.0, 15.08, 62.21, 0.38, 66.0, -95.13, 62.21, 0.62, 2.0, 46.0, 14.09, 45.32, 0.41, 66.0, -96.12, 45.32, 0.59, 2.0, 46.0, 24.3, 27.06, 0.192, 66.0, -85.91, 27.06, 0.808, 1.0, 66.0, -61.57, 15.3, 1.0, 2.0, 46.0, 84.87, 62.14, 0.16757, 66.0, -25.34, 62.14, 0.83243, 2.0, 46.0, 61.9, 94.84, 0.68145, 66.0, -48.31, 94.84, 0.31855, 2.0, 46.0, 22.54, 21.88, 0.16, 66.0, -87.67, 21.88, 0.84, 2.0, 46.0, 43.15, -95.95, 0.73445, 66.0, -67.06, -95.95, 0.26555, 2.0, 46.0, 41.77, -87.24, 0.67858, 66.0, -68.44, -87.24, 0.32142, 2.0, 46.0, 60.05, -70.36, 0.50195, 66.0, -50.16, -70.36, 0.49805, 2.0, 46.0, 48.49, 51.09, 0.25, 66.0, -61.72, 51.09, 0.75, 2.0, 46.0, 48.17, 73.71, 0.15634, 66.0, -62.04, 73.71, 0.84366 ], + "hull": 29, + "edges": [ 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 56, 54, 56, 54, 52, 52, 50, 50, 48, 48, 46, 46, 44, 42, 44, 32, 34, 4, 58, 58, 60, 62, 64, 64, 66, 66, 54, 50, 68, 68, 70, 70, 44, 60, 72, 62, 74, 72, 74, 74, 76, 76, 78, 78, 44, 16, 80, 80, 82, 82, 84, 84, 86, 86, 44, 14, 88, 88, 72, 14, 16, 10, 12, 12, 14, 12, 60, 90, 92, 92, 94, 94, 96, 96, 98, 98, 100, 100, 102, 102, 104, 104, 106, 106, 90, 108, 110, 110, 112, 38, 40, 40, 42, 112, 40, 34, 36, 36, 38, 36, 114, 114, 108, 30, 32, 30, 28, 24, 26, 28, 26, 22, 24, 22, 20, 20, 18, 18, 16, 28, 116, 116, 118, 118, 120, 120, 20 ], + "width": 271.0, + "height": 298.0 + } + }, + "head-bb": { + "head": { + "type": "boundingbox", + "vertexCount": 6, + "vertices": [ -19.14, -70.3, 40.8, -118.08, 257.78, -115.62, 285.17, 57.18, 120.77, 164.95, -5.07, 76.95 ] + } + }, + "hoverboard-board": { + "hoverboard-board": { + "type": "mesh", + "uvs": [ 0.13864607, 0.5662393, 0.1142763, 0.5146078, 0.07618786, 0.5210682, 0.023639273, 0.5299812, 0.012808947, 0.5318183, 0, 0.3797923, 0, 0.2205953, 0.005191774, 0.10824845, 0.010375012, 0.10726268, 0.03834171, 0.10194385, 0.05091461, 0, 0.08326002, 0, 0.10932894, 0.04206121, 0.13820295, 0.08864832, 0.18915813, 0.24067438, 0.22233906, 0.4063021, 0.23886204, 0.4406347, 0.8341238, 0.44034415, 0.8844377, 0.3829573, 0.9259101, 0.32638615, 0.959957, 0.2884101, 0.9861191, 0.2854167, 1, 0.38675195, 0.9949444, 0.471042, 0.9788285, 0.5325082, 0.9440907, 0.62135, 0.9020624, 0.6949223, 0.8656917, 0.7109357, 0.8282192, 0.7079088, 0.8128592, 0.7712708, 0.629307, 0.772659, 0.61364, 0.7064525, 0.4716633, 0.7066431, 0.4590079, 0.7782668, 0.2774682, 0.769859, 0.2657999, 0.7037184, 0.24976107, 0.7138066, 0.246009, 0.7782668, 0.230418, 0.8493069, 0.2092619, 0.9095554, 0.17298914, 1, 0.15076564, 0.9996735, 0.1290571, 0.9019248, 0.10369129, 0.736925, 0.10198391, 0.6248198, 0.0913133, 0.4727209, 0.09133468, 0.41324735, 0.15081826, 0.41867685, 0.2199145, 0.518557, 0.0633089, 0.10816091, 0.08382638, 0.2169557, 0.08905153, 0.3753241, 0.15903135, 0.5872583, 0.1753802, 0.6570573, 0.20118096, 0.8029049, 0.1791791, 0.5564352, 0.22166404, 0.5802012, 0.862594, 0.5796152, 0.9234568, 0.4853438, 0.9669095, 0.3688111, 0.09450015, 0.13259096, 0.12687987, 0.17830575, 0.15985525, 0.24681903, 0.18035573, 0.3126794, 0.2060718, 0.4235007, 0.16074103, 0.8540321, 0.1362352, 0.7012158, 0.12096038, 0.6404868, 0.02395992, 0.2181119, 0.027316555, 0.3783871, 0.025566524, 0.4971959, 0.14475645, 0.4573603, 0.18019417, 0.5168893, 0.19692187, 0.5663605 ], + "triangles": [ 10, 11, 12, 9, 10, 12, 49, 9, 12, 60, 49, 12, 13, 60, 12, 61, 60, 13, 50, 49, 60, 50, 60, 61, 68, 8, 9, 68, 9, 49, 68, 49, 50, 7, 8, 68, 6, 7, 68, 61, 13, 14, 62, 61, 14, 50, 61, 62, 63, 62, 14, 59, 20, 21, 19, 20, 59, 51, 50, 62, 51, 62, 63, 51, 69, 68, 51, 68, 50, 6, 68, 69, 5, 6, 69, 18, 19, 59, 15, 63, 14, 59, 21, 22, 47, 51, 63, 47, 46, 51, 47, 63, 64, 15, 64, 63, 64, 15, 16, 71, 46, 47, 23, 59, 22, 69, 51, 70, 45, 46, 71, 70, 51, 2, 58, 18, 59, 58, 59, 23, 17, 18, 58, 70, 5, 69, 2, 51, 46, 1, 45, 71, 47, 48, 71, 47, 64, 48, 48, 72, 71, 1, 71, 72, 16, 48, 64, 45, 2, 46, 2, 45, 1, 70, 4, 5, 3, 70, 2, 3, 4, 70, 24, 58, 23, 72, 0, 1, 73, 55, 72, 55, 0, 72, 48, 73, 72, 57, 17, 58, 25, 57, 58, 56, 48, 16, 73, 48, 56, 56, 16, 17, 56, 17, 57, 52, 0, 55, 24, 25, 58, 44, 0, 52, 67, 44, 52, 52, 56, 53, 73, 52, 55, 56, 52, 73, 67, 52, 53, 26, 57, 25, 66, 67, 53, 56, 32, 35, 53, 56, 35, 56, 57, 32, 28, 31, 57, 57, 31, 32, 57, 27, 28, 26, 27, 57, 36, 53, 35, 43, 44, 67, 43, 67, 66, 34, 35, 32, 29, 31, 28, 30, 31, 29, 53, 54, 66, 53, 36, 54, 33, 34, 32, 37, 54, 36, 65, 43, 66, 38, 54, 37, 54, 65, 66, 39, 65, 54, 42, 43, 65, 38, 39, 54, 40, 42, 65, 40, 41, 42, 65, 39, 40 ], + "vertices": [ -189.36, 15.62, -201.35, 23.47, -220.09, 22.49, -245.95, 21.13, -251.28, 20.86, -257.58, 43.96, -257.57, 68.16, -255.02, 85.24, -252.47, 85.39, -238.71, 86.2, -232.52, 101.69, -216.61, 101.69, -203.78, 95.3, -189.58, 88.21, -164.51, 65.1, -148.19, 39.93, -140.06, 34.71, 152.82, 34.73, 177.57, 43.45, 197.97, 52.05, 214.72, 57.82, 227.6, 58.27, 234.42, 42.87, 231.94, 30.06, 224.01, 20.72, 206.91, 7.21, 186.23, -3.97, 168.34, -6.4, 149.9, -5.94, 142.35, -15.57, 52.04, -15.77, 44.33, -5.71, -25.52, -5.73, -31.75, -16.62, -121.07, -15.34, -126.81, -5.28, -134.7, -6.81, -136.54, -16.61, -144.22, -27.41, -154.63, -36.57, -172.47, -50.31, -183.41, -50.26, -194.09, -35.4, -206.56, -10.32, -207.4, 6.72, -212.65, 29.84, -212.64, 38.88, -183.37, 38.05, -149.38, 22.86, -226.43, 85.25, -216.33, 68.71, -213.76, 44.64, -179.34, 12.42, -171.29, 1.81, -158.6, -20.36, -169.42, 17.11, -148.52, 13.49, 166.82, 13.56, 196.76, 27.89, 218.14, 45.6, -211.08, 81.54, -195.15, 74.59, -178.93, 64.17, -168.84, 54.16, -156.19, 37.31, -178.5, -28.13, -190.55, -4.9, -198.07, 4.33, -245.79, 68.54, -244.14, 44.18, -245.0, 26.12, -186.36, 32.17, -168.92, 23.12, -160.69, 15.6 ], + "hull": 45, + "edges": [ 0, 2, 8, 10, 10, 12, 12, 14, 18, 20, 20, 22, 26, 28, 28, 30, 30, 32, 32, 34, 34, 36, 36, 38, 38, 40, 40, 42, 42, 44, 44, 46, 46, 48, 48, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 60, 62, 62, 64, 64, 66, 66, 68, 68, 70, 70, 72, 72, 74, 80, 82, 82, 84, 84, 86, 86, 88, 0, 88, 2, 90, 90, 92, 92, 94, 94, 96, 96, 32, 18, 98, 98, 100, 100, 102, 2, 4, 102, 4, 92, 102, 0, 104, 104, 106, 106, 108, 78, 80, 108, 78, 74, 76, 76, 78, 62, 56, 64, 70, 0, 110, 112, 114, 114, 116, 116, 118, 118, 42, 50, 116, 114, 34, 98, 120, 120, 122, 22, 24, 24, 26, 120, 24, 122, 124, 124, 126, 126, 128, 128, 96, 80, 130, 130, 132, 132, 134, 134, 88, 14, 16, 16, 18, 136, 16, 136, 138, 138, 140, 4, 6, 6, 8, 140, 6, 96, 112, 92, 142, 142, 144, 110, 146, 146, 112, 144, 146 ], + "width": 492.0, + "height": 152.0 + } + }, + "hoverboard-thruster-front": { + "hoverboard-thruster": { "x": 0.021476746, "y": -7.079941, "rotation": 0.17448044, "width": 60, "height": 64 } + }, + "hoverboard-thruster-rear": { + "hoverboard-thruster": { "x": 1.099083, "y": -6.286655, "rotation": 0.17448044, "width": 60, "height": 64 } + }, + "hoverglow-front": { + "hoverglow-small": { + "x": 2.129986, + "y": -1.9999886, + "scaleX": 0.303, + "scaleY": 0.495, + "rotation": 0.1500038, + "width": 274, + "height": 75 + } + }, + "hoverglow-rear": { + "hoverglow-small": { + "x": 1.389984, + "y": -2.089989, + "scaleX": 0.303, + "scaleY": 0.495, + "rotation": 0.609827, + "width": 274, + "height": 75 + } + }, + "mouth": { + "mouth-grind": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2.0, 66.0, -98.93, -85.88, 0.22, 46.0, 11.28, -85.88, 0.78, 2.0, 66.0, -129.77, 1.84, 0.6, 46.0, -19.56, 1.84, 0.4, 2.0, 66.0, -74.12, 21.41, 0.6, 46.0, 36.09, 21.41, 0.4, 2.0, 66.0, -43.28, -66.32, 0.4, 46.0, 66.93, -66.32, 0.6 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93.0, + "height": 59.0 + }, + "mouth-oooo": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2.0, 46.0, 11.28, -85.89, 0.22, 66.0, -98.93, -85.89, 0.78, 2.0, 46.0, -19.56, 1.85, 0.6, 66.0, -129.78, 1.85, 0.4, 2.0, 46.0, 36.1, 21.42, 0.6, 66.0, -74.12, 21.42, 0.4, 2.0, 46.0, 66.94, -66.32, 0.4, 66.0, -43.27, -66.32, 0.6 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93.0, + "height": 59.0 + }, + "mouth-smile": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2.0, 66.0, -98.93, -85.89, 0.21075, 46.0, 11.28, -85.89, 0.78925, 2.0, 66.0, -129.77, 1.85, 0.6, 46.0, -19.56, 1.85, 0.4, 2.0, 66.0, -74.11, 21.42, 0.6, 46.0, 36.1, 21.42, 0.4, 2.0, 66.0, -43.27, -66.32, 0.40772, 46.0, 66.94, -66.32, 0.59228 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93.0, + "height": 59.0 + } + }, + "muzzle": { + "muzzle01": { + "x": 151.9714, + "y": 5.807556, + "scaleX": 3.736082, + "scaleY": 3.736082, + "rotation": 0.15336847, + "width": 133, + "height": 79 + }, + "muzzle02": { + "x": 187.2479, + "y": 5.901977, + "scaleX": 4.062283, + "scaleY": 4.062283, + "rotation": 0.15336847, + "width": 135, + "height": 84 + }, + "muzzle03": { + "x": 231.96396, + "y": 6.021667, + "scaleX": 4.132498, + "scaleY": 4.132498, + "rotation": 0.15336847, + "width": 166, + "height": 106 + }, + "muzzle04": { + "x": 231.964, + "y": 6.021667, + "scaleX": 4.004575, + "scaleY": 4.004575, + "rotation": 0.15336847, + "width": 149, + "height": 90 + }, + "muzzle05": { + "x": 293.8012, + "y": 6.187192, + "scaleX": 4.467276, + "scaleY": 4.467276, + "rotation": 0.15336847, + "width": 135, + "height": 75 + } + }, + "muzzle-glow": { + "muzzle-glow": { "width": 50, "height": 50 } + }, + "muzzle-ring": { + "muzzle-ring": { "x": -1.304802, "y": 0.3222961, "scaleX": 0.3147263, "scaleY": 0.3147263, "width": 49, "height": 209 } + }, + "muzzle-ring2": { + "muzzle-ring": { "x": -1.304802, "y": 0.3222961, "scaleX": 0.3147263, "scaleY": 0.3147263, "width": 49, "height": 209 } + }, + "muzzle-ring3": { + "muzzle-ring": { "x": -1.304802, "y": 0.3222961, "scaleX": 0.3147263, "scaleY": 0.3147263, "width": 49, "height": 209 } + }, + "muzzle-ring4": { + "muzzle-ring": { "x": -1.304802, "y": 0.3222961, "scaleX": 0.3147263, "scaleY": 0.3147263, "width": 49, "height": 209 } + }, + "neck": { + "neck": { "x": 9.7695, "y": -3.0127716, "rotation": -55.22381, "width": 36, "height": 41 } + }, + "portal-bg": { + "portal-bg": { "x": -3.0979004, "y": 7.247131, "scaleX": 1.04917, "scaleY": 1.04917, "width": 266, "height": 266 } + }, + "portal-flare1": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare2": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare3": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare4": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare5": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare6": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare7": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare8": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare9": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare10": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-shade": { + "portal-shade": { "width": 266, "height": 266 } + }, + "portal-streaks1": { + "portal-streaks1": { "scaleX": 0.9773776, "scaleY": 0.9773776, "width": 252, "height": 256 } + }, + "portal-streaks2": { + "portal-streaks2": { "x": -1.6380005, "y": 2.793793, "width": 250, "height": 249 } + }, + "rear-bracer": { + "rear-bracer": { "x": 11.151097, "y": -2.2033694, "rotation": 66.17306, "width": 56, "height": 72 } + }, + "rear-foot": { + "rear-foot": { + "type": "mesh", + "uvs": [ 0.4836849, 0.13870415, 0.5199078, 0.2142364, 0.5509983, 0.2790666, 0.588384, 0.2981607, 0.6348886, 0.3219122, 0.773423, 0.3926665, 1, 0.7334662, 1, 1, 0.5483075, 0.9988311, 0.3116092, 1, 0, 1, 0, 0.4139664, 0.1363084, 0, 0.4171667, 0 ], + "triangles": [ 8, 3, 4, 8, 4, 5, 8, 5, 6, 8, 6, 7, 11, 1, 10, 3, 9, 2, 2, 10, 1, 12, 13, 0, 0, 11, 12, 1, 11, 0, 2, 9, 10, 3, 8, 9 ], + "vertices": [ 2.0, 8.0, 10.45, 29.41, 0.90802, 9.0, -6.74, 49.62, 0.09198, 2.0, 8.0, 16.56, 29.27, 0.84259, 9.0, -2.65, 45.09, 0.15741, 2.0, 8.0, 21.8, 29.15, 0.69807, 9.0, 0.85, 41.2, 0.30193, 2.0, 8.0, 25.53, 31.43, 0.52955, 9.0, 5.08, 40.05, 0.47045, 2.0, 8.0, 30.18, 34.27, 0.39303, 9.0, 10.33, 38.62, 0.60697, 2.0, 8.0, 44.02, 42.73, 0.27525, 9.0, 25.98, 34.36, 0.72475, 2.0, 8.0, 76.47, 47.28, 0.21597, 9.0, 51.56, 13.9, 0.78403, 2.0, 8.0, 88.09, 36.29, 0.28719, 9.0, 51.55, -2.09, 0.71281, 2.0, 8.0, 52.94, -0.73, 0.47576, 9.0, 0.52, -1.98, 0.52424, 2.0, 8.0, 34.63, -20.23, 0.68757, 9.0, -26.23, -2.03, 0.31243, 2.0, 8.0, 10.44, -45.81, 0.84141, 9.0, -61.43, -2.0, 0.15859, 2.0, 8.0, -15.11, -21.64, 0.93283, 9.0, -61.4, 33.15, 0.06717, 1.0, 8.0, -22.57, 6.61, 1.0, 1.0, 8.0, -0.76, 29.67, 1.0 ], + "hull": 14, + "edges": [ 14, 12, 10, 12, 14, 16, 16, 18, 18, 20, 4, 18, 20, 22, 24, 26, 22, 24, 4, 2, 2, 20, 4, 6, 6, 16, 6, 8, 8, 10, 2, 0, 0, 26 ], + "width": 113.0, + "height": 60.0 + } + }, + "rear-shin": { + "rear-shin": { "x": 58.29028, "y": -2.754337, "rotation": 92.37433, "width": 75, "height": 178 } + }, + "rear-thigh": { + "rear-thigh": { "x": 33.10798, "y": -4.11312, "rotation": 72.541, "width": 55, "height": 94 } + }, + "rear-upper-arm": { + "rear-upper-arm": { "x": 21.125124, "y": 4.087035, "rotation": 89.326, "width": 40, "height": 87 } + }, + "side-glow1": { + "hoverglow-small": { "x": 2.0941744, "scaleX": 0.2352714, "scaleY": 0.41317555, "width": 274, "height": 75 } + }, + "side-glow2": { + "hoverglow-small": { "x": 2.0941744, "scaleX": 0.2352714, "scaleY": 0.41317555, "width": 274, "height": 75 } + }, + "side-glow3": { + "hoverglow-small": { "x": 2.0941744, "scaleX": 0.358589, "scaleY": 0.6297418, "width": 274, "height": 75 } + }, + "torso": { + "torso": { + "type": "mesh", + "uvs": [ 0.6250965, 0.12672493, 1, 0.2636083, 1, 0.2887058, 1, 0.660211, 1, 0.6824525, 0.923239, 0.692587, 0.951158, 0.8496525, 0.7712399, 1, 0.4965475, 1, 0.2718115, 1, 0.1384236, 0.7719636, 0.09886348, 0.6817047, 0.05634972, 0.584707, 0, 0.45614165, 0, 0.3377818, 0, 0.1943639, 0.1446278, 0, 0.2780154, 0, 0.725248, 0.2783501, 0.7609111, 0.462161, 0.8488804, 0.6796275, 0.6825737, 0.6324945, 0.5398596, 0.38469505, 0.2544315, 0.3216951, 0.3006293, 0.5517359, 0.3955271, 0.795069, 0.2638947, 0.1700697, 0.5240986, 0.18673615, 0.7149173, 0.766553, 0.8215117, 0.7295553, 0.2762614, 0.4303966, 0.62327, 0.5295234, 0.3454993, 0.66679, 0.5324313, 0.2913962 ], + "triangles": [ 18, 1, 2, 19, 2, 3, 18, 0, 1, 23, 15, 26, 27, 26, 16, 14, 15, 23, 15, 16, 26, 17, 27, 16, 13, 14, 23, 0, 27, 17, 13, 23, 30, 11, 12, 24, 21, 31, 19, 12, 13, 30, 24, 22, 31, 31, 22, 19, 12, 30, 24, 32, 24, 31, 24, 30, 22, 3, 20, 19, 32, 31, 21, 11, 24, 32, 4, 5, 3, 8, 28, 7, 7, 29, 6, 7, 28, 29, 9, 25, 8, 8, 25, 28, 9, 10, 25, 29, 5, 6, 10, 32, 25, 25, 21, 28, 25, 32, 21, 10, 11, 32, 28, 21, 29, 29, 20, 5, 29, 21, 20, 5, 20, 3, 20, 21, 19, 33, 26, 27, 22, 18, 19, 19, 18, 2, 33, 27, 18, 30, 23, 22, 22, 33, 18, 23, 33, 22, 33, 23, 26, 27, 0, 18 ], + "vertices": [ 2.0, 29.0, 44.59, -10.39, 0.88, 40.0, -17.65, 33.99, 0.12, 3.0, 28.0, 59.65, -45.08, 0.12189, 29.0, 17.13, -45.08, 0.26811, 40.0, 22.68, 15.82, 0.61, 3.0, 28.0, 55.15, -44.72, 0.1345, 29.0, 12.63, -44.72, 0.2555, 40.0, 23.43, 11.37, 0.61, 3.0, 27.0, 31.01, -39.45, 0.51133, 28.0, -11.51, -39.45, 0.30867, 40.0, 34.58, -54.57, 0.18, 3.0, 27.0, 27.01, -39.14, 0.53492, 28.0, -15.5, -39.14, 0.28508, 40.0, 35.25, -58.52, 0.18, 2.0, 27.0, 25.79, -31.5, 0.75532, 28.0, -16.73, -31.5, 0.24468, 1.0, 27.0, -2.61, -32.0, 1.0, 1.0, 27.0, -28.2, -12.29, 1.0, 1.0, 27.0, -26.08, 14.55, 1.0, 1.0, 27.0, -24.35, 36.5, 1.0, 2.0, 27.0, 17.6, 46.3, 0.8332, 28.0, -24.92, 46.3, 0.1668, 2.0, 27.0, 34.1, 48.89, 0.59943, 28.0, -8.42, 48.89, 0.40058, 3.0, 27.0, 51.83, 51.67, 0.29262, 28.0, 9.32, 51.67, 0.63181, 29.0, -33.2, 51.67, 0.07557, 3.0, 27.0, 75.34, 55.35, 0.06656, 28.0, 32.82, 55.35, 0.62298, 29.0, -9.7, 55.35, 0.31046, 2.0, 28.0, 54.06, 53.67, 0.37296, 29.0, 11.54, 53.67, 0.62704, 2.0, 28.0, 79.79, 51.64, 0.10373, 29.0, 37.27, 51.64, 0.89627, 1.0, 29.0, 71.04, 34.76, 1.0, 1.0, 29.0, 70.01, 21.72, 1.0, 1.0, 30.0, 36.74, 7.06, 1.0, 3.0, 30.0, 45.7, -24.98, 0.67, 28.0, 25.87, -18.9, 0.3012, 29.0, -16.65, -18.9, 0.0288, 2.0, 27.0, 28.69, -24.42, 0.77602, 28.0, -13.83, -24.42, 0.22398, 3.0, 30.0, 43.24, -56.49, 0.064, 27.0, 38.43, -8.84, 0.67897, 28.0, -4.09, -8.84, 0.25703, 3.0, 30.0, 22.02, -14.85, 0.29, 28.0, 41.48, 1.59, 0.53368, 29.0, -1.04, 1.59, 0.17632, 3.0, 30.0, -7.45, -8.33, 0.76, 28.0, 54.98, 28.59, 0.06693, 29.0, 12.46, 28.59, 0.17307, 3.0, 30.0, 3.91, -48.4, 0.25, 27.0, 55.87, 27.33, 0.15843, 28.0, 13.35, 27.33, 0.59157, 1.0, 27.0, 11.47, 21.51, 1.0, 2.0, 30.0, -11.09, 18.74, 0.416, 29.0, 39.6, 25.51, 0.584, 2.0, 30.0, 14.56, 20.03, 0.53, 29.0, 34.6, 0.33, 0.47, 1.0, 27.0, 14.12, -10.1, 1.0, 2.0, 27.0, 19.94, -21.03, 0.92029, 28.0, -22.58, -21.03, 0.07971, 3.0, 30.0, -2.08, -27.26, 0.29, 28.0, 35.31, 27.99, 0.49582, 29.0, -7.21, 27.99, 0.21418, 2.0, 30.0, 34.42, -39.19, 0.25, 28.0, 14.84, -4.5, 0.75, 2.0, 27.0, 34.87, 24.58, 0.67349, 28.0, -7.64, 24.58, 0.32651, 2.0, 30.0, 18.5, 1.59, 0.76, 29.0, 15.76, 1.0, 0.24 ], + "hull": 18, + "edges": [ 14, 12, 12, 10, 10, 8, 18, 20, 32, 34, 30, 32, 2, 4, 36, 4, 36, 38, 38, 40, 4, 6, 6, 8, 40, 6, 40, 42, 14, 16, 16, 18, 50, 16, 46, 52, 54, 36, 2, 0, 0, 34, 54, 0, 54, 32, 20, 50, 14, 56, 56, 42, 50, 56, 56, 58, 58, 40, 58, 10, 46, 60, 60, 48, 26, 60, 60, 44, 24, 26, 24, 48, 42, 62, 62, 44, 48, 62, 48, 64, 64, 50, 42, 64, 20, 22, 22, 24, 64, 22, 26, 28, 28, 30, 28, 46, 44, 66, 66, 54, 46, 66, 66, 36, 62, 38 ], + "width": 98.0, + "height": 180.0 + } + } + } + } +], +"events": { + "footstep": {} +}, +"animations": { + "aim": { + "slots": { + "crosshair": { + "attachment": [ + { "name": "crosshair" } + ] + } + }, + "bones": { + "front-bracer": { + "rotate": [ + { "value": 9.111553 } + ] + }, + "front-fist": { + "rotate": [ + { "value": 36.07917 } + ] + }, + "gun": { + "rotate": [ + { "value": -0.3051109 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": -26.552755 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "value": 62.30537 } + ] + } + }, + "ik": { + "aim-ik": [ + { "mix": 0.995 } + ] + }, + "transform": { + "aim-front-arm-transform": [ + { "mixRotate": 0.784 } + ], + "aim-head-transform": [ + { "mixRotate": 0.659 } + ], + "aim-torso-transform": [ + { "mixRotate": 0.423 } + ] + } + }, + "death": { + "slots": { + "eye": { + "attachment": [ + { "name": "eye-surprised" }, + { "time": 0.5333333, "name": "eye-indifferent" }, + { "time": 2.2, "name": "eye-surprised" }, + { "time": 4.6, "name": "eye-indifferent" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "name": "mouth-oooo" }, + { "time": 0.5333333, "name": "mouth-grind" }, + { "time": 1.4, "name": "mouth-oooo" }, + { "time": 2.166667, "name": "mouth-grind" }, + { "time": 4.533333, "name": "mouth-oooo" } + ] + } + }, + "bones": { + "back-foot-tip": { + "rotate": [ + { + "value": -0.2811985, + "curve": [ 8.212626E-5, -7.967849, 0.02724255, -18.69264 ] + }, + { + "time": 0.06666667, + "value": -18.99631, + "curve": [ 0.1659652, -19.30436, 0.20791964, 15.58339 ] + }, + { + "time": 0.2666667, + "value": 45.95023, + "curve": [ 0.3060278, 66.24353, 0.3775362, 99.08093 ] + }, + { + "time": 0.4333333, + "value": 99.08093, + "curve": [ 0.4966522, 98.61508, 0.4882892, -1.1972253 ] + }, + { + "time": 0.5666666, + "value": -1.3168106, + "curve": [ 0.6369079, -0.8404943, 0.6868753, 94.40564 ] + }, + { + "time": 0.7333333, + "value": 94.3284, + "curve": [ 0.8318345, 94.16463, 0.8951556, 29.59783 ] + }, + { + "time": 0.9666666, + "value": 28.666117, + "curve": [ 1.026319, 28.666117, 1.044541, 53.14217 ] + }, + { "time": 1.1, "value": 53.37511 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 21.88077, + "curve": [ 0.03333333, 21.88077, 0.09858582, 20.435394 ] + }, + { + "time": 0.13333334, + "value": 9.429705, + "curve": [ 0.16401745, -0.2889843, 0.16229573, -38.25987 ] + }, + { + "time": 0.2, + "value": -38.05125, + "curve": [ 0.239789, -37.9624, 0.2278192, -17.819233 ] + }, + { + "time": 0.3333333, + "value": -9.72551, + "curve": [ 0.3719403, -6.76407, 0.4312939, -0.7419243 ] + }, + { + "time": 0.4666667, + "value": 6.467783, + "curve": [ 0.4891468, 11.049698, 0.503116, 19.088676 ] + }, + { + "time": 0.5333333, + "value": 19.08868, + "curve": [ 0.5710945, 19.08868, 0.5543282, -42.67358 ] + }, + { + "time": 0.6, + "value": -42.67358, + "curve": [ 0.6526683, -42.67358, 0.6908418, -13.799316 ] + }, + { + "time": 0.7, + "value": -3.53628, + "curve": [ 0.7065422, 3.7950516, 0.719421, 24.93827 ] + }, + { + "time": 0.8, + "value": 25.30683, + "curve": [ 0.9015828, 24.746063, 0.9921238, -0.34114075 ] + }, + { "time": 1, "value": -32.16309, "curve": "stepped" }, + { + "time": 2.233333, + "value": -32.16309, + "curve": [ 2.6, -32.16309, 2.6377406, -5.295488 ] + }, + { + "time": 2.7, + "value": -1.9566765, + "curve": [ 2.707448, -1.557268, 2.775, 1.6656933 ] + }, + { + "time": 2.8, + "value": 1.6656933, + "curve": [ 2.825, 1.6656933, 2.875, -0.3915653 ] + }, + { + "time": 2.9, + "value": -0.3915653, + "curve": [ 2.925, -0.3915653, 2.975, 0.2594051 ] + }, + { + "time": 3, + "value": 0.2594051, + "curve": [ 3.025, 0.2594051, 3.075, -1.8061695 ] + }, + { + "time": 3.1, + "value": -1.8061695, + "curve": [ 3.125, -1.8061695, 3.175, -0.5175162 ] + }, + { + "time": 3.2, + "value": -0.5175162, + "curve": [ 3.225, -0.5175162, 3.275, -2.407952 ] + }, + { + "time": 3.3, + "value": -2.407952, + "curve": [ 3.333333, -2.407952, 3.4, -0.38046455 ] + }, + { + "time": 3.4333334, + "value": -0.38046455, + "curve": [ 3.466667, -0.38046455, 3.533333, -2.253333 ] + }, + { + "time": 3.5666666, + "value": -2.253333, + "curve": [ 3.591667, -2.253333, 3.641667, -0.3265362 ] + }, + { + "time": 3.666667, + "value": -0.3265362, + "curve": [ 3.7, -0.3265362, 3.766667, -1.3411007 ] + }, + { + "time": 3.8, + "value": -1.3411007, + "curve": [ 3.825, -1.3411007, 3.861913, -0.767765 ] + }, + { + "time": 3.9, + "value": -0.7731666, + "curve": [ 3.941953, -0.7668838, 3.990771, -1.4800053 ] + }, + { + "time": 4, + "value": -1.866457, + "curve": [ 4.166666, -1.866457, 4.5, -1.9566765 ] + }, + { + "time": 4.666666, + "value": -1.9566765, + "curve": [ 4.709497, 18.048933, 4.766667, 34.55217 ] + }, + { + "time": 4.8, + "value": 34.55217, + "curve": [ 4.839665, 34.24439, 4.901583, 12.027884 ] + }, + { "time": 4.933333, "value": -18.749977 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -2.333191, + "curve": [ 0.018520074, 4.426531, 0.06852007, 10.824462 ] + }, + { + "time": 0.1, + "value": 10.599137, + "curve": [ 0.14767976, 10.599137, 0.12264546, -15.241027 ] + }, + { + "time": 0.2, + "value": -15.346755, + "curve": [ 0.2663191, -15.4374, 0.3159685, -6.48421 ] + }, + { + "time": 0.3333333, + "value": -3.89693, + "curve": [ 0.36239055, 0.432456, 0.4787541, 22.36063 ] + }, + { + "time": 0.5666666, + "value": 22.010826, + "curve": [ 0.6100949, 21.83802, 0.6272623, 12.848224 ] + }, + { + "time": 0.6333333, + "value": 9.047508, + "curve": [ 0.6433533, 2.774735, 0.6223488, -39.42856 ] + }, + { + "time": 0.7, + "value": -39.49933, + "curve": [ 0.7731914, -39.56604, 0.8138696, 14.771628 ] + }, + { + "time": 0.8666667, + "value": 14.809445, + "curve": [ 0.9652192, 14.88003, 1.1, 5.635015 ] + }, + { "time": 1.1, "value": -6.07953, "curve": "stepped" }, + { + "time": 2.233333, + "value": -6.07953, + "curve": [ 2.3068335, -6.07953, 2.4266386, -25.88878 ] + }, + { + "time": 2.533333, + "value": -22.42055, + "curve": [ 2.597695, -20.383656, 2.6568334, 5.728967 ] + }, + { + "time": 2.7, + "value": 5.728967, + "curve": [ 2.770472, 5.728967, 2.8510454, -5.377005 ] + }, + { + "time": 2.9333334, + "value": -5.377005, + "curve": [ 3.00755, -5.377005, 3.0867045, -4.539953 ] + }, + { + "time": 3.166667, + "value": -4.165549, + "curve": [ 3.222622, -3.912559, 4.485574, 5.728966 ] + }, + { + "time": 4.666666, + "value": 5.728966, + "curve": [ 4.733333, 5.728966, 4.885902, -2.474717 ] + }, + { "time": 4.933333, "value": -6.523767 } + ] + }, + "front-foot": { + "rotate": [ + { + "curve": [ 0.008333334, -11.325378, 0.10833333, -57.71149 ] + }, + { + "time": 0.13333334, + "value": -57.71149, + "curve": [ 0.175, -57.71149, 0.22882803, 19.72928 ] + }, + { + "time": 0.3, + "value": 19.34176, + "curve": [ 0.3539871, 19.34176, 0.4, -57.76014 ] + }, + { + "time": 0.4333333, + "value": -57.76014, + "curve": [ 0.4583333, -57.76014, 0.510723, -3.5613594 ] + }, + { + "time": 0.5333333, + "value": 3.698765, + "curve": [ 0.5631978, 13.288166, 0.6333333, 15.792763 ] + }, + { + "time": 0.6666667, + "value": 15.792763, + "curve": [ 0.7, 15.792763, 0.7666666, -48.75049 ] + }, + { + "time": 0.8, + "value": -48.75049, + "curve": [ 0.8416666, -48.75049, 0.925, 4.704307 ] + }, + { + "time": 0.9666666, + "value": 4.704307, + "curve": [ 1, 4.704307, 1.0666667, -22.89701 ] + }, + { + "time": 1.1, + "value": -22.89701, + "curve": [ 1.1416667, -22.89701, 1.225, -13.27708 ] + }, + { "time": 1.2666667, "value": -13.27708 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -0.2811985, + "curve": [ 0.008333334, -0.2811985, 0.002817385, -66.61513 ] + }, + { + "time": 0.06666667, + "value": -65.75365, + "curve": [ 0.16552, -64.41987, 0.2337835, 14.352765 ] + }, + { + "time": 0.2666667, + "value": 38.24919, + "curve": [ 0.2937184, 57.90787, 0.3924242, 89.78588 ] + }, + { + "time": 0.4666667, + "value": 90.73152, + "curve": [ 0.4833333, 90.73152, 0.55, 177.66196 ] + }, + { + "time": 0.5666666, + "value": 177.66196, + "curve": [ 0.7326745, 176.2435, 0.75, 11.348257 ] + }, + { + "time": 0.8, + "value": 11.348257, + "curve": [ 0.8859025, 12.29389, 0.9114622, 47.87824 ] + }, + { + "time": 0.9333333, + "value": 56.76897, + "curve": [ 0.967334, 70.59048, 1.05, 86.4574 ] + }, + { + "time": 1.1, + "value": 86.4574, + "curve": [ 1.186726, 86.4574, 1.2140645, 66.44207 ] + }, + { "time": 1.3333334, "value": 64.5508 } + ] + }, + "front-shin": { + "rotate": [ + { + "curve": [ 0.08635836, -0.01806736, 0.19055387, -24.251423 ] + }, + { + "time": 0.2, + "value": -26.49584, + "curve": [ 0.21439336, -29.91574, 0.24939965, -40.50952 ] + }, + { + "time": 0.3333333, + "value": -40.57034, + "curve": [ 0.4313408, -40.70344, 0.4589271, -11.343845 ] + }, + { + "time": 0.4666667, + "value": -8.71192, + "curve": [ 0.4771134, -5.159385, 0.5239128, 17.1284 ] + }, + { + "time": 0.6, + "value": 16.98232, + "curve": [ 0.6317624, 17.085365, 0.625, 2.764457 ] + }, + { + "time": 0.6333333, + "value": 2.764458, + "curve": [ 0.6484549, 2.764458, 0.652977, 2.74659 ] + }, + { + "time": 0.6666667, + "value": 2.591426, + "curve": [ 0.6784885, 2.385952, 0.7333333, 2.531887 ] + }, + { + "time": 0.7333333, + "value": -9.426415, + "curve": [ 0.7452463, -2.476608, 0.7820335, 3.124748 ] + }, + { + "time": 0.8, + "value": 4.278675, + "curve": [ 0.8318292, 6.322961, 0.895421, 8.461233 ] + }, + { + "time": 0.9333333, + "value": 8.49048, + "curve": [ 0.9860933, 8.531183, 1.0511496, 6.381635 ] + }, + { + "time": 1.0666667, + "value": 2.28483, + "curve": [ 1.078323, 4.166202, 1.1031494, 5.861723 ] + }, + { + "time": 1.1333333, + "value": 5.884948, + "curve": [ 1.1908875, 5.92923, 1.208822, 4.560581 ] + }, + { "time": 1.2333333, "value": 2.524644 } + ] + }, + "front-thigh": { + "rotate": [ + { + "curve": [ 0.05976329, 1.0151215, 0.1509999, 45.23327 ] + }, + { + "time": 0.16666667, + "value": 54.00554, + "curve": [ 0.18961367, 66.85423, 0.3579875, 169.85176 ] + }, + { + "time": 0.5, + "value": 169.5134, + "curve": [ 0.6275878, 169.85176, 0.6924103, 108.84532 ] + }, + { + "time": 0.7, + "value": 97.73543, + "curve": [ 0.7232997, 102.60121, 0.805322, 111.5996 ] + }, + { + "time": 0.8666667, + "value": 111.69462, + "curve": [ 0.8991471, 111.82616, 1.0152105, 109.1455 ] + }, + { "time": 1.0666667, "value": 95.79772 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -38.85507, + "curve": [ 0.02192639, -40.37515, 0.09562777, -41.91797 ] + }, + { + "time": 0.13333334, + "value": -41.91797, + "curve": [ 0.1762986, -41.91798, 0.2164709, -16.920395 ] + }, + { + "time": 0.23333333, + "value": -4.34639, + "curve": [ 0.2575247, 13.692627, 0.3075902, 60.34659 ] + }, + { + "time": 0.4, + "value": 60.16684, + "curve": [ 0.4959516, 59.98024, 0.538565, 33.62846 ] + }, + { + "time": 0.5666666, + "value": 23.061996, + "curve": [ 0.5945549, 32.71104, 0.6754874, 53.71147 ] + }, + { + "time": 0.7333333, + "value": 53.61354, + "curve": [ 0.7969134, 53.50589, 0.926482, 30.978836 ] + }, + { "time": 0.9333333, "value": 19.57402, "curve": "stepped" }, + { + "time": 1.9666667, + "value": 19.57402, + "curve": [ 2.245216, 19.57402, 2.7021875, 77.025 ] + }, + { + "time": 3.0666666, + "value": 77.0602, + "curve": [ 3.208887, 77.32796, 3.291069, 67.99296 ] + }, + { + "time": 3.4333334, + "value": 67.9596, + "curve": [ 3.608477, 68.3418, 3.7293816, 73.87673 ] + }, + { + "time": 3.833333, + "value": 73.41716, + "curve": [ 4.152479, 73.91438, 4.460341, 71.98025 ] + }, + { + "time": 4.633333, + "value": 64.76924, + "curve": [ 4.687792, 62.49916, 4.846802, 26.42305 ] + }, + { "time": 4.866667, "value": 10.94069 } + ] + }, + "gun": { + "rotate": [ + { + "value": -2.788574, + "curve": [ 0.03333333, -2.788574, 0.11987463, -7.215712 ] + }, + { + "time": 0.13333334, + "value": -8.516563, + "curve": [ 0.16800457, -11.867717, 0.2902747, -23.711977 ] + }, + { + "time": 0.3333333, + "value": -26.241997, + "curve": [ 0.368596, -28.313953, 0.4355997, -29.74596 ] + }, + { + "time": 0.5, + "value": -29.65575, + "curve": [ 0.552479, -29.58224, 0.611462, -25.47485 ] + }, + { + "time": 0.6333333, + "value": -22.68271, + "curve": [ 0.6562596, -19.7559, 0.67987, -10.02117 ] + }, + { + "time": 0.7, + "value": -6.485645, + "curve": [ 0.7221142, -2.601631, 0.75, -1.21659 ] + }, + { + "time": 0.7666666, + "value": -1.350212, + "curve": [ 0.7916667, -1.5506454, 0.8416666, -19.737776 ] + }, + { "time": 0.8666667, "value": -19.7968 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.04689246, -0.2130623, 0.04790161, 7.863083 ] + }, + { + "time": 0.06666667, + "value": 13.272148, + "curve": [ 0.08325758, 18.054514, 0.13504568, 24.44309 ] + }, + { + "time": 0.2, + "value": 24.01697, + "curve": [ 0.225, 24.01697, 0.2803424, 6.321228 ] + }, + { + "time": 0.3, + "value": 3.1026344, + "curve": [ 0.3225088, -0.5827751, 0.3818797, -7.121094 ] + }, + { + "time": 0.4666667, + "value": -7.447723, + "curve": [ 0.5115855, -7.655552, 0.5376558, 12.13205 ] + }, + { + "time": 0.5666666, + "value": 16.46309, + "curve": [ 0.6085693, 22.718737, 0.6716594, 27.3962 ] + }, + { + "time": 0.7333333, + "value": 27.54968, + "curve": [ 0.8266793, 27.3962, 0.932931, 23.22974 ] + }, + { + "time": 0.9666666, + "value": 19.106976, + "curve": [ 0.9980442, 15.272388, 1.0916667, -2.528984 ] + }, + { + "time": 1.1333333, + "value": -2.528984, + "curve": [ 1.1583333, -2.528984, 1.2083334, 0 ] + }, + { "time": 1.2333333, "curve": "stepped" }, + { + "time": 2, + "curve": [ 2.075, 0, 2.247674, 0.3461227 ] + }, + { + "time": 2.333333, + "value": 0.7803421, + "curve": [ 2.584982, 2.055981, 2.8047395, 3.4637756 ] + }, + { + "time": 3.2, + "value": 3.503952, + "curve": [ 3.5925975, 3.543865, 3.9791405, 2.3555145 ] + }, + { + "time": 4.166666, + "value": 1.553379, + "curve": [ 4.39082, 0.594574, 4.447003, 0.0361824 ] + }, + { + "time": 4.6, + "value": 0.0361824, + "curve": [ 4.641668, 0.0361824, 4.741667, 0 ] + }, + { "time": 4.933333 } + ] + }, + "hair2": { + "rotate": [ + { + "value": 10.609882, + "curve": [ 0.075, 10.609882, 0.05, 12.669956 ] + }, + { + "time": 0.06666667, + "value": 12.669956, + "curve": [ 0.1233677, 12.669956, 0.19394414, -16.505566 ] + }, + { + "time": 0.2, + "value": -19.86787, + "curve": [ 0.20651405, -23.48457, 0.23617338, -31.682863 ] + }, + { + "time": 0.3, + "value": -31.80027, + "curve": [ 0.3564386, -31.90409, 0.4369411, -25.611557 ] + }, + { + "time": 0.4666667, + "value": -19.291225, + "curve": [ 0.485298, -15.329792, 0.5289479, 6.481163 ] + }, + { + "time": 0.5666666, + "value": 6.667576, + "curve": [ 0.6279005, 6.970203, 0.6498716, -46.39313 ] + }, + { + "time": 0.7333333, + "value": -46.29858, + "curve": [ 0.8430756, -46.17424, 0.9410482, -33.36858 ] + }, + { + "time": 0.9666666, + "value": -23.173223, + "curve": [ 0.9721882, -20.975813, 1.0466495, 15.210228 ] + }, + { + "time": 1.1, + "value": 15.210228, + "curve": [ 1.1416667, 15.210228, 1.182938, 10.734215 ] + }, + { + "time": 1.2666667, + "value": 10.609882, + "curve": [ 1.45, 10.337642, 1.8166667, 10.609882 ] + }, + { + "time": 2, + "value": 10.609882, + "curve": [ 2.075, 10.609882, 2.225, 16.90288 ] + }, + { + "time": 2.3, + "value": 16.90288, + "curve": [ 2.3271945, 16.90288, 2.346594, 6.813179 ] + }, + { + "time": 2.4, + "value": 6.834305, + "curve": [ 2.492377, 6.870834, 2.6021945, 17.392544 ] + }, + { + "time": 2.666667, + "value": 17.392544, + "curve": [ 2.7416666, 17.392544, 2.8916986, 10.665386 ] + }, + { + "time": 2.966667, + "value": 10.640583, + "curve": [ 3.186902, 10.56771, 3.343602, 10.731342 ] + }, + { + "time": 3.6, + "value": 11.39581, + "curve": [ 3.7658195, 11.825535, 3.873757, 14.87431 ] + }, + { + "time": 3.9333334, + "value": 14.827503, + "curve": [ 4.022158, 14.75772, 4.208427, 9.491276 ] + }, + { + "time": 4.3, + "value": 9.53775, + "curve": [ 4.391111, 9.583996, 4.44072, 14.816524 ] + }, + { + "time": 4.533333, + "value": 14.84467, + "curve": [ 4.642342, 14.877789, 4.692117, 1.173443 ] + }, + { + "time": 4.766667, + "value": 1.2434273, + "curve": [ 4.822706, 1.2960372, 4.818161, 18.354725 ] + }, + { + "time": 4.866667, + "value": 18.384907, + "curve": [ 4.904529, 18.40846, 4.901352, 10.607553 ] + }, + { "time": 4.933333, "value": 10.609882 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0, 0, 0.04056912, 10.74298 ] + }, + { + "time": 0.06666667, + "value": 14.15986, + "curve": [ 0.07479883, 15.224585, 0.14791566, 18.036913 ] + }, + { + "time": 0.2, + "value": 18.13369, + "curve": [ 0.2513522, 18.229107, 0.3068256, -4.75262 ] + }, + { + "time": 0.3666667, + "value": -5.062149, + "curve": [ 0.41201925, -5.296737, 0.4698103, -0.9579954 ] + }, + { + "time": 0.5, + "value": 2.209665, + "curve": [ 0.5121224, 3.4816265, 0.5948224, 20.305944 ] + }, + { + "time": 0.6333333, + "value": 24.8722, + "curve": [ 0.6472809, 26.525967, 0.7191794, 29.326023 ] + }, + { + "time": 0.8, + "value": 29.219383, + "curve": [ 0.8586156, 29.142044, 0.9000327, 28.480516 ] + }, + { + "time": 0.9333333, + "value": 26.11037, + "curve": [ 0.9809244, 22.72311, 0.9980939, 2.056135 ] + }, + { "time": 1.1, "value": 2.209665 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.011168385, 4.50322, 0.05, 11.416817 ] + }, + { + "time": 0.06666667, + "value": 11.416817, + "curve": [ 0.1, 11.416817, 0.1361588, -5.918403 ] + }, + { + "time": 0.16666667, + "value": -10.537537, + "curve": [ 0.20614353, -16.514656, 0.3274886, -21.9986 ] + }, + { + "time": 0.3666667, + "value": -24.471233, + "curve": [ 0.41259405, -27.36985, 0.4666667, -43.9946 ] + }, + { + "time": 0.5, + "value": -43.9946, + "curve": [ 0.5333333, -43.9946, 0.5522224, 12.119652 ] + }, + { + "time": 0.6333333, + "value": 11.853188, + "curve": [ 0.7141786, 11.587608, 0.7583333, -34.13222 ] + }, + { + "time": 0.8, + "value": -34.13222, + "curve": [ 0.8583333, -34.13222, 1.0149958, -12.471024 ] + }, + { + "time": 1.0666667, + "value": -8.848976, + "curve": [ 1.1205677, -5.070595, 1.219171, -0.015052795 ] + }, + { + "time": 1.3333334, + "value": 1.2907867, + "curve": [ 1.508893, 3.2989044, 1.7627754, 2.7490234 ] + }, + { + "time": 1.8666667, + "value": 2.776871, + "curve": [ 1.974238, 2.805704, 2.1083546, 2.808632 ] + }, + { + "time": 2.2, + "value": 2.776871, + "curve": [ 2.315253, 2.736931, 2.3741815, 1.219162 ] + }, + { + "time": 2.466667, + "value": 1.179222, + "curve": [ 2.525, 1.179222, 2.608333, 10.794548 ] + }, + { + "time": 2.666667, + "value": 10.794548, + "curve": [ 2.725, 10.794548, 2.893151, 4.721054 ] + }, + { + "time": 3.033333, + "value": 4.721054, + "curve": [ 3.1166666, 4.721054, 3.283333, 7.932075 ] + }, + { + "time": 3.3666666, + "value": 7.932075, + "curve": [ 3.4916666, 7.932075, 3.775, 6.927864 ] + }, + { + "time": 3.9, + "value": 6.927864, + "curve": [ 3.9809444, 6.927864, 4.09364, 6.897201 ] + }, + { + "time": 4.2, + "value": 8.442413, + "curve": [ 4.267491, 9.422943, 4.401258, 16.605806 ] + }, + { + "time": 4.5, + "value": 16.33462, + "curve": [ 4.581609, 16.11781, 4.708941, 9.9449 ] + }, + { + "time": 4.733333, + "value": 6.5066, + "curve": [ 4.747063, 4.571221, 4.779032, -1.7636824 ] + }, + { + "time": 4.8, + "value": -1.7486115, + "curve": [ 4.823359, -1.7325964, 4.819983, 4.467903 ] + }, + { + "time": 4.866667, + "value": 6.043281, + "curve": [ 4.899199, 7.141105, 4.912722, 6.927864 ] + }, + { "time": 4.933333, "value": 6.927864 } + ] + }, + "head": { + "rotate": [ + { + "value": -2.827988, + "curve": [ 0.015444444, -2.827988, 0.03569071, 12.719316 ] + }, + { + "time": 0.06666667, + "value": 12.186468, + "curve": [ 0.0960013, 11.681858, 0.11911735, -1.144228 ] + }, + { + "time": 0.13333334, + "value": -6.858564, + "curve": [ 0.14927696, -13.267348, 0.21048637, -37.27945 ] + }, + { + "time": 0.3, + "value": -36.86384, + "curve": [ 0.3539913, -36.61315, 0.4120227, -32.35048 ] + }, + { + "time": 0.4666667, + "value": -23.489603, + "curve": [ 0.4899489, -19.87037, 0.5120964, -3.287432 ] + }, + { + "time": 0.5333333, + "value": -3.237766, + "curve": [ 0.5596176, -3.3898296, 0.6143611, -67.24913 ] + }, + { + "time": 0.6333333, + "value": -74.40298, + "curve": [ 0.6523558, -81.5758, 0.7021659, -88.9422 ] + }, + { + "time": 0.7333333, + "value": -88.93178, + "curve": [ 0.8048823, -88.90787, 0.8380167, -80.87495 ] + }, + { + "time": 0.8666667, + "value": -81.02708, + "curve": [ 0.9216276, -81.3189, 0.9755556, -85.28828 ] + }, + { "time": 1, "value": -85.28828, "curve": "stepped" }, + { + "time": 2.233333, + "value": -85.28828, + "curve": [ 2.3143334, -85.28828, 2.382326, -68.06154 ] + }, + { + "time": 2.466667, + "value": -63.48384, + "curve": [ 2.5701094, -57.86936, 2.9157326, -55.24182 ] + }, + { + "time": 3.2, + "value": -55.10316, + "curve": [ 3.447132, -54.98262, 4.134757, -56.60572 ] + }, + { + "time": 4.266667, + "value": -58.2344, + "curve": [ 4.67212, -63.24052, 4.64639, -82.6929 ] + }, + { "time": 4.933333, "value": -85.28828 } + ], + "scale": [ + { + "time": 0.4666667, + "curve": [ 0.469, 1.005, 0.4916667, 1.065, 0.475, 1.0178572, 0.4916667, 0.94 ] + }, + { + "time": 0.5, + "x": 1.065, + "y": 0.94, + "curve": [ 0.5166666, 1.065, 0.5410837, 0.9910153, 0.5166666, 0.94, 0.5423501, 1.0256574 ] + }, + { + "time": 0.5666666, + "x": 0.9895735, + "y": 1.0247642, + "curve": [ 0.5933727, 0.9880685, 0.6089288, 1.001505, 0.5948418, 1.0237292, 0.6074599, 1.0010352 ] + }, + { "time": 0.6333333 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.025, 0, 0.08982687, 1.433876, 0.025, 0, 0.075, -34.76472 ] + }, + { + "time": 0.1, + "x": 1.5892944, + "y": -34.76472, + "curve": [ 0.2139062, 3.3294754, 0.375, 5.335235, 0.19166666, -34.76472, 0.4413305, -21.16603 ] + }, + { + "time": 0.4666667, + "x": 5.335235, + "y": -12.572044, + "curve": [ 0.4916667, 5.335235, 0.5497855, 5.235496, 0.482024, -7.362872, 0.5036168, 4.027279 ] + }, + { + "time": 0.5666666, + "x": 5.112495, + "y": 4.00758, + "curve": [ 0.6580276, 4.446754, 0.6791785, 3.194435, 0.6491876, 3.9818, 0.6417333, -16.840157 ] + }, + { + "time": 0.7, + "x": 2.7987366, + "y": -16.74048, + "curve": [ 0.7865131, 1.1546326, 0.880658, -1.2923965, 0.772064, -16.6172, 0.819524, 8.945714 ] + }, + { + "time": 0.9, + "x": -1.721161, + "y": 8.90686, + "curve": [ 0.9605302, -3.062973, 1.025, -3.5791626, 0.974895, 8.870702, 0.9505928, -1.371925 ] + }, + { + "time": 1.1, + "x": -3.5791626, + "y": -1.4544678, + "curve": [ 1.2916666, -3.5791626, 2.001765, -2.4029236, 1.291651, -1.5603487, 1.975, -1.4544678 ] + }, + { + "time": 2.166667, + "x": -1.3947296, + "y": -1.4544678, + "curve": [ 2.250246, -0.8837433, 2.503161, 1.3765717, 2.283333, -1.4544678, 2.6026855, -12.435727 ] + }, + { + "time": 2.666667, + "x": 2.132713, + "y": -14.44743, + "curve": [ 2.7657926, 2.5911255, 2.998697, 2.812721, 2.834681, -19.73016, 3.002592, -25.203335 ] + }, + { + "time": 3.1333334, + "x": 2.9122925, + "y": -26.08423, + "curve": [ 3.391734, 3.1033936, 4.198695, 4.047333, 3.48327, -28.441994, 4.12858, -27.230576 ] + }, + { + "time": 4.366667, + "x": 4.813339, + "y": -19.586075, + "curve": [ 4.429278, 5.098861, 4.593682, 8.53765, 4.538166, -14.079535, 4.583333, -7.87503 ] + }, + { + "time": 4.666666, + "x": 8.654564, + "y": -4.557136, + "curve": [ 4.793823, 8.85827, 4.805771, 5.925122, 4.690854, -3.594114, 4.800488, -1.6082137 ] + }, + { "time": 4.933333, "x": 5.803871, "y": -1.9929583 } + ] + }, + "hip": { + "translate": [ + { + "curve": [ 0.09774662, -42.62397, 0.16644298, -79.8482, 0.028903656, 84.97473, 0.1091842, 155.92613 ] + }, + { + "time": 0.2666667, + "x": -133.79216, + "y": 152.4395, + "curve": [ 0.3611138, -184.62695, 0.3924851, -203.6922, 0.42022145, 149.1156, 0.4666667, -15.698044 ] + }, + { + "time": 0.4666667, + "x": -230.0192, + "y": -113.87448, + "curve": [ 0.5225717, -249.85983, 0.5651282, -261.7036, 0.4733397, -133.10252, 0.5833333, -203.43018 ] + }, + { + "time": 0.6, + "x": -268.57, + "y": -203.43018, + "curve": [ 0.6630102, -280.97705, 0.8163472, -290.0504, 0.7083333, -203.43018, 0.8916666, -203.4962 ] + }, + { "time": 1, "x": -290.41855, "y": -203.4962 } + ] + }, + "neck": { + "rotate": [ + { + "value": -2.827988, + "curve": [ 0.11415303, 1.3304386, 0.194984, 4.130054 ] + }, + { + "time": 0.2666667, + "value": 4.132889, + "curve": [ 0.3512333, 4.13624, 0.4440456, -24.501444 ] + }, + { + "time": 0.5, + "value": -24.686066, + "curve": [ 0.570637, -23.89392, 0.5499004, 34.22126 ] + }, + { + "time": 0.6666667, + "value": 35.12734, + "curve": [ 0.713132, 34.81157, 0.7555716, 22.7647 ] + }, + { + "time": 0.8333333, + "value": 22.81864, + "curve": [ 0.8679167, 22.842625, 0.9156492, 47.94965 ] + }, + { "time": 0.9666666, "value": 47.94965, "curve": "stepped" }, + { + "time": 2.233333, + "value": 47.94965, + "curve": [ 2.3, 47.94965, 2.6166525, 18.71746 ] + }, + { + "time": 2.666667, + "value": 18.505486, + "curve": [ 3.171996, 16.579683, 4.060461, 16.790627 ] + }, + { + "time": 4.533333, + "value": 18.505486, + "curve": [ 4.706526, 19.133564, 4.775889, 41.10513 ] + }, + { "time": 4.8, "value": 47.94965 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.362316, + "curve": [ 0.03333333, 10.362316, 0.1, -32.88954 ] + }, + { + "time": 0.13333334, + "value": -32.88954, + "curve": [ 0.18333334, -32.88954, 0.2833333, -4.45478 ] + }, + { + "time": 0.3333333, + "value": -4.45478, + "curve": [ 0.3666667, -4.45478, 0.4379563, -6.86408 ] + }, + { + "time": 0.4666667, + "value": -8.989485, + "curve": [ 0.5292276, -13.620812, 0.6053304, -20.580513 ] + }, + { + "time": 0.6333333, + "value": -23.20364, + "curve": [ 0.7078339, -30.182356, 0.7583333, -35.55501 ] + }, + { + "time": 0.8, + "value": -35.55501, + "curve": [ 0.875, -35.55501, 1.025, -23.20364 ] + }, + { "time": 1.1, "value": -23.20364 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -0.2811966, + "curve": [ 0.03333333, -0.2811966, 0.256232, -66.7055 ] + }, + { + "time": 0.3666667, + "value": -66.84443, + "curve": [ 0.4184119, -66.90952, 0.4985725, -21.794205 ] + }, + { + "time": 0.6, + "value": -21.5233, + "curve": [ 0.6519168, -21.38463, 0.6645703, -53.96108 ] + }, + { + "time": 0.7, + "value": -54.26296, + "curve": [ 0.7574644, -53.96108, 0.8429435, -2.072342 ] + }, + { + "time": 0.9333333, + "value": -1.4685898, + "curve": [ 0.9684307, -2.072342, 0.9754344, -19.96207 ] + }, + { + "time": 1, + "value": -19.96207, + "curve": [ 1.025, -19.96207, 1.075, -12.420547 ] + }, + { + "time": 1.1, + "value": -12.420547, + "curve": [ 1.1333333, -12.420547, 1.2, -18.34373 ] + }, + { "time": 1.2333333, "value": -18.34373 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": -0.2811985 } + ] + }, + "rear-shin": { + "rotate": [ + { + "curve": [ 0.02134387, -16.65366, 0.09115682, -54.81634 ] + }, + { + "time": 0.16666667, + "value": -55.28844, + "curve": [ 0.1869984, -55.41556, 0.2134717, -52.51734 ] + }, + { + "time": 0.23333333, + "value": -45.98236, + "curve": [ 0.2420925, -43.10037, 0.3105709, -12.726774 ] + }, + { + "time": 0.3333333, + "value": -6.317261, + "curve": [ 0.3562187, 0.12688255, 0.4666666, 24.495005 ] + }, + { + "time": 0.5, + "value": 24.495005, + "curve": [ 0.5425889, 24.495005, 0.5597089, 3.782467 ] + }, + { + "time": 0.5666666, + "value": -3.525984, + "curve": [ 0.5851009, 3.8576965, 0.6593201, 16.627193 ] + }, + { + "time": 0.7, + "value": 16.561085, + "curve": [ 0.7823284, 16.42729, 0.896085, 8.43845 ] + }, + { + "time": 0.9333333, + "value": 4.041226, + "curve": [ 0.9562264, 6.836118, 1.0083333, 8.41251 ] + }, + { + "time": 1.0333333, + "value": 8.41251, + "curve": [ 1.0666667, 8.41251, 1.1224273, 8.136743 ] + }, + { "time": 1.1666666, "value": 5.799962 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "curve": [ 0.03333333, 0, 0.12001532, 50.26316 ] + }, + { + "time": 0.13333334, + "value": 57.30254, + "curve": [ 0.16367698, 73.341, 0.2737021, 147.17735 ] + }, + { + "time": 0.3333333, + "value": 147.10303, + "curve": [ 0.47515625, 146.44525, 0.582564, 95.71753 ] + }, + { + "time": 0.6, + "value": 79.66113, + "curve": [ 0.6198274, 94.74216, 0.7321241, 103.15384 ] + }, + { + "time": 0.7666666, + "value": 103.02254, + "curve": [ 0.8121768, 102.84955, 0.8968627, 95.74734 ] + }, + { "time": 0.9333333, "value": 83.01085 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": -44.69556, + "curve": [ 0.03333333, -44.69556, 0.1197083, 54.88644 ] + }, + { + "time": 0.13333334, + "value": 64.6217, + "curve": [ 0.1537096, 79.18082, 0.2141258, 79.4221 ] + }, + { + "time": 0.2666667, + "value": 63.39506, + "curve": [ 0.2927642, 55.18524, 0.3318916, 30.12935 ] + }, + { + "time": 0.3666667, + "value": 30.12935, + "curve": [ 0.40001765, 30.12935, 0.4412998, 39.87414 ] + }, + { + "time": 0.4666667, + "value": 55.12625, + "curve": [ 0.48838425, 68.18418, 0.5204052, 100.72226 ] + }, + { + "time": 0.5333333, + "value": 111.95866, + "curve": [ 0.550502, 126.88067, 0.627324, 185.96957 ] + }, + { + "time": 0.6666667, + "value": 185.96957, + "curve": [ 0.6916667, 185.96957, 0.7357943, 162.4288 ] + }, + { + "time": 0.8, + "value": 158.0067, + "curve": [ 0.9000576, 151.11525, 1.0166667, 144.0128 ] + }, + { "time": 1.1, "value": 144.0128, "curve": "stepped" }, + { + "time": 2.3666666, + "value": 144.0128, + "curve": [ 2.4916666, 144.0128, 2.7416666, 138.6282 ] + }, + { + "time": 2.8666666, + "value": 138.6282, + "curve": [ 3.0666666, 138.6282, 3.466667, 138.63403 ] + }, + { + "time": 3.666667, + "value": 138.63403, + "curve": [ 3.8833334, 138.63403, 4.316666, 135.18347 ] + }, + { + "time": 4.533333, + "value": 135.18347, + "curve": [ 4.575, 135.18347, 4.691666, 131.594 ] + }, + { + "time": 4.733333, + "value": 131.594, + "curve": [ 4.758333, 131.594, 4.516667, 144.0128 ] + }, + { "time": 4.833333, "value": 144.0128 } + ], + "translate": [ + { + "time": 0.4666667, + "curve": [ 0.5166666, 0, 0.6166667, -34.96278, 0.5166666, 0, 0.6166667, -16.58711 ] + }, + { "time": 0.6666667, "x": -35.02248, "y": -16.61543 } + ] + }, + "torso": { + "rotate": [ + { + "value": -8.61538, + "curve": [ 0.010259143, -16.71203, 0.03222887, -33.60068 ] + }, + { + "time": 0.06666667, + "value": -33.37212, + "curve": [ 0.18178344, -32.60808, 0.2976945, 123.07062 ] + }, + { + "time": 0.4666667, + "value": 122.77002, + "curve": [ 0.5109518, 122.69125, 0.5204181, 100.20042 ] + }, + { + "time": 0.5666666, + "value": 88.9638, + "curve": [ 0.5875576, 83.8881, 0.6666667, 75.34303 ] + }, + { + "time": 0.7, + "value": 75.34303, + "curve": [ 0.7666666, 75.34303, 0.9, 76.03314 ] + }, + { "time": 0.9666666, "value": 76.03314 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.04833333, 0, 0.12943684, -12.732102 ] + }, + { + "time": 0.16666667, + "value": -15.947126, + "curve": [ 0.22118534, -20.65514, 0.2544313, -21.62372 ] + }, + { + "time": 0.3, + "value": -21.586037, + "curve": [ 0.457501, -21.45581, 0.4595645, -1.671394 ] + }, + { + "time": 0.6333333, + "value": -1.709037, + "curve": [ 0.7095563, -1.7255486, 0.7151743, -4.000723 ] + }, + { + "time": 0.7666666, + "value": -3.972734, + "curve": [ 0.8663324, -3.918559, 0.839921, 0.016319573 ] + }, + { "time": 1, "curve": "stepped" }, + { + "time": 2, + "curve": [ 2.275, 0, 2.8669045, -5.797145 ] + }, + { + "time": 3.1, + "value": -6.437279, + "curve": [ 3.327306, -7.06151, 3.7103264, -6.232035 ] + }, + { + "time": 3.9333334, + "value": -5.405311, + "curve": [ 4.168433, -4.533755, 4.488472, -2.8298516 ] + }, + { "time": 4.8 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.025, 0, 0.09008592, -3.655975 ] + }, + { + "time": 0.1, + "value": -4.551666, + "curve": [ 0.14257246, -8.397885, 0.22345562, -17.0685 ] + }, + { + "time": 0.23333333, + "value": -18.311, + "curve": [ 0.2820652, -24.44091, 0.35017, -28.99538 ] + }, + { + "time": 0.3666667, + "value": -30.06988, + "curve": [ 0.4051797, -32.57841, 0.4417323, -33.03234 ] + }, + { + "time": 0.4666667, + "value": -32.98805, + "curve": [ 0.4914639, -33.04064, 0.5048738, -23.56439 ] + }, + { + "time": 0.5333333, + "value": -23.546326, + "curve": [ 0.5708778, -23.66542, 0.5987943, -27.20989 ] + }, + { + "time": 0.6333333, + "value": -27.20665, + "curve": [ 0.669014, -27.203304, 0.742272, -10.42768 ] + }, + { + "time": 0.7666666, + "value": -7.788528, + "curve": [ 0.7875314, -5.531253, 0.7960346, -4.417817 ] + }, + { + "time": 0.8333333, + "value": -2.901961, + "curve": [ 0.874938, -1.2111093, 0.9333333, 0 ] + }, + { "time": 0.9666666, "curve": "stepped" }, + { + "time": 2.4333334, + "curve": [ 2.516667, 0, 2.6833556, 4.630115 ] + }, + { + "time": 2.766667, + "value": 4.656875, + "curve": [ 3.084372, 4.758941, 3.248143, 4.367768 ] + }, + { + "time": 3.4, + "value": 3.736271, + "curve": [ 3.596353, 2.919743, 3.754788, 2.181887 ] + }, + { + "time": 3.8666666, + "value": 1.7159004, + "curve": [ 4.136221, 0.593175, 4.471063, 0 ] + }, + { "time": 4.8 } + ] + } + }, + "ik": { + "front-foot-ik": [ + { "mix": 0 } + ], + "front-leg-ik": [ + { "mix": 0, "bendPositive": false } + ], + "rear-foot-ik": [ + { "mix": 0.005 } + ], + "rear-leg-ik": [ + { "mix": 0.005, "bendPositive": false } + ] + } + }, + "hoverboard": { + "slots": { + "exhaust1": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "exhaust2": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "exhaust3": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "hoverboard-board": { + "attachment": [ + { "name": "hoverboard-board" } + ] + }, + "hoverboard-thruster-front": { + "attachment": [ + { "name": "hoverboard-thruster" } + ] + }, + "hoverboard-thruster-rear": { + "attachment": [ + { "name": "hoverboard-thruster" } + ] + }, + "hoverglow-front": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "hoverglow-rear": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "side-glow1": { + "attachment": [ + { "name": "hoverglow-small" }, + { "time": 0.9666666 } + ] + }, + "side-glow2": { + "attachment": [ + { "time": 0.06666667, "name": "hoverglow-small" }, + { "time": 1 } + ] + }, + "side-glow3": { + "attachment": [ + { "name": "hoverglow-small" }, + { "time": 0.9666666 } + ] + } + }, + "bones": { + "back-shoulder": { + "translate": [ + { + "x": 1.4024963, + "y": 0.4371624, + "curve": [ 0.08833333, 1.4024963, 0.20787777, -2.4733276, 0.08833333, 0.4371624, 0.20787777, 8.614532 ] + }, + { + "time": 0.3333333, + "x": -2.4733276, + "y": 8.614532, + "curve": [ 0.5721222, -2.4733276, 0.8333333, 1.4024963, 0.5721222, 8.614532, 0.8333333, 0.4371624 ] + }, + { "time": 1, "x": 1.4024963, "y": 0.4371624 } + ] + }, + "board-ik": { + "translate": [ + { + "x": 393.6227, + "curve": [ 0.08333333, 393.6227, 0.25, 393.47745, 0.08333333, 0, 0.25, 117.69192 ] + }, + { + "time": 0.3333333, + "x": 393.47745, + "y": 117.69192, + "curve": [ 0.375, 393.47745, 0.4583333, 393.6227, 0.375, 117.69192, 0.4583333, 83.82092 ] + }, + { "time": 0.5, "x": 393.6227, "y": 83.82092 }, + { "time": 0.6666667, "x": 393.62265, "y": 30.147125 }, + { "time": 1, "x": 393.6227 } + ] + }, + "exhaust1": { + "scale": [ + { + "x": 1.5925673, + "y": 0.9635573, + "curve": [ 0.03333333, 1.5925673, 0.1, 1, 0.03333333, 0.9635573, 0.1, 0.712985 ] + }, + { + "time": 0.13333334, + "y": 0.712985, + "curve": [ 0.15, 1, 0.18333334, 1.77402, 0.15, 0.712985, 0.18333334, 0.8827183 ] + }, + { + "time": 0.2, + "x": 1.77402, + "y": 0.8827183, + "curve": [ 0.24166666, 1.77402, 0.325, 1.1814528, 0.24166666, 0.8827183, 0.325, 0.6494452 ] + }, + { + "time": 0.3666667, + "x": 1.1814528, + "y": 0.6494452, + "curve": [ 0.4083333, 1.1814528, 0.4916667, 1.892804, 0.4083333, 0.6494452, 0.4916667, 0.8191784 ] + }, + { + "time": 0.5333333, + "x": 1.892804, + "y": 0.8191784, + "curve": [ 0.5583333, 1.892804, 0.6083333, 1.1802405, 0.5583333, 0.8191784, 0.6083333, 0.6857325 ] + }, + { + "time": 0.6333333, + "x": 1.1802405, + "y": 0.6857325, + "curve": [ 0.6583333, 1.1802405, 0.7083333, 1.9033748, 0.6583333, 0.6857325, 0.7083333, 0.8554657 ] + }, + { + "time": 0.7333333, + "x": 1.9033748, + "y": 0.8554657, + "curve": [ 0.7666666, 1.9033748, 0.8333333, 1.3108075, 0.7666666, 0.8554657, 0.8333333, 0.6222546 ] + }, + { + "time": 0.8666667, + "x": 1.3108075, + "y": 0.6222546, + "curve": [ 0.9, 1.3108075, 0.9666666, 1.5925673, 0.9, 0.6222546, 0.9666666, 0.9635573 ] + }, + { "time": 1, "x": 1.5925673, "y": 0.9635573 } + ] + }, + "exhaust2": { + "scale": [ + { + "x": 1.8796126, + "y": 0.8323539, + "curve": [ 0.025, 1.8796126, 0.075, 1.3108075, 0.025, 0.8323539, 0.075, 0.6857325 ] + }, + { + "time": 0.1, + "x": 1.3108075, + "y": 0.6857325, + "curve": [ 0.13333334, 1.3108075, 0.2, 2.0101795, 0.13333334, 0.6857325, 0.2077625, 0.7363072 ] + }, + { + "time": 0.23333333, + "x": 2.0101795, + "y": 0.768876, + "curve": [ 0.2666667, 2.0101795, 0.3333333, 1, 0.2818951, 0.8307277, 0.3333333, 0.909796 ] + }, + { + "time": 0.3666667, + "y": 0.909796, + "curve": [ 0.4, 1, 0.4666667, 1.699372, 0.4, 0.909796, 0.4736002, 0.8906031 ] + }, + { + "time": 0.5, + "x": 1.699372, + "y": 0.8596064, + "curve": [ 0.5166666, 1.699372, 0.55, 1.1814528, 0.5395093, 0.8132176, 0.55, 0.712985 ] + }, + { + "time": 0.5666666, + "x": 1.1814528, + "y": 0.712985, + "curve": [ 0.6166667, 1.1814528, 0.7166666, 1.8808248, 0.6166667, 0.712985, 0.7166666, 0.7960666 ] + }, + { + "time": 0.7666666, + "x": 1.8808248, + "y": 0.7960666, + "curve": [ 0.8, 1.8808248, 0.8666667, 1.3002366, 0.8, 0.7960666, 0.8666667, 0.6494452 ] + }, + { + "time": 0.9, + "x": 1.3002366, + "y": 0.6494452, + "curve": [ 0.925, 1.3002366, 0.975, 1.8796126, 0.925, 0.6494452, 0.975, 0.8323539 ] + }, + { "time": 1, "x": 1.8796126, "y": 0.8323539 } + ] + }, + "exhaust3": { + "scale": [ + { + "x": 1.881543, + "y": 0.8103436, + "curve": [ 0.01666667, 1.881543, 0.16666667, 1.3002366, 0.01666667, 0.8103436, 0.16666667, 0.6494452 ] + }, + { + "time": 0.2, + "x": 1.3002366, + "y": 0.6494452, + "curve": [ 0.225, 1.3002366, 0.275, 2.050583, 0.225, 0.6494452, 0.275, 0.9842434 ] + }, + { + "time": 0.3, + "x": 2.050583, + "y": 0.9842434, + "curve": [ 0.325, 2.050583, 0.375, 1.3108075, 0.325, 0.9842434, 0.3838705, 0.7154094 ] + }, + { + "time": 0.4, + "x": 1.3108075, + "y": 0.6857325, + "curve": [ 0.4333333, 1.3108075, 0.5, 1.860152, 0.4257191, 0.6384113, 0.5, 0.5370912 ] + }, + { + "time": 0.5333333, + "x": 1.860152, + "y": 0.5370912, + "curve": [ 0.5666666, 1.860152, 0.6333333, 1.186524, 0.5666666, 0.5370912, 0.6043684, 0.8539467 ] + }, + { + "time": 0.6666667, + "x": 1.186524, + "y": 0.8538576, + "curve": [ 0.7, 1.186524, 0.7666666, 1.5493445, 0.7065524, 0.8538005, 0.7735073, 0.7750741 ] + }, + { + "time": 0.8, + "x": 1.5493445, + "y": 0.7456156, + "curve": [ 0.8166666, 1.5493445, 0.85, 1.1814528, 0.8145783, 0.729405, 0.85, 0.712985 ] + }, + { + "time": 0.8666667, + "x": 1.1814528, + "y": 0.712985, + "curve": [ 0.9, 1.1814528, 0.9666666, 1.881543, 0.9, 0.712985, 0.9666666, 0.8103436 ] + }, + { "time": 1, "x": 1.881543, "y": 0.8103436 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": -11.184067, + "curve": [ 0.06406893, -14.818895, 0.25, -20.00856 ] + }, + { + "time": 0.3333333, + "value": -20.00856, + "curve": [ 0.4290698, -20.11992, 0.5796532, 5.121221 ] + }, + { + "time": 0.6, + "value": 8.669727, + "curve": [ 0.6174707, 11.71663, 0.6872666, 20.52466 ] + }, + { + "time": 0.7666666, + "value": 20.55344, + "curve": [ 0.8483785, 20.69685, 0.963258, -9.425582 ] + }, + { "time": 1, "value": -11.184067 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": 7.6139, + "curve": [ 0.14280485, 7.615801, 0.24749964, -23.17212 ] + }, + { + "time": 0.2666667, + "value": -26.562366, + "curve": [ 0.28090015, -29.07997, 0.3512679, -37.35728 ] + }, + { + "time": 0.4333333, + "value": -37.20402, + "curve": [ 0.513157, -37.05031, 0.5616712, -29.884733 ] + }, + { + "time": 0.6, + "value": -25.176544, + "curve": [ 0.6211285, -22.581184, 0.694023, -3.983979 ] + }, + { + "time": 0.8, + "value": 3.628184, + "curve": [ 0.8612922, 8.030727, 0.9464212, 7.569488 ] + }, + { "time": 1, "value": 7.6139 } + ], + "translate": [ + { + "curve": [ 0.11666667, 0, 0.35, 0.5231628, 0.11666667, 0, 0.35, -3.271973 ] + }, + { + "time": 0.4666667, + "x": 0.5231628, + "y": -3.271973, + "curve": [ 0.6, 0.5231628, 0.8666667, 0, 0.6, -3.271973, 0.8666667, 0 ] + }, + { "time": 1 } + ], + "shear": [ + { + "y": 19.83303, + "curve": [ 0.11666667, 0, 0.35, 15.27623, 0.11666667, 19.83303, 0.35, 28.307434 ] + }, + { + "time": 0.4666667, + "x": 15.27623, + "y": 28.307434, + "curve": [ 0.6, 15.27623, 0.8666667, 0, 0.6, 28.307434, 0.8666667, 19.83303 ] + }, + { "time": 1, "y": 19.83303 } + ] + }, + "front-leg-target": { + "translate": [ + { + "time": 0.3666667, + "curve": [ 0.4278075, 10.829493, 0.5666666, 12.77742, 0.4139037, 7.293329, 0.5666666, 8.790497 ] + }, + { + "time": 0.6, + "x": 12.77742, + "y": 8.790497, + "curve": [ 0.6916666, 12.77742, 0.7715744, 11.271518, 0.6916666, 8.790497, 0.766436, 8.619392 ] + }, + { "time": 0.8666667 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.461792, + "y": 10.149414, + "curve": [ 0.10333333, 1.461792, 0.24937777, 1.3603516, 0.10333333, 10.149414, 0.24937777, -4.394674 ] + }, + { + "time": 0.4, + "x": 1.3603516, + "y": -4.394674, + "curve": [ 0.6206223, 1.3603516, 0.85, 1.461792, 0.6206223, -4.394674, 0.85, 10.149414 ] + }, + { "time": 1, "x": 1.461792, "y": 10.149414 } + ] + }, + "front-thigh": { + "translate": [ + { "x": -7.48584, "y": 8.506332 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -85.92003, + "curve": [ 0.07966432, -85.58839, 0.2837893, -62.70161 ] + }, + { + "time": 0.3666667, + "value": -55.13999, + "curve": [ 0.4377993, -48.64994, 0.551424, -43.20866 ] + }, + { + "time": 0.6333333, + "value": -43.21428, + "curve": [ 0.7163255, -43.21998, 0.9083333, -85.92003 ] + }, + { "time": 1, "value": -85.92003 } + ], + "translate": [ + { + "x": -0.592102, + "y": -2.9409485, + "curve": [ 0.10046556, -1.2054043, 0.275, -1.7364502, 0.09166667, -2.9409485, 0.275, -6.385315 ] + }, + { + "time": 0.3666667, + "x": -1.7364502, + "y": -6.385315, + "curve": [ 0.4333333, -1.7364502, 0.5666666, 0.7228088, 0.4333333, -6.385315, 0.5872842, -4.478018 ] + }, + { + "time": 0.6333333, + "x": 0.7228088, + "y": -4.209206, + "curve": [ 0.725, 0.7228088, 0.9083333, -0.0769291, 0.7425978, -3.571373, 0.9083333, -2.9409485 ] + }, + { "time": 1, "x": -0.592102, "y": -2.9409485 } + ] + }, + "gun": { + "rotate": [ + { + "value": 1.9487133, + "curve": [ 0.08333333, 1.9487133, 0.24508634, 36.73203 ] + }, + { + "time": 0.3333333, + "value": 36.71154, + "curve": [ 0.4394591, 36.6869, 0.58874, 10.679077 ] + }, + { + "time": 0.6333333, + "value": 8.750355, + "curve": [ 0.7013947, 5.806615, 0.9166667, 1.9487133 ] + }, + { "time": 1, "value": 1.9487133 } + ] + }, + "hair1": { + "rotate": [ + { + "value": 9.61486, + "curve": [ 0.0597572, 9.040993, 0.25, 8.903637 ] + }, + { + "time": 0.3333333, + "value": 8.903637, + "curve": [ 0.3916667, 8.903637, 0.5083333, 14.578968 ] + }, + { + "time": 0.5666666, + "value": 14.578968, + "curve": [ 0.675, 14.578968, 0.9562207, 10.283142 ] + }, + { "time": 1, "value": 9.61486 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -3.820675, + "curve": [ 0.01666667, -3.820675, 0.06448884, -9.15762 ] + }, + { + "time": 0.13333334, + "value": -9.085266, + "curve": [ 0.17791706, -9.03841, 0.23369503, 1.2894592 ] + }, + { + "time": 0.2666667, + "value": 5.978203, + "curve": [ 0.2757636, 7.271835, 0.3364826, 17.103916 ] + }, + { + "time": 0.3666667, + "value": 17.10401, + "curve": [ 0.4125646, 17.10416, 0.4666667, 1.5926285 ] + }, + { + "time": 0.5, + "value": 1.5926285, + "curve": [ 0.5333333, 1.5926285, 0.5666666, 13.625595 ] + }, + { + "time": 0.6, + "value": 13.625595, + "curve": [ 0.6166667, 13.625595, 0.6833333, 0.7837257 ] + }, + { + "time": 0.7, + "value": 0.7837257, + "curve": [ 0.7166666, 0.7837257, 0.7501043, 12.009415 ] + }, + { + "time": 0.7666666, + "value": 11.89935, + "curve": [ 0.7922618, 11.729248, 0.8166666, -0.848919 ] + }, + { + "time": 0.8333333, + "value": -0.8489151, + "curve": [ 0.8502976, -0.8489151, 0.8801587, 1.9889565 ] + }, + { + "time": 0.9, + "value": 1.8188553, + "curve": [ 0.9164942, 1.677452, 0.95, -6.89547 ] + }, + { + "time": 0.9666666, + "value": -6.89547, + "curve": [ 0.975, -6.89547, 0.9916667, -3.820675 ] + }, + { "time": 1, "value": -3.820675 } + ] + }, + "hair3": { + "rotate": [ + { + "value": 9.61486, + "curve": [ 0.01430481, 8.505188, 0.075, 2.63373 ] + }, + { + "time": 0.1, + "value": 2.63373, + "curve": [ 0.15, 2.63373, 0.25, 13.522522 ] + }, + { + "time": 0.3, + "value": 13.522522, + "curve": [ 0.35, 13.522522, 0.45, 11.27948 ] + }, + { + "time": 0.5, + "value": 11.27948, + "curve": [ 0.575, 11.27948, 0.725, 18.13115 ] + }, + { + "time": 0.8, + "value": 18.13115, + "curve": [ 0.85, 18.13115, 0.9779913, 11.06923 ] + }, + { "time": 1, "value": 9.61486 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -17.701607, + "curve": [ 0.008333334, -17.701607, 0.025, -23.727055 ] + }, + { + "time": 0.03333333, + "value": -23.727055, + "curve": [ 0.06666667, -23.727055, 0.1541442, -4.404465 ] + }, + { + "time": 0.16666667, + "value": -1.922989, + "curve": [ 0.19701427, 4.090751, 0.2357135, 12.90876 ] + }, + { + "time": 0.2666667, + "value": 17.55626, + "curve": [ 0.3007945, 22.680435, 0.3416667, 27.974327 ] + }, + { + "time": 0.3666667, + "value": 27.974327, + "curve": [ 0.4, 27.974327, 0.4666667, -1.449669 ] + }, + { + "time": 0.5, + "value": -1.449669, + "curve": [ 0.5166666, -1.449669, 0.55, 3.160774 ] + }, + { + "time": 0.5666666, + "value": 3.160774, + "curve": [ 0.5833333, 3.160774, 0.6166667, -8.90451 ] + }, + { + "time": 0.6333333, + "value": -8.90451, + "curve": [ 0.6416666, -8.90451, 0.6583333, -5.404777 ] + }, + { + "time": 0.6666667, + "value": -5.404777, + "curve": [ 0.6833333, -5.404777, 0.7166666, -15.321167 ] + }, + { + "time": 0.7333333, + "value": -15.321167, + "curve": [ 0.75, -15.321167, 0.7833333, -9.186089 ] + }, + { + "time": 0.8, + "value": -9.186089, + "curve": [ 0.8166666, -9.186089, 0.85, -23.603443 ] + }, + { + "time": 0.8666667, + "value": -23.603443, + "curve": [ 0.8833333, -23.603443, 0.9166667, -17.379684 ] + }, + { + "time": 0.9333333, + "value": -17.379684, + "curve": [ 0.9416666, -17.379684, 0.9583333, -20.4615 ] + }, + { + "time": 0.9666666, + "value": -20.4615, + "curve": [ 0.975, -20.4615, 0.9916667, -17.701607 ] + }, + { "time": 1, "value": -17.701607 } + ] + }, + "head": { + "rotate": [ + { + "value": 10.198807, + "curve": [ 0.04406569, 11.515038, 0.2000242, 16.12476 ] + }, + { + "time": 0.2666667, + "value": 16.143196, + "curve": [ 0.3745627, 16.17304, 0.4921486, 2.6543446 ] + }, + { + "time": 0.6333333, + "value": 2.6821194, + "curve": [ 0.7254708, 2.700241, 0.9627052, 9.26286 ] + }, + { "time": 1, "value": 10.198807 } + ], + "translate": [ + { + "curve": [ 0.030124607, -0.24282837, 0.2, -4.21814, 0.05138515, -1.064109, 0.2, -3.622406 ] + }, + { + "time": 0.2666667, + "x": -4.21814, + "y": -3.622406, + "curve": [ 0.3583333, -4.21814, 0.5416667, 0.835022, 0.3583333, -3.622406, 0.5416667, 6.01123 ] + }, + { + "time": 0.6333333, + "x": 0.835022, + "y": 6.01123, + "curve": [ 0.725, 0.835022, 0.9392234, 0.3238945, 0.725, 6.01123, 0.9453953, 1.1418962 ] + }, + { "time": 1 } + ] + }, + "head-control": { + "translate": [ + { + "x": 0.3734741, + "y": -11.16998, + "curve": [ 0.1325, 0.3734741, 0.335225, -10.23227, 0.1325, -11.16998, 0.335225, 3.1505556 ] + }, + { + "time": 0.5333333, + "x": -10.23227, + "y": 3.1505556, + "curve": [ 0.709775, -10.23227, 0.8833333, 0.3734741, 0.709775, 3.1505556, 0.8833333, -11.16998 ] + }, + { "time": 1, "x": 0.3734741, "y": -11.16998 } + ] + }, + "hip": { + "translate": [ + { + "x": -53.48852, + "y": 32.14271, + "curve": [ 0.06116406, -53.76524, 0.09322592, -51.81199, 0.04435653, 16.33867, 0.06267085, 9.66658 ] + }, + { + "time": 0.13333334, + "x": -49.3139, + "y": 7.007004, + "curve": [ 0.29993045, -35.26631, 0.4609025, -20.05555, 0.3135046, 9.52168, 0.4075428, 121.0916 ] + }, + { + "time": 0.5666666, + "x": -20.05555, + "y": 122.72142, + "curve": [ 0.7164096, -20.09259, 0.9122115, -53.29204, 0.7525202, 121.79715, 0.9457761, 51.85494 ] + }, + { "time": 1, "x": -53.48852, "y": 32.14271 } + ] + }, + "hoverboard-controller": { + "translate": [ + { + "x": 319.55005, + "y": -1.5864716, + "curve": [ 0.06366143, 319.55005, 0.20047696, 347.8535, 0.05799424, -1.1977158, 0.20033485, 23.109634 ] + }, + { + "time": 0.2666667, + "x": 347.65765, + "y": 39.62125, + "curve": [ 0.3499189, 347.4113, 0.4759206, 341.4658, 0.3227371, 53.57854, 0.4395483, 85.8174 ] + }, + { + "time": 0.5333333, + "x": 338.4745, + "y": 85.7157, + "curve": [ 0.6032626, 334.8311, 0.9125736, 319.6466, 0.6208322, 85.6208, 0.879996, -1.529808 ] + }, + { "time": 1, "x": 319.55005, "y": -1.5864716 } + ] + }, + "hoverboard-thruster-front": { + "rotate": [ + { + "curve": [ 0.125, 0, 0.375, 24.06499 ] + }, + { + "time": 0.5, + "value": 24.06499, + "curve": [ 0.625, 24.06499, 0.875, 0 ] + }, + { "time": 1 } + ] + }, + "hoverboard-thruster-rear": { + "rotate": [ + { + "curve": [ 0.125, 0, 0.375, 24.06499 ] + }, + { + "time": 0.5, + "value": 24.06499, + "curve": [ 0.625, 24.06499, 0.875, 0 ] + }, + { "time": 1 } + ] + }, + "hoverglow-front": { + "scale": [ + { + "x": 0.8491376, + "y": 1.763755, + "curve": [ 0.01666667, 0.8491376, 0.05, 0.8346928, 0.01666667, 1.763755, 0.05, 2.033342 ] + }, + { + "time": 0.06666667, + "x": 0.8346928, + "y": 2.033342, + "curve": [ 0.09166667, 0.8346928, 0.14166667, 0.7520234, 0.09166667, 2.033342, 0.14166667, 1.583745 ] + }, + { + "time": 0.16666667, + "x": 0.7520234, + "y": 1.583745, + "curve": [ 0.18333334, 0.7520234, 0.21666667, 0.8093396, 0.18333334, 1.583745, 0.21666667, 1.710419 ] + }, + { + "time": 0.23333333, + "x": 0.8093396, + "y": 1.710419, + "curve": [ 0.25, 0.8093396, 0.2833333, 0.7172279, 0.25, 1.710419, 0.2833333, 1.4495454 ] + }, + { + "time": 0.3, + "x": 0.7172279, + "y": 1.4495454, + "curve": [ 0.3166667, 0.7172279, 0.35, 0.777262, 0.3166667, 1.4495454, 0.35, 1.6981606 ] + }, + { + "time": 0.3666667, + "x": 0.777262, + "y": 1.6981606, + "curve": [ 0.4003396, 0.7808548, 0.45, 0.6849891, 0.375, 1.6981606, 0.45, 1.1725577 ] + }, + { + "time": 0.4666667, + "x": 0.6849891, + "y": 1.1725577, + "curve": [ 0.4916667, 0.6849891, 0.5416667, 0.8251068, 0.4916667, 1.1725577, 0.5416667, 1.5723042 ] + }, + { + "time": 0.5666666, + "x": 0.8251068, + "y": 1.5723042, + "curve": [ 0.6112108, 0.8156652, 0.6300903, 0.7267164, 0.6112108, 1.577025, 0.6061659, 1.254833 ] + }, + { + "time": 0.6666667, + "x": 0.7247796, + "y": 1.2406707, + "curve": [ 0.6916666, 0.7247796, 0.7416667, 0.895386, 0.6916666, 1.2406707, 0.7494154, 1.7993612 ] + }, + { + "time": 0.7666666, + "x": 0.895386, + "y": 1.857167, + "curve": [ 0.7833333, 0.895386, 0.7963972, 0.8921125, 0.7960031, 1.9554677, 0.8166666, 1.9618536 ] + }, + { + "time": 0.8333333, + "x": 0.8452676, + "y": 1.9618536, + "curve": [ 0.8445584, 0.8310312, 0.8833333, 0.8022892, 0.85, 1.9618536, 0.8715095, 1.704042 ] + }, + { + "time": 0.9, + "x": 0.8022892, + "y": 1.4913216, + "curve": [ 0.9166667, 0.8022892, 0.95, 0.8449259, 0.9067616, 1.440837, 0.9364872, 1.507996 ] + }, + { + "time": 0.9666666, + "x": 0.8449259, + "y": 1.626705, + "curve": [ 0.975, 0.8449259, 0.9916667, 0.8491376, 0.9730492, 1.6518108, 0.9916667, 1.763755 ] + }, + { "time": 1, "x": 0.8491376, "y": 1.763755 } + ] + }, + "hoverglow-rear": { + "scale": [ + { + "x": 0.8449259, + "y": 1.3101475, + "curve": [ 0.01666667, 0.8449259, 0.11666667, 0.8991723, 0.01666667, 1.3101475, 0.11666667, 2.033342 ] + }, + { + "time": 0.13333334, + "x": 0.8991723, + "y": 2.033342, + "curve": [ 0.15, 0.8991723, 0.18333334, 0.7520234, 0.15, 2.033342, 0.18333334, 1.5736133 ] + }, + { + "time": 0.2, + "x": 0.7520234, + "y": 1.5736133, + "curve": [ 0.225, 0.7520234, 0.275, 0.8093396, 0.225, 1.5736133, 0.275, 1.710419 ] + }, + { + "time": 0.3, + "x": 0.8093396, + "y": 1.710419, + "curve": [ 0.3166667, 0.8093396, 0.35, 0.7172279, 0.3166667, 1.710419, 0.35, 1.3971558 ] + }, + { + "time": 0.3666667, + "x": 0.7172279, + "y": 1.3971558, + "curve": [ 0.3833333, 0.7172279, 0.4166667, 0.777262, 0.3833333, 1.3971558, 0.4166667, 1.4500636 ] + }, + { + "time": 0.4333333, + "x": 0.777262, + "y": 1.4500636, + "curve": [ 0.45, 0.777262, 0.4963621, 0.6890192, 0.45, 1.4500636, 0.48116705, 1.1675577 ] + }, + { + "time": 0.5333333, + "x": 0.6849891, + "y": 1.1725577, + "curve": [ 0.5651535, 0.6815206, 0.6166667, 0.7576283, 0.5753807, 1.1765877, 0.6166667, 1.2969007 ] + }, + { + "time": 0.6333333, + "x": 0.7576283, + "y": 1.2969007, + "curve": [ 0.6583333, 0.7576283, 0.7083333, 0.7247796, 0.6583333, 1.2969007, 0.7083333, 1.2406707 ] + }, + { + "time": 0.7333333, + "x": 0.7247796, + "y": 1.2406707, + "curve": [ 0.7721235, 0.731604, 0.7963621, 0.8931111, 0.7822757, 1.2383958, 0.7783453, 1.8535308 ] + }, + { + "time": 0.8333333, + "x": 0.895386, + "y": 1.857167, + "curve": [ 0.8779188, 0.8999355, 0.9916667, 0.8449259, 0.879716, 1.8602344, 0.9916667, 1.3101475 ] + }, + { "time": 1, "x": 0.8449259, "y": 1.3101475 } + ] + }, + "neck": { + "rotate": [ + { + "value": 10.19881, + "curve": [ 0.06957364, 12.08755, 0.1893048, 16.03221 ] + }, + { + "time": 0.2666667, + "value": 16.14319, + "curve": [ 0.3330214, 16.14319, 0.44935405, 8.034576 ] + }, + { + "time": 0.5, + "value": 5.831173, + "curve": [ 0.5416202, 4.020448, 0.6, 2.68211 ] + }, + { + "time": 0.6333333, + "value": 2.68211, + "curve": [ 0.725, 2.68211, 0.943217, 8.572393 ] + }, + { "time": 1, "value": 10.19881 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 31.00085, + "curve": [ 0.10833333, 31.00085, 0.3249924, 12.759247 ] + }, + { + "time": 0.4333333, + "value": 12.785236, + "curve": [ 0.5866608, 12.822018, 0.9166667, 31.00085 ] + }, + { "time": 1, "value": 31.00085 } + ] + }, + "rear-leg-target": { + "translate": [ + { + "time": 0.4666667, + "curve": [ 0.4916667, 0, 0.5342913, 4.468475, 0.4916667, 0, 0.5418452, 1.6264877 ] + }, + { + "time": 0.5666666, + "x": 4.532356, + "y": 1.7728882, + "curve": [ 0.6222881, 4.642107, 0.7166666, 3.312281, 0.6148122, 2.0568504, 0.7103563, 2.09515 ] + }, + { "time": 0.8 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 31.65309, + "curve": [ 0.10833333, 31.65309, 0.325, 13.01352 ] + }, + { + "time": 0.4333333, + "value": 13.01352, + "curve": [ 0.7098432, 13.01352, 0.9166667, 31.65309 ] + }, + { "time": 1, "value": 31.65309 } + ] + }, + "side-glow1": { + "rotate": [ + { "value": 51.12233, "curve": "stepped" }, + { "time": 0.06666667, "value": 43.8174, "curve": "stepped" }, + { "time": 0.1, "value": 40.95424, "curve": "stepped" }, + { "time": 0.16666667, "value": 27.781216, "curve": "stepped" }, + { "time": 0.2, "value": 10.243, "curve": "stepped" }, + { "time": 0.2666667, "curve": "stepped" }, + { "time": 0.8, "value": -25.81146 } + ], + "translate": [ + { "x": 338.2833, "y": 40.22265, "curve": "stepped" }, + { "time": 0.06666667, "x": 331.1985, "y": 30.38891, "curve": "stepped" }, + { "time": 0.1, "x": 318.6327, "y": 20.58814, "curve": "stepped" }, + { "time": 0.16666667, "x": 302.4495, "y": 9.637321, "curve": "stepped" }, + { "time": 0.2, "x": 276.8743, "y": 1.13282, "curve": "stepped" }, + { "time": 0.2666667, "x": 248.1646, "curve": "stepped" }, + { "time": 0.3, "x": 221.3581, "curve": "stepped" }, + { "time": 0.3666667, "x": 195.69295, "curve": "stepped" }, + { "time": 0.4, "x": 171.07834, "curve": "stepped" }, + { "time": 0.4666667, "x": 144.8389, "curve": "stepped" }, + { "time": 0.5, "x": 121.2188, "curve": "stepped" }, + { "time": 0.5666666, "x": 91.9805, "curve": "stepped" }, + { "time": 0.6, "x": 62.63257, "curve": "stepped" }, + { "time": 0.6666667, "x": 30.775017, "curve": "stepped" }, + { "time": 0.7, "curve": "stepped" }, + { "time": 0.7666666, "x": -28.4489, "curve": "stepped" }, + { "time": 0.8, "x": -67.48724, "y": 16.81865, "curve": "stepped" }, + { "time": 0.8666667, "x": -83.07391, "y": 24.3574, "curve": "stepped" }, + { "time": 0.9, "x": -93.80559, "y": 29.547943 } + ], + "scale": [ + { "x": 0.5346727, "curve": "stepped" }, + { "time": 0.06666667, "x": 0.5943282, "curve": "stepped" }, + { "time": 0.1, "x": 0.8437301, "curve": "stepped" }, + { "time": 0.16666667, "curve": "stepped" }, + { "time": 0.8, "x": 0.5339128, "curve": "stepped" }, + { "time": 0.8666667, "x": 0.427879, "y": 0.8014025, "curve": "stepped" }, + { "time": 0.9, "x": 0.3489812, "y": 0.6536295 } + ] + }, + "side-glow2": { + "rotate": [ + { "time": 0.06666667, "value": 51.12233, "curve": "stepped" }, + { "time": 0.1, "value": 43.8174, "curve": "stepped" }, + { "time": 0.16666667, "value": 40.95424, "curve": "stepped" }, + { "time": 0.2, "value": 27.781216, "curve": "stepped" }, + { "time": 0.2666667, "value": 10.243, "curve": "stepped" }, + { "time": 0.3, "curve": "stepped" }, + { "time": 0.8666667, "value": -25.81146 } + ], + "translate": [ + { "time": 0.06666667, "x": 338.2833, "y": 40.22265, "curve": "stepped" }, + { "time": 0.1, "x": 331.1985, "y": 30.38891, "curve": "stepped" }, + { "time": 0.16666667, "x": 318.6327, "y": 20.58814, "curve": "stepped" }, + { "time": 0.2, "x": 302.4495, "y": 9.637321, "curve": "stepped" }, + { "time": 0.2666667, "x": 276.8743, "y": 1.13282, "curve": "stepped" }, + { "time": 0.3, "x": 248.1646, "curve": "stepped" }, + { "time": 0.3666667, "x": 221.3581, "curve": "stepped" }, + { "time": 0.4, "x": 195.69295, "curve": "stepped" }, + { "time": 0.4666667, "x": 171.07834, "curve": "stepped" }, + { "time": 0.5, "x": 144.8389, "curve": "stepped" }, + { "time": 0.5666666, "x": 121.2188, "curve": "stepped" }, + { "time": 0.6, "x": 91.9805, "curve": "stepped" }, + { "time": 0.6666667, "x": 62.63257, "curve": "stepped" }, + { "time": 0.7, "x": 30.775017, "curve": "stepped" }, + { "time": 0.7666666, "curve": "stepped" }, + { "time": 0.8, "x": -28.4489, "curve": "stepped" }, + { "time": 0.8666667, "x": -67.48724, "y": 16.81865, "curve": "stepped" }, + { "time": 0.9, "x": -83.07391, "y": 24.3574, "curve": "stepped" }, + { "time": 0.9666666, "x": -93.80559, "y": 29.547943 } + ], + "scale": [ + { "time": 0.06666667, "x": 0.5346727, "curve": "stepped" }, + { "time": 0.1, "x": 0.5943282, "curve": "stepped" }, + { "time": 0.16666667, "x": 0.8437301, "curve": "stepped" }, + { "time": 0.2, "curve": "stepped" }, + { "time": 0.8666667, "x": 0.5339128, "curve": "stepped" }, + { "time": 0.9, "x": 0.427879, "y": 0.8014025, "curve": "stepped" }, + { "time": 0.9666666, "x": 0.3489812, "y": 0.6536295 } + ] + }, + "torso": { + "rotate": [ + { + "value": -34.73093, + "curve": [ 0.03395751, -36.31231, 0.16164774, -39.33425 ] + }, + { + "time": 0.2666667, + "value": -39.36955, + "curve": [ 0.3838235, -39.36955, 0.491429, -29.519127 ] + }, + { + "time": 0.5, + "value": -28.85652, + "curve": [ 0.5246124, -26.95381, 0.5709302, -21.00995 ] + }, + { + "time": 0.6333333, + "value": -21.00995, + "curve": [ 0.725, -21.00995, 0.9691816, -33.3546 ] + }, + { "time": 1, "value": -34.73093 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.03333333, 0, 0.1, 2.348778 ] + }, + { + "time": 0.13333334, + "value": 2.348778, + "curve": [ 0.225, 2.348778, 0.4083333, -2.398811 ] + }, + { + "time": 0.5, + "value": -2.398811, + "curve": [ 0.5666666, -2.398811, 0.7, 1.444809 ] + }, + { + "time": 0.7666666, + "value": 1.444809, + "curve": [ 0.825, 1.444809, 0.9416666, 0 ] + }, + { "time": 1 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.06324984, 0.7667523, 0.1060111, 1.417019 ] + }, + { + "time": 0.16666667, + "value": 1.417019, + "curve": [ 0.2593384, 1.417019, 0.3443328, -1.252899 ] + }, + { + "time": 0.4666667, + "value": -1.255848, + "curve": [ 0.6558634, -1.260408, 0.9167232, -0.779322 ] + }, + { "time": 1 } + ] + } + }, + "transform": { + "front-foot-board-transform": [ + { "mixRotate": 0.9969877 } + ], + "rear-foot-board-transform": [ + {} + ], + "toes-board": [ + {} + ] + }, + "attachments": { + "default": { + "front-foot": { + "front-foot": { + "deform": [ + { + "offset": 26, + "vertices": [ -0.02832031, -5.370239, -0.02832031, -5.370239, 3.818802, -3.7757006, -0.02832031, -5.370239, -3.821594, 3.7784686 ] + } + ] + } + }, + "front-shin": { + "front-shin": { + "deform": [ + { + "offset": 14, + "vertices": [ 0.5298004, -1.12677, -0.855072, -4.205871, -11.351578, -10.192245, -10.798645, -8.437653, -6.064468, -6.897568, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5489197, -3.060211, 1.4846344, -2.296631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.804367, -7.018173 ] + }, + { + "time": 0.3666667, + "offset": 14, + "vertices": [ 0.5298004, -1.12677, -11.66571, -9.072113, -25.65866, -17.537354, -25.532166, -16.50978, -11.782318, -11.26097, 0, 0, 0.6048736, -1.6358948, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.6048736, -1.6358948, 0, 0, -2.645218, -7.357391, 1.4846344, -2.296631, 0, 0, 0, 0, 0, 0, 0.6048736, -1.6358948, 0.6048736, -1.6358948, 0.6048736, -1.6358948, 0.6048736, -1.6358948, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.6048736, -1.6358948, 0, 0, -10.068726, -12.0999 ] + }, + { + "time": 0.5333333, + "offset": 14, + "vertices": [ 0.5298004, -1.12677, -0.855072, -4.205871, -7.007751, -8.24771, -6.454819, -6.493118, -6.064468, -6.897568, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5489197, -3.060211, 1.4846344, -2.296631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.804367, -7.018173 ] + }, + { + "time": 1, + "offset": 14, + "vertices": [ 0.5298004, -1.12677, -0.855072, -4.205871, -11.351578, -10.192245, -10.798645, -8.437653, -6.064468, -6.897568, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5489197, -3.060211, 1.4846344, -2.296631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.804367, -7.018173 ] + } + ] + } + }, + "hoverboard-board": { + "hoverboard-board": { + "deform": [ + { + "curve": [ 0.06666667, 0, 0.2, 1 ] + }, + { + "time": 0.2666667, + "offset": 1, + "vertices": [ 2.458557, 0, 0, 0, 0, 0, 0, 0, 0, 3.5567284, -2.975464E-4, 3.5567284, -2.975464E-4, 0, 0, 0, 0, 0, 0, -7.591247E-4, -9.841583, -7.591247E-4, -9.841583, -7.591247E-4, -9.841583, -7.591247E-4, -9.841583, -7.591247E-4, -9.841583, -7.591247E-4, -9.841583, -7.591247E-4, -9.841583, -7.591247E-4, -9.841583, -7.591247E-4, -9.841583, -7.591247E-4, -9.841583, -7.591247E-4, -9.841583, -7.591247E-4, -9.841583, 0, 0, 0, 0, 0, 0, 0, 0, -4.905582, 0.11214447, -9.407063, 6.17981E-4, -6.348713, 4.348755E-4, -6.349247, -6.570183, -6.349247, -6.570183, -6.348713, 4.348755E-4, -2.330795, 1.678467E-4, -2.331329, -6.57045, -2.331329, -6.57045, -2.330795, 1.678467E-4, 0, 0, 1.2207031E-4, 2.458557, 1.2207031E-4, 2.458557, 1.2207031E-4, 2.458557, 1.2207031E-4, 2.458557, 3.3297005, 4.440048, 3.3297005, 4.440048, 3.3297005, 4.440048, 1.2207031E-4, 2.458557, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.462269, 1.678467E-4, -2.462269, 1.678467E-4, -2.523163, 1.131302, -2.523163, 1.131302, -2.523163, 1.131302, 1.2207031E-4, 2.458557, 1.2207031E-4, 2.458557, -9.40694, 2.459175, 1.8806305, 0.4419708, -2.89917E-4, -3.5480804, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.523163, 1.131302, -2.523163, 1.131302, -2.523163, 1.131302, -2.462269, 1.678467E-4, -2.462269, 1.678467E-4, -2.462269, 1.678467E-4, 0, 0, 0, 0, 1.2207031E-4, 2.458557 ], + "curve": [ 0.45, 0, 0.8166666, 1 ] + }, + { "time": 1 } + ] + } + }, + "rear-foot": { + "rear-foot": { + "deform": [ + { + "offset": 28, + "vertices": [ -1.9307785, 1.3478165, -0.3141708, 2.333626, 3.051224, 0.3394623, 2.31472, -2.016785, 2.175835, -2.057953, -0.04277039, -2.994591, 1.1542892, 0.2632828, 0.9750137, -0.6716919 ] + } + ] + } + } + } + } + }, + "idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-bracer": { + "rotate": [ + { + "value": 42.46212, + "curve": [ 0.02905485, 42.9721, 0.1343778, 45.28228 ] + }, + { + "time": 0.3333333, + "value": 45.27423, + "curve": [ 0.5781397, 45.26433, 0.7984326, 40.07414 ] + }, + { + "time": 0.8333333, + "value": 39.74404, + "curve": [ 0.8783341, 39.31842, 1.0192736, 38.22513 ] + }, + { + "time": 1.2, + "value": 38.22134, + "curve": [ 1.376692, 38.21765, 1.619414, 41.68151 ] + }, + { "time": 1.6666666, "value": 42.46212 } + ] + }, + "front-fist": { + "rotate": [ + { + "curve": [ 0.0861111, 0, 0.23336044, 2.482643 ] + }, + { + "time": 0.3333333, + "value": 4.127198, + "curve": [ 0.428754, 5.69687, 0.7111111, 10.064902 ] + }, + { + "time": 0.8333333, + "value": 10.064902, + "curve": [ 0.9263888, 10.064902, 1.0922853, 4.210019 ] + }, + { + "time": 1.2, + "value": 2.781331, + "curve": [ 1.3494836, 0.7986326, 1.551389, 0 ] + }, + { "time": 1.6666666 } + ] + }, + "front-foot-target": { + "translate": [ + { "x": -69.06195 } + ] + }, + "front-shoulder": { + "translate": [ + { + "curve": [ 0.2097222, 0, 0.5250046, -1.7180977, 0.2097222, 0, 0.5250046, 4.075973 ] + }, + { + "time": 0.8333333, + "x": -1.7180977, + "y": 4.075973, + "curve": [ 1.1499954, -1.7180977, 1.4597223, 0, 1.1499954, 4.075973, 1.4597223, 0 ] + }, + { "time": 1.6666666 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -60.86928, + "curve": [ 0.15379426, -60.85433, 0.4520833, -68.65044 ] + }, + { + "time": 0.8333333, + "value": -68.65044, + "curve": [ 1.2208333, -68.65044, 1.542334, -60.86928 ] + }, + { "time": 1.6666666, "value": -60.86928 } + ] + }, + "gun": { + "rotate": [ + { + "curve": [ 0.0990061, 0.2725744, 0.3666667, 1.227249 ] + }, + { + "time": 0.5333333, + "value": 1.227249, + "curve": [ 0.665, 1.227249, 0.9372414, -0.5649137 ] + }, + { + "time": 1.1333333, + "value": -0.5542478, + "curve": [ 1.3156896, -0.5539121, 1.5823046, -0.20918465 ] + }, + { "time": 1.6666666 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.06666667, 0, 0.21343653, 2.859753 ] + }, + { + "time": 0.2666667, + "value": 3.646973, + "curve": [ 0.3576066, 4.991878, 0.535274, 7.916351 ] + }, + { + "time": 0.6666667, + "value": 7.916351, + "curve": [ 0.8092751, 7.916355, 1.0674844, 5.494446 ] + }, + { + "time": 1.1333333, + "value": 4.69825, + "curve": [ 1.245374, 3.34354, 1.525, 0 ] + }, + { "time": 1.6666666 } + ] + }, + "hair2": { + "rotate": [ + { + "curve": [ 0.06666667, 0, 0.22483164, -7.965755 ] + }, + { + "time": 0.2666667, + "value": -9.751606, + "curve": [ 0.3156868, -11.84417, 0.518887, -16.655235 ] + }, + { + "time": 0.6666667, + "value": -16.65524, + "curve": [ 0.8171845, -16.65524, 1.0289435, -11.434772 ] + }, + { + "time": 1.1333333, + "value": -9.13718, + "curve": [ 1.250492, -6.558552, 1.525, 0 ] + }, + { "time": 1.6666666 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.1, 0, 0.3, 1.3225384 ] + }, + { + "time": 0.4, + "value": 1.3225384, + "curve": [ 0.55, 1.3225384, 0.8664853, 0.925766 ] + }, + { + "time": 1, + "value": 0.7331009, + "curve": [ 1.189498, 0.4596481, 1.5, 0 ] + }, + { "time": 1.6666666 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.1183693, -0.4436188, 0.3, -8.51938 ] + }, + { + "time": 0.4, + "value": -8.51938, + "curve": [ 0.55, -8.51938, 0.85, 1.9588852 ] + }, + { + "time": 1, + "value": 1.9588852, + "curve": [ 1.1666666, 1.9588852, 1.5774637, 0.3826828 ] + }, + { "time": 1.6666666 } + ] + }, + "head": { + "rotate": [ + { + "value": -6.74768, + "curve": [ 0.1764417, -7.881808, 0.3491666, -8.94765 ] + }, + { + "time": 0.4666667, + "value": -8.94765, + "curve": [ 0.55, -8.94765, 0.6970137, -6.771097 ] + }, + { + "time": 0.8333333, + "value": -5.436397, + "curve": [ 0.8796374, -4.983036, 1.05, -4.122652 ] + }, + { + "time": 1.1333333, + "value": -4.122652, + "curve": [ 1.2658333, -4.122652, 1.4685582, -5.477994 ] + }, + { "time": 1.6666666, "value": -6.74768 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.09774022, 1.4601135, 0.2998519, 4.490768, 0.16993235, 0.1333159, 0.3162684, -3.280374 ] + }, + { + "time": 0.4, + "x": 4.554458, + "y": -5.95164, + "curve": [ 0.5295718, 4.636848, 0.7759276, 2.589203, 0.49205795, -8.888537, 0.6681138, -14.213062 ] + }, + { + "time": 0.8666667, + "x": 1.4223175, + "y": -14.2641, + "curve": [ 0.9656826, 0.1489792, 1.1093842, -2.909935, 0.993936, -14.2641, 1.143917, -10.576373 ] + }, + { + "time": 1.2333333, + "x": -3.021858, + "y": -8.259235, + "curve": [ 1.3416667, -3.021858, 1.5675943, -1.4818802, 1.3165368, -6.103104, 1.5583333, 0 ] + }, + { "time": 1.6666666 } + ] + }, + "hip": { + "rotate": [ + { + "curve": [ 0.07331329, 0.34827155, 0.3033066, 1.270263 ] + }, + { + "time": 0.4, + "value": 1.2787018, + "curve": [ 0.6146915, 1.2974385, 0.847058, -1.4075624 ] + }, + { + "time": 1.2, + "value": -1.3809776, + "curve": [ 1.3437005, -1.3701534, 1.6023358, -0.2823823 ] + }, + { "time": 1.6666666 } + ], + "translate": [ + { + "x": -11.972925, + "y": -23.15497, + "curve": [ 0.05875295, -12.964105, 0.2579626, -15.19205, 0.14166667, -23.15497, 0.34119925, -24.893784 ] + }, + { + "time": 0.4666667, + "x": -15.13656, + "y": -26.739166, + "curve": [ 0.6203822, -15.095693, 0.788416, -13.2845, 0.5973517, -28.661255, 0.75, -30.01097 ] + }, + { + "time": 0.9, + "x": -12.016165, + "y": -30.01097, + "curve": [ 0.9780124, -11.129423, 1.174976, -9.05292, 1.0355474, -29.93872, 1.233996, -28.080444 ] + }, + { + "time": 1.3333334, + "x": -9.05817, + "y": -26.638184, + "curve": [ 1.500856, -9.06372, 1.614493, -10.950818, 1.453844, -24.888504, 1.60875, -23.15497 ] + }, + { "time": 1.6666666, "x": -11.972925, "y": -23.15497 } + ] + }, + "neck": { + "rotate": [ + { + "value": 3.7834435, + "curve": [ 0.16666667, 3.7834435, 0.5, 5.449173 ] + }, + { + "time": 0.6666667, + "value": 5.449173, + "curve": [ 0.9166667, 5.449173, 1.4166666, 3.7834435 ] + }, + { "time": 1.6666666, "value": 3.7834435 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "curve": [ 0.06311346, 0.5412674, 0.3666667, 3.3939 ] + }, + { + "time": 0.5333333, + "value": 3.3939, + "curve": [ 0.6958333, 3.3939, 0.938892, -1.6320496 ] + }, + { + "time": 1.2, + "value": -1.6092262, + "curve": [ 1.4195797, -1.5900345, 1.5741305, -0.6726322 ] + }, + { "time": 1.6666666 } + ] + }, + "rear-foot-target": { + "translate": [ + { "x": 48.86993 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 39.19888, + "curve": [ 0.185123, 39.21545, 0.5, 29.370453 ] + }, + { + "time": 0.6666667, + "value": 29.370453, + "curve": [ 0.9166667, 29.370453, 1.4166666, 39.19888 ] + }, + { "time": 1.6666666, "value": 39.19888 } + ] + }, + "torso": { + "rotate": [ + { + "value": -22.87543, + "curve": [ 0.0994818, -23.44993, 0.3631936, -24.73999 ] + }, + { + "time": 0.5333333, + "value": -24.74071, + "curve": [ 0.7060638, -24.7416, 0.9608056, -20.96683 ] + }, + { + "time": 1.1333333, + "value": -20.967194, + "curve": [ 1.35508, -20.967667, 1.5666924, -22.280136 ] + }, + { "time": 1.6666666, "value": -22.87543 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.06681584, 0.3343238, 0.3412546, 2.5357144 ] + }, + { + "time": 0.5333333, + "value": 2.5443554, + "curve": [ 0.7340414, 2.553385, 0.98162, -0.9433611 ] + }, + { + "time": 1.1333333, + "value": -0.9299526, + "curve": [ 1.365215, -0.9094587, 1.548701, -0.561897 ] + }, + { "time": 1.6666666 } + ] + }, + "torso3": { + "rotate": [ + { + "value": -2.148, + "curve": [ 0.05198252, -1.9036858, 0.3839926, -0.14695562 ] + }, + { + "time": 0.5333333, + "value": -0.1397686, + "curve": [ 0.761939, -0.12876725, 0.8954164, -3.104005 ] + }, + { + "time": 1.1333333, + "value": -3.1014395, + "curve": [ 1.348143, -3.098699, 1.5921898, -2.457665 ] + }, + { "time": 1.6666666, "value": -2.148 } + ] + } + } + }, + "idle-turn": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-bracer": { + "rotate": [ + { + "value": 6.690201, + "curve": [ 0, 19.76432, 0.03859885, 56.53068 ] + }, + { + "time": 0.06666667, + "value": 56.6253, + "curve": [ 0.11433945, 56.78601, 0.18898627, 42.46212 ] + }, + { "time": 0.2666667, "value": 42.46212 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -15.535895, + "curve": [ 0, -3.0764246, 0.03372228, 18.443924 ] + }, + { + "time": 0.06666667, + "value": 19.023037, + "curve": [ 0.10797147, 19.74911, 0.16942663, 0 ] + }, + { "time": 0.2666667 } + ], + "scale": [ + { + "x": 0.9399196, + "curve": [ 0, 0.9621076, 0.02415492, 1.236838, 0, 1, 0.02560019, 0.947412 ] + }, + { + "time": 0.06666667, + "x": 1.2361622, + "y": 0.947412, + "curve": [ 0.11725762, 1.235358, 0.18898627, 1, 0.1165446, 0.947412, 0.18898627, 1 ] + }, + { "time": 0.2666667 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": -1.85278, + "curve": [ 0.014102791, -8.91439, 0.04653653, -28.39679 ] + }, + { + "time": 0.1, + "value": -28.88741, + "curve": [ 0.14351568, -29.286743, 0.2624582, -21.7725 ] + }, + { "time": 0.2666667 } + ], + "translate": [ + { + "x": 9.968124, + "y": 0.8236809, + "curve": [ 0, -54.41335, 0.07785524, -69.06195, 0, 0.15267313, 0.07785524, 0 ] + }, + { "time": 0.16666667, "x": -69.06195 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.1284485, + "y": -14.31152, + "curve": [ 0.06666667, 1.1284485, 0.2, 0, 0.06666667, -14.31152, 0.2, 0 ] + }, + { "time": 0.2666667 } + ] + }, + "front-thigh": { + "translate": [ + { + "x": 12.209518, + "y": 1.8914032, + "curve": [ 0.03333333, 12.209518, 0.1, 0, 0.03333333, 1.8914032, 0.1, 0 ] + }, + { "time": 0.13333334 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -302.772, + "curve": [ 0, -406.90015, 0.12456839, -420.8693 ] + }, + { "time": 0.2666667, "value": -420.8693 } + ], + "translate": [ + { + "x": 2.2368546, + "y": -4.981582, + "curve": [ 0.06666667, 2.2368546, 0.11140642, 0, 0.06666667, -4.981582, 0.11140642, 0 ] + }, + { "time": 0.2666667 } + ] + }, + "gun": { + "rotate": [ + { + "value": -3.954601, + "curve": [ 0, -10.403942, 0.01909628, -20.42602 ] + }, + { + "time": 0.03333333, + "value": -20.454044, + "curve": [ 0.04384435, -20.474735, 0.12498682, 0 ] + }, + { "time": 0.2 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -3.849964, + "curve": [ 0.04377778, -3.849964, 0.071606, 6.912709 ] + }, + { + "time": 0.13333334, + "value": 8.052677, + "curve": [ 0.16629143, 8.6487, 0.20818974, 0 ] + }, + { "time": 0.2666667 } + ] + }, + "hair2": { + "rotate": [ + { + "value": 1.249958, + "curve": [ 0.04377778, 1.249958, 0.071606, 8.967916 ] + }, + { + "time": 0.13333334, + "value": 8.597805, + "curve": [ 0.16629143, 8.404295, 0.20818974, 0 ] + }, + { "time": 0.2666667 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -9.007214, + "curve": [ 0.04377778, -9.007214, 0.071606, 7.410595 ] + }, + { + "time": 0.13333334, + "value": 10.077616, + "curve": [ 0.16629143, 11.472048, 0.20818974, 0 ] + }, + { "time": 0.2666667 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -16.49289, + "curve": [ 0.04377778, -16.49289, 0.100582, -5.97757 ] + }, + { + "time": 0.13333334, + "value": -2.952637, + "curve": [ 0.1616467, -0.3376007, 0.20818974, 0 ] + }, + { "time": 0.2666667 } + ] + }, + "head": { + "rotate": [ + { + "value": 5.116035, + "curve": [ 0, -6.34088, 0.12456839, -6.747682 ] + }, + { "time": 0.2666667, "value": -6.747682 } + ], + "scale": [ + { + "y": 1.03, + "curve": [ 0.06666667, 1, 0.10697675, 1, 0.06666667, 1.03, 0.10697675, 1 ] + }, + { "time": 0.2666667 } + ] + }, + "head-control": { + "translate": [ + { + "x": -13.715668, + "y": -34.70318, + "curve": [ 0.06666667, -13.715668, 0.2, 0, 0.06666667, -34.70318, 0.2, 0 ] + }, + { "time": 0.2666667 } + ] + }, + "hip": { + "translate": [ + { + "x": -2.693813, + "y": -6.786743, + "curve": [ 0.06666667, -2.693813, 0.2, -11.972925, 0.06666667, -6.786743, 0.2, -23.15497 ] + }, + { "time": 0.2666667, "x": -11.972925, "y": -23.15497 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.19942, + "curve": [ 0, 6.270158, 0.12456839, 3.7834435 ] + }, + { "time": 0.2666667, "value": 3.7834435 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 11.752888, + "curve": [ 0, -7.974851, 0.016757887, -33.39882 ] + }, + { + "time": 0.03333333, + "value": -33.3857, + "curve": [ 0.04859935, -33.37362, 0.1310863, 0 ] + }, + { "time": 0.2 } + ] + }, + "rear-foot-target": { + "translate": [ + { + "x": -58.394, + "y": 30.476856, + "curve": [ 0, -7.151085, 0.0466009, 16.621117, 0, 12.707376, 0.03919706, 0.22035736 ] + }, + { + "time": 0.1, + "x": 34.13688, + "y": -0.1882988, + "curve": [ 0.135537, 45.79357, 0.16338927, 48.86993, 0.132507, -0.4067766, 0.16338927, 0 ] + }, + { "time": 0.2, "x": 48.86993 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -16.11101, + "y": -1.3840027, + "curve": [ 0.03333333, -16.11101, 0.1, 0, 0.03333333, -1.3840027, 0.1, 0 ] + }, + { "time": 0.13333334 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 248.56125, + "curve": [ 0, 371.2775, 0.06228419, 399.1989 ] + }, + { "time": 0.13333334, "value": 399.1989 } + ], + "translate": [ + { + "x": -2.839569, + "y": 37.28061, + "curve": [ 0.03333333, -2.839569, 0.06943522, 0, 0.03333333, 37.28061, 0.06943522, 0 ] + }, + { "time": 0.13333334 } + ] + }, + "torso": { + "rotate": [ + { + "value": -18.249893, + "curve": [ 0, -10.59406, 0.12456839, -22.87542 ] + }, + { "time": 0.2666667, "value": -22.87542 } + ], + "scale": [ + { + "y": 1.03, + "curve": [ 0.06666667, 1, 0.13178295, 1, 0.06666667, 1.03, 0.13178295, 1 ] + }, + { "time": 0.2666667 } + ] + }, + "torso3": { + "rotate": [ + { "time": 0.2666667, "value": -2.147999 } + ] + } + } + }, + "jump": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" }, + { "time": 0.1, "name": "front-fist-closed" }, + { "time": 0.8333333, "name": "front-fist-open" } + ] + } + }, + "bones": { + "back-foot-tip": { + "rotate": [ + { + "value": -143.72617, + "curve": [ 0.08347857, -144.23846, 0.166992, -74.25503 ] + }, + { + "time": 0.2666667, + "value": -52.75867, + "curve": [ 0.3417112, -36.57418, 0.512951, -36.57154 ] + }, + { + "time": 0.6333333, + "value": -30.97292, + "curve": [ 0.7235831, -26.775673, 0.848118, -17.061863 ] + }, + { + "time": 0.9666666, + "value": -16.74177, + "curve": [ 1.167036, -16.200747, 1.2718493, -144.1704 ] + }, + { "time": 1.3333334, "value": -143.72617 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 20.536366, + "curve": [ 0.054479, 32.22879, 0.1920287, 55.84296 ] + }, + { + "time": 0.23333333, + "value": 62.57772, + "curve": [ 0.2903467, 71.87382, 0.3750252, 79.28102 ] + }, + { + "time": 0.4333333, + "value": 79.18405, + "curve": [ 0.5546791, 78.98224, 0.6837272, 27.53711 ] + }, + { + "time": 0.7333333, + "value": 13.280796, + "curve": [ 0.785987, -1.851322, 0.8744862, -24.76372 ] + }, + { + "time": 1, + "value": -25.451767, + "curve": [ 1.164866, -26.35554, 1.303476, 9.098476 ] + }, + { "time": 1.3333334, "value": 20.536366 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16143, + "curve": [ 0.11426024, -39.59057, 0.3, -45.60855 ] + }, + { + "time": 0.4, + "value": -45.60855, + "curve": [ 0.4416667, -45.60855, 0.5367003, -21.53749 ] + }, + { + "time": 0.5666666, + "value": -15.396365, + "curve": [ 0.5918796, -10.22935, 0.6916011, 11.892562 ] + }, + { + "time": 0.7333333, + "value": 11.73226, + "curve": [ 0.7830127, 11.541427, 0.8309314, 1.8034153 ] + }, + { + "time": 0.8666667, + "value": -5.78305, + "curve": [ 0.8969967, -12.221985, 0.9008168, -14.216885 ] + }, + { + "time": 0.9333333, + "value": -14.51377, + "curve": [ 0.9742595, -14.88744, 0.9759359, 10.380578 ] + }, + { + "time": 1, + "value": 10.547044, + "curve": [ 1.027373, 10.7364, 1.0228404, -8.439857 ] + }, + { + "time": 1.0333333, + "value": -8.417142, + "curve": [ 1.059476, -8.360548, 1.073571, 10.116536 ] + }, + { + "time": 1.1, + "value": 10.219346, + "curve": [ 1.168007, 10.483893, 1.269697, -36.06642 ] + }, + { "time": 1.3333334, "value": -36.16143 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 7.35138, + "curve": [ 0, 4.801658, 0.05, -26.644875 ] + }, + { + "time": 0.06666667, + "value": -26.644875, + "curve": [ 0.19166666, -26.644875, 0.4416667, -11.77327 ] + }, + { + "time": 0.5666666, + "value": -11.77327, + "curve": [ 0.6916666, -11.77327, 0.9416666, -19.36478 ] + }, + { + "time": 1.0666667, + "value": -19.36478, + "curve": [ 1.1333333, -19.36478, 1.3201784, 3.8209915 ] + }, + { "time": 1.3333334, "value": 7.35138 } + ] + }, + "front-foot-target": { + "rotate": [ + { "value": -62.53822 } + ], + "translate": [ + { "x": 16.34054, "y": 0.18180084 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -1.573183, + "curve": [ 0, -24.70923, 0.16180633, -60.87512 ] + }, + { + "time": 0.2666667, + "value": -60.83403, + "curve": [ 0.3420365, -60.8045, 0.5816783, -43.50105 ] + }, + { + "time": 0.7, + "value": -39.45053, + "curve": [ 0.773209, -36.94436, 0.8316296, -36.77623 ] + }, + { + "time": 0.9666666, + "value": -36.60168, + "curve": [ 1.0543914, -36.4883, 1.0922754, -37.3679 ] + }, + { + "time": 1.1666666, + "value": -33.26124, + "curve": [ 1.237124, -29.371746, 1.146854, -1.413369 ] + }, + { "time": 1.2, "value": -1.573183 } + ] + }, + "front-leg-target": { + "translate": [ + { "x": -13.945175, "y": -30.34133 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -74.18883, + "curve": [ 0, -51.13796, 0.04227064, -12.53828 ] + }, + { + "time": 0.16666667, + "value": -12.284243, + "curve": [ 0.284518, -12.320733, 0.3699448, -74.43774 ] + }, + { + "time": 0.4333333, + "value": -92.91604, + "curve": [ 0.49831665, -111.8592, 0.6173691, -140.282 ] + }, + { + "time": 0.9, + "value": -140.8386, + "curve": [ 1.0041902, -141.0438, 1.0896565, -47.86548 ] + }, + { + "time": 1.1, + "value": -37.43758, + "curve": [ 1.107549, -29.827354, 1.140393, -21.18304 ] + }, + { + "time": 1.1666666, + "value": -21.08193, + "curve": [ 1.1795067, -21.032516, 1.1907092, -50.65045 ] + }, + { + "time": 1.2, + "value": -53.17039, + "curve": [ 1.2200128, -58.52528, 1.2707275, -73.38457 ] + }, + { "time": 1.3333334, "value": -74.18883 } + ] + }, + "front-shoulder": { + "translate": [ + { + "curve": [ 0.03111111, -2.21615, 0.06512593, -3.731018, 0.02012519, -3.248451, 0.06512593, -14.739197 ] + }, + { + "time": 0.1, + "x": -3.731018, + "y": -14.739197, + "curve": [ 0.21592553, -3.731018, 0.3842896, -0.1688366, 0.21592553, -14.739197, 0.4023343, -12.508928 ] + }, + { + "time": 0.5, + "x": 1.6337395, + "y": -9.514136, + "curve": [ 0.6319761, 3.689713, 0.9348034, 7.411598, 0.585023, -6.907011, 0.9085255, 10.862894 ] + }, + { + "time": 1.1, + "x": 7.445492, + "y": 10.988812, + "curve": [ 1.1797043, 7.461843, 1.2645, 2.857668, 1.193326, 11.050184, 1.2938455, 3.3825455 ] + }, + { "time": 1.3333334 } + ] + }, + "front-thigh": { + "rotate": [ + { + "value": 55.07567, + "curve": [ 0.007130125, 46.6568, 0.04317886, 26.299644 ] + }, + { + "time": 0.06666667, + "value": 22.83655, + "curve": [ 0.0995464, 17.988686, 0.16537325, 15.78083 ] + }, + { + "time": 0.23333333, + "value": 15.70864, + "curve": [ 0.3091745, 15.628075, 0.408071, 46.6661 ] + }, + { + "time": 0.5, + "value": 63.59865, + "curve": [ 0.5603974, 74.72335, 0.7619598, 91.47623 ] + }, + { + "time": 0.9666666, + "value": 91.81103, + "curve": [ 1.0678477, 92.01352, 1.095855, 22.05076 ] + }, + { + "time": 1.1666666, + "value": 22.250694, + "curve": [ 1.1796615, 22.287384, 1.1757435, 56.16681 ] + }, + { + "time": 1.2, + "value": 56.16073, + "curve": [ 1.2463567, 56.1491, 1.2631978, 54.9383 ] + }, + { "time": 1.3333334, "value": 55.07567 } + ], + "translate": [ + { "x": -5.134582, "y": 11.552978 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -40.20753, + "curve": [ 0.0536731, -35.4564, 0.15, -31.119186 ] + }, + { + "time": 0.2, + "value": -31.119186, + "curve": [ 0.3083333, -31.119186, 0.5466946, -80.11781 ] + }, + { + "time": 0.6333333, + "value": -96.56404, + "curve": [ 0.6965202, -108.5585, 0.796608, -112.53702 ] + }, + { + "time": 0.8666667, + "value": -112.59852, + "curve": [ 1.1365902, -112.8355, 1.2737077, -49.19292 ] + }, + { "time": 1.3333334, "value": -40.20753 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.364543, + "curve": [ 0.022356797, 16.282055, 0.15, 30.81017 ] + }, + { + "time": 0.2, + "value": 30.81017, + "curve": [ 0.2583333, 30.81017, 0.375, 13.257755 ] + }, + { + "time": 0.4333333, + "value": 13.257755, + "curve": [ 0.5083333, 13.257755, 0.6584936, 15.046124 ] + }, + { + "time": 0.7333333, + "value": 14.982923, + "curve": [ 0.7894168, 14.935562, 0.8279614, 13.620555 ] + }, + { + "time": 0.8666667, + "value": 12.72069, + "curve": [ 0.8868754, 12.250854, 0.9843205, 9.831252 ] + }, + { + "time": 1.0333333, + "value": 8.599857, + "curve": [ 1.0447482, 8.31307, 1.0826218, 7.5548 ] + }, + { + "time": 1.1333333, + "value": 7.128548, + "curve": [ 1.1752198, 6.776476, 1.2833333, 6.182274 ] + }, + { "time": 1.3333334, "value": 6.182274 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -6.81118, + "curve": [ 6.198326E-4, -3.118248, 0.07407378, 14.658455 ] + }, + { + "time": 0.13333334, + "value": 14.658455, + "curve": [ 0.1879631, 14.802738, 0.2932519, 9.556835 ] + }, + { + "time": 0.3333333, + "value": 5.994396, + "curve": [ 0.3813762, 1.7243423, 0.55, -11.111454 ] + }, + { + "time": 0.6666667, + "value": -11.111454, + "curve": [ 0.8333333, -11.111454, 0.9333333, 22.544525 ] + }, + { + "time": 1.1, + "value": 22.544525, + "curve": [ 1.1583333, 22.544525, 1.275, -6.81118 ] + }, + { "time": 1.3333334, "value": -6.81118 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -6.81118, + "curve": [ 0, -3.171306, 0.04172101, 16.333447 ] + }, + { + "time": 0.06666667, + "value": 16.333447, + "curve": [ 0.21039502, 15.738186, 0.2083106, -12.064487 ] + }, + { + "time": 0.3333333, + "value": -12.206696, + "curve": [ 0.4166059, -12.301414, 0.5518459, -3.984657 ] + }, + { + "time": 0.6666667, + "value": 1.520172, + "curve": [ 0.7256673, 4.348827, 0.8166666, 4.99239 ] + }, + { + "time": 0.8666667, + "value": 4.99239, + "curve": [ 0.9006666, 4.99239, 0.912419, -29.0468 ] + }, + { + "time": 0.9666666, + "value": -27.445984, + "curve": [ 0.9874499, -26.832684, 1.0178803, -5.424507 ] + }, + { + "time": 1.0666667, + "value": -5.462139, + "curve": [ 1.1068223, -5.215767, 1.0952008, -33.51232 ] + }, + { + "time": 1.1333333, + "value": -33.27906, + "curve": [ 1.1622323, -33.56716, 1.191986, 8.044712 ] + }, + { + "time": 1.2666667, + "value": 7.86092, + "curve": [ 1.3024503, 7.77285, 1.312639, 2.7002945 ] + }, + { "time": 1.3333334, "value": 2.7002945 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -6.81118, + "curve": [ 0, 13.591494, 0.11666667, 18.21131 ] + }, + { + "time": 0.13333334, + "value": 18.21131, + "curve": [ 0.16666667, 18.21131, 0.2600757, 12.954233 ] + }, + { + "time": 0.3, + "value": 11.559322, + "curve": [ 0.3819209, 8.69708, 0.5500176, 9.432354 ] + }, + { + "time": 0.6666667, + "value": 9.31987, + "curve": [ 0.8425521, 9.150269, 0.9184876, -7.338802 ] + }, + { "time": 1.3333334, "value": -6.81118 } + ], + "translate": [ + { + "time": 0.6666667, + "curve": [ 0.7805555, 0, 0.9722685, 16.029846, 0.7805555, 0, 0.9722685, 0.9185066 ] + }, + { + "time": 1.1333333, + "x": 16.029846, + "y": 0.9185066, + "curve": [ 1.211065, 16.029846, 1.2805556, 0, 1.211065, 0.9185066, 1.2805556, 0 ] + }, + { "time": 1.3333334 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.81118, + "curve": [ 5.15683E-4, -3.8773804, 0.06299744, 16.181213 ] + }, + { + "time": 0.16666667, + "value": 16.13695, + "curve": [ 0.24208304, 16.104736, 0.24888137, 16.071587 ] + }, + { + "time": 0.3333333, + "value": 13.456192, + "curve": [ 0.4421503, 10.08622, 0.5731355, -2.199707 ] + }, + { + "time": 0.6, + "value": -6.041511, + "curve": [ 0.614021, -8.046585, 0.7166666, -33.44294 ] + }, + { + "time": 0.7666666, + "value": -33.44294, + "curve": [ 0.8094166, -33.44294, 0.834842, -31.31959 ] + }, + { + "time": 0.8666667, + "value": -27.36391, + "curve": [ 0.8738313, -26.473354, 0.9031405, -14.281486 ] + }, + { + "time": 0.9333333, + "value": -14.470863, + "curve": [ 0.9563123, -14.615005, 0.9435583, -25.90742 ] + }, + { + "time": 1, + "value": -25.96328, + "curve": [ 1.062178, -26.024826, 1.051079, -1.867569 ] + }, + { + "time": 1.0666667, + "value": -1.867569, + "curve": [ 1.096342, -1.867569, 1.096107, -16.08857 ] + }, + { + "time": 1.1333333, + "value": -16.08187, + "curve": [ 1.1694173, -16.07538, 1.1533196, -3.377556 ] + }, + { + "time": 1.2, + "value": -3.379791, + "curve": [ 1.2339214, -3.382614, 1.2706475, -6.074844 ] + }, + { "time": 1.3333334, "value": -6.074844 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.143766, + "curve": [ 0.008089039, 12.187704, 0.19672124, -23.52956 ] + }, + { + "time": 0.3333333, + "value": -23.954443, + "curve": [ 0.5092692, -23.954443, 0.6666667, -2.658644 ] + }, + { + "time": 0.7333333, + "value": -2.658644, + "curve": [ 0.7916667, -2.658644, 0.9083333, -13.318874 ] + }, + { + "time": 0.9666666, + "value": -13.318874, + "curve": [ 1.158066, -13.10643, 1.2405527, -1.5812836 ] + }, + { "time": 1.3333334, "value": -1.5812836 } + ], + "scale": [ + { + "curve": [ 0.04056496, 1, 0.05244635, 0.9616517, 0.04056496, 1, 0.05244635, 1.1370772 ] + }, + { + "time": 0.1, + "x": 0.9541517, + "y": 1.1370772, + "curve": [ 0.2021565, 0.9616517, 0.3177854, 1, 0.2021565, 1.1370772, 0.2518122, 1.0023715 ] + }, + { "time": 0.4666667 }, + { + "time": 1.0666667, + "x": 1.00178, + "curve": [ 1.0916667, 1.00178, 1.126085, 1.14276, 1.0916667, 1, 1.128311, 0.9745202 ] + }, + { + "time": 1.1666666, + "x": 1.1436756, + "y": 0.9733993, + "curve": [ 1.2036642, 1.1445105, 1.233349, 0.958515, 1.206164, 0.972245, 1.226671, 1.0624334 ] + }, + { + "time": 1.2666667, + "x": 0.9582605, + "y": 1.0626047, + "curve": [ 1.283691, 0.9581305, 1.2915703, 1.0012144, 1.28767, 1.0626947, 1.287913, 1.000691 ] + }, + { "time": 1.3333334 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.13816746, -2.400314, 0.2271148, -10.436157, 0.12329163, 1.045341, 0.2271148, 2.703059 ] + }, + { + "time": 0.3666667, + "x": -10.436157, + "y": 2.703059, + "curve": [ 0.4842861, -10.436157, 0.5852061, -5.626303, 0.4842861, 2.703059, 0.6293005, -23.622154 ] + }, + { + "time": 0.7333333, + "x": -2.2910004, + "y": -26.605564, + "curve": [ 0.8177672, -0.3898468, 0.9616582, 1.2078018, 0.8576196, -30.1698, 0.9715124, -28.75122 ] + }, + { + "time": 1.1, + "x": 1.2535706, + "y": -28.74897, + "curve": [ 1.1915684, 1.2838593, 1.2344676, 0.9751358, 1.224319, -28.746796, 1.2349995, -2.151868 ] + }, + { "time": 1.3333334 } + ] + }, + "hip": { + "translate": [ + { + "y": -45.45778, + "curve": [ 0.04166667, -0.0852939, 0.15, 15.21902, 0.03129127, 44.98263, 0.12330207, 289.72595 ] + }, + { + "time": 0.2, + "x": 15.21902, + "y": 415.8538, + "curve": [ 0.3315271, 15.21902, 0.5392024, -34.51724, 0.2711933, 532.9294, 0.4828083, 720.4994 ] + }, + { + "time": 0.7666666, + "x": -34.51724, + "y": 721.5962, + "curve": [ 0.8875864, -34.51724, 1.0574986, -21.949486, 1.0490158, 721.1747, 1.0975217, 379.8363 ] + }, + { + "time": 1.1333333, + "x": -15.66561, + "y": 266.7697, + "curve": [ 1.1441567, -14.768756, 1.187973, -10.528233, 1.150137, 213.71597, 1.171716, -61.31535 ] + }, + { + "time": 1.2333333, + "x": -6.5328, + "y": -61.33868, + "curve": [ 1.2715176, -3.2195106, 1.3106667, 0.04639988, 1.2905277, -61.36034, 1.296268, -44.80271 ] + }, + { "time": 1.3333334, "y": -45.45778 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.884876, + "curve": [ 0.10369815, 11.816757, 0.1789163, 11.152155 ] + }, + { + "time": 0.2, + "value": 10.077812, + "curve": [ 0.2546602, 7.292541, 0.4045541, -8.148415 ] + }, + { + "time": 0.4333333, + "value": -9.350786, + "curve": [ 0.5083333, -12.484213, 0.5950779, -13.13547 ] + }, + { + "time": 0.6666667, + "value": -12.605598, + "curve": [ 0.7137053, -12.257435, 0.8148956, -5.572529 ] + }, + { + "time": 0.8333333, + "value": -4.081579, + "curve": [ 0.882925, -0.0714054, 1.0454744, 12.765446 ] + }, + { + "time": 1.1, + "value": 15.060447, + "curve": [ 1.2079053, 19.60223, 1.2786733, 20.643595 ] + }, + { "time": 1.3333334, "value": 20.730635 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 28.284866, + "curve": [ 0.02212139, 25.120243, 0.18745896, -0.8935051 ] + }, + { + "time": 0.2, + "value": -2.518879, + "curve": [ 0.2570979, -9.918992, 0.3723359, -17.379135 ] + }, + { + "time": 0.4333333, + "value": -17.410477, + "curve": [ 0.5404287, -17.465504, 0.659186, -16.91498 ] + }, + { + "time": 0.7666666, + "value": -12.098708, + "curve": [ 0.9074817, -5.788708, 1.02477, 14.578896 ] + }, + { + "time": 1.1, + "value": 20.57702, + "curve": [ 1.1912643, 27.85358, 1.2833333, 29.665577 ] + }, + { "time": 1.3333334, "value": 29.665577 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": -7.141128 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": 18.55221 } + ], + "translate": [ + { "x": -176.39333, "y": 134.11803 } + ] + }, + "rear-leg-target": { + "rotate": [ + { "value": -38.43331 } + ], + "translate": [ + { "x": 85.00298, "y": -33.59399 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -115.63992, + "curve": [ 0.06674182, -117.17092, 0.125, -117.14553 ] + }, + { + "time": 0.16666667, + "value": -117.14553, + "curve": [ 0.225, -117.14553, 0.3323854, -108.76366 ] + }, + { + "time": 0.4, + "value": -107.15474, + "curve": [ 0.4798223, -105.25534, 0.6848591, -103.48536 ] + }, + { + "time": 0.7666666, + "value": -101.96748, + "curve": [ 0.8257901, -100.87048, 0.9185745, -92.3025 ] + }, + { + "time": 1, + "value": -92.2841, + "curve": [ 1.1131337, -92.25854, 1.2974604, -114.21733 ] + }, + { "time": 1.3333334, "value": -115.63992 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 12.807907, + "curve": [ 0.06666667, 12.807907, 0.2416681, 67.87932 ] + }, + { + "time": 0.2666667, + "value": 74.10752, + "curve": [ 0.3144626, 86.0155, 0.4544868, 92.22735 ] + }, + { + "time": 0.5666666, + "value": 92.23942, + "curve": [ 0.7529982, 92.25944, 0.9659008, 67.9441 ] + }, + { + "time": 1, + "value": 61.31865, + "curve": [ 1.0389384, 53.75296, 1.2178437, 12.682728 ] + }, + { "time": 1.3333334, "value": 12.807907 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.50333, + "curve": [ 0.04802571, 36.09633, 0.16843162, 20.44992 ] + }, + { + "time": 0.3, + "value": 20.44989, + "curve": [ 0.47593585, 20.449875, 0.5709888, 33.75796 ] + }, + { + "time": 0.6, + "value": 38.67331, + "curve": [ 0.642064, 45.80016, 0.6806553, 57.44073 ] + }, + { + "time": 0.7333333, + "value": 62.90692, + "curve": [ 0.828676, 72.80023, 0.9955254, 77.61066 ] + }, + { + "time": 1.0333333, + "value": 80.3669, + "curve": [ 1.0823636, 83.94128, 1.1476828, 90.60106 ] + }, + { + "time": 1.2, + "value": 90.60106, + "curve": [ 1.2475935, 90.46378, 1.316745, 53.06635 ] + }, + { "time": 1.3333334, "value": 49.06278 } + ] + }, + "torso": { + "rotate": [ + { + "value": -45.56914, + "curve": [ 0.0224493, -44.6064, 0.030192604, -39.06304 ] + }, + { + "time": 0.06666667, + "value": -35.29085, + "curve": [ 0.12008706, -29.766033, 0.2801849, -19.95289 ] + }, + { + "time": 0.4333333, + "value": -19.951965, + "curve": [ 0.6730827, -19.950523, 0.8707536, -22.3845 ] + }, + { + "time": 0.9666666, + "value": -27.08225, + "curve": [ 1.094143, -33.32597, 1.176246, -44.92588 ] + }, + { "time": 1.3333334, "value": -45.56914 } + ], + "translate": [ + { "x": -3.786807, "y": -0.7673931 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 4.52226, + "curve": [ 0.013146168, 2.325753, 0.09166667, -9.747728 ] + }, + { + "time": 0.13333334, + "value": -9.747728, + "curve": [ 0.175, -9.747728, 0.29143155, -1.2561474 ] + }, + { + "time": 0.3333333, + "value": 0.9645132, + "curve": [ 0.3585428, 2.3005335, 0.542815, 4.246187 ] + }, + { + "time": 0.6, + "value": 4.67707, + "curve": [ 0.6832887, 5.304644, 0.770924, 5.917166 ] + }, + { + "time": 0.8333333, + "value": 6.479486, + "curve": [ 0.8711326, 6.820064, 1.0833334, 11.36564 ] + }, + { + "time": 1.1666666, + "value": 11.36564, + "curve": [ 1.2083334, 11.36564, 1.316622, 6.180848 ] + }, + { "time": 1.3333334, "value": 4.52226 } + ], + "translate": [ + { + "curve": [ 0, 0, 0.08217777, -2.2354736, 0, 0, 0.08217777, -0.4165649 ] + }, + { + "time": 0.16666667, + "x": -2.980652, + "y": -0.55542, + "curve": [ 0.23188147, -2.2354736, 0.2977778, 0, 0.23188147, -0.4165649, 0.2977778, 0 ] + }, + { "time": 0.3333333, "curve": "stepped" }, + { + "time": 0.8666667, + "curve": [ 0.8891257, 0, 0.9115246, 0.2615417, 0.8891257, 0, 0.9124576, 0.0579729 ] + }, + { + "time": 0.9333333, + "x": 0.682602, + "y": 0.2299322, + "curve": [ 1.015697, 2.223103, 1.0952613, 5.900007, 1.0227647, 0.966601, 1.0952613, 1.987397 ] + }, + { + "time": 1.1666666, + "x": 6.465088, + "y": 2.1777496, + "curve": [ 1.229566, 5.746765, 1.2859417, 0, 1.229566, 1.9357758, 1.2859417, 0 ] + }, + { "time": 1.3333334 } + ] + }, + "torso3": { + "rotate": [ + { + "value": 4.52226, + "curve": [ 0.025, 4.52226, 0.075, -6.171848 ] + }, + { + "time": 0.1, + "value": -6.171848, + "curve": [ 0.175, -6.171848, 0.3806811, -0.7088436 ] + }, + { + "time": 0.4, + "value": -0.2465725, + "curve": [ 0.4465686, 0.8677432, 0.775, 4.844738 ] + }, + { + "time": 0.9, + "value": 4.844738, + "curve": [ 1.0083333, 4.844738, 1.225, 4.52226 ] + }, + { "time": 1.3333334, "value": 4.52226 } + ] + } + }, + "ik": { + "front-foot-ik": [ + { + "mix": 0, + "curve": [ 0.3, 0, 0.9, 1, 0.3, 0, 0.9, 0 ] + }, + { "time": 1.2 } + ], + "front-leg-ik": [ + { + "mix": 0, + "bendPositive": false, + "curve": [ 0.3, 0, 0.9, 1, 0.3, 0, 0.9, 0 ] + }, + { "time": 1.2, "bendPositive": false } + ], + "rear-foot-ik": [ + { "mix": 0 } + ], + "rear-leg-ik": [ + { "mix": 0, "bendPositive": false } + ] + }, + "events": [ + { "time": 1.2, "name": "footstep" } + ] + }, + "portal": { + "slots": { + "clipping": { + "attachment": [ + { "name": "clipping" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "time": 0.9, "name": "mouth-grind" }, + { "time": 2.266667, "name": "mouth-smile" } + ] + }, + "portal-bg": { + "attachment": [ + { "name": "portal-bg" }, + { "time": 3 } + ] + }, + "portal-flare1": { + "attachment": [ + { "time": 1.1, "name": "portal-flare1" }, + { "time": 1.1333333, "name": "portal-flare2" }, + { "time": 1.1666666, "name": "portal-flare3" }, + { "time": 1.2, "name": "portal-flare1" }, + { "time": 1.2333333, "name": "portal-flare2" }, + { "time": 1.2666667, "name": "portal-flare1" }, + { "time": 1.3333334 } + ] + }, + "portal-flare2": { + "attachment": [ + { "time": 1.1, "name": "portal-flare2" }, + { "time": 1.1333333, "name": "portal-flare3" }, + { "time": 1.1666666, "name": "portal-flare1" }, + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333333, "name": "portal-flare3" }, + { "time": 1.2666667 } + ] + }, + "portal-flare3": { + "attachment": [ + { "time": 1.2, "name": "portal-flare3" }, + { "time": 1.2333333, "name": "portal-flare2" }, + { "time": 1.2666667 } + ] + }, + "portal-flare4": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333333, "name": "portal-flare1" }, + { "time": 1.2666667, "name": "portal-flare2" }, + { "time": 1.3333334 } + ] + }, + "portal-flare5": { + "attachment": [ + { "time": 1.2333333, "name": "portal-flare3" }, + { "time": 1.2666667, "name": "portal-flare1" }, + { "time": 1.3333334 } + ] + }, + "portal-flare6": { + "attachment": [ + { "time": 1.2666667, "name": "portal-flare3" }, + { "time": 1.3333334 } + ] + }, + "portal-flare7": { + "attachment": [ + { "time": 1.1333333, "name": "portal-flare2" }, + { "time": 1.1666666 } + ] + }, + "portal-flare8": { + "attachment": [ + { "time": 1.2, "name": "portal-flare3" }, + { "time": 1.2333333, "name": "portal-flare2" }, + { "time": 1.2666667 } + ] + }, + "portal-flare9": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333333, "name": "portal-flare3" }, + { "time": 1.2666667, "name": "portal-flare1" }, + { "time": 1.3 } + ] + }, + "portal-flare10": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333333, "name": "portal-flare1" }, + { "time": 1.2666667, "name": "portal-flare3" }, + { "time": 1.3 } + ] + }, + "portal-shade": { + "attachment": [ + { "name": "portal-shade" }, + { "time": 3 } + ] + }, + "portal-streaks1": { + "attachment": [ + { "name": "portal-streaks1" }, + { "time": 3 } + ] + }, + "portal-streaks2": { + "attachment": [ + { "name": "portal-streaks2" }, + { "time": 3 } + ] + } + }, + "bones": { + "back-foot-tip": { + "rotate": [ + { + "time": 1.0666667, + "value": 56.07264, + "curve": [ 1.137642, 59.2081, 1.1920346, 59.64967 ] + }, + { + "time": 1.2333333, + "value": 59.45566, + "curve": [ 1.29476, 59.16713, 1.45, 22.53593 ] + }, + { "time": 1.4666667, "value": -0.8375263 } + ] + }, + "clipping": { + "translate": [ + { "x": -476.5466, "y": 2.27098 } + ], + "scale": [ + { "x": 0.9833469, "y": 1.197023 } + ] + }, + "flare1": { + "rotate": [ + { "time": 1.1, "value": 8.19671 } + ], + "translate": [ + { "time": 1.1, "x": -19.965195, "y": 149.6754 }, + { "time": 1.2, "x": 3.848387, "y": 152.43144 }, + { "time": 1.2333333, "x": -15.415985, "y": 152.2934 } + ], + "scale": [ + { + "time": 1.1, + "x": 0.8052482, + "y": 0.8052482, + "curve": [ 1.1185277, 0.7628392, 1.1604003, 1.161824, 1.1166667, 0.8052482, 1.15, 0.6051311 ] + }, + { + "time": 1.1666666, + "x": 1.279132, + "y": 0.6051311, + "curve": [ 1.176861, 1.4699727, 1.1916667, 2.15059, 1.175, 0.6051311, 1.1916667, 0.9112708 ] + }, + { + "time": 1.2, + "x": 2.15059, + "y": 0.9112708, + "curve": [ 1.2083334, 2.15059, 1.230963, 1.6683322, 1.2083334, 0.9112708, 1.226749, 0.8440541 ] + }, + { + "time": 1.2333333, + "x": 1.607645, + "y": 0.8052482, + "curve": [ 1.2490696, 1.2047595, 1.2833333, 0.5473236, 1.253722, 0.6850893, 1.2833333, 0.4158778 ] + }, + { "time": 1.3, "x": 0.5473236, "y": 0.4158778 } + ], + "shear": [ + { "time": 1.1, "y": 4.625496 }, + { "time": 1.2333333, "x": -5.742333, "y": 4.625496 } + ] + }, + "flare2": { + "rotate": [ + { "time": 1.1, "value": 12.2888 } + ], + "translate": [ + { "time": 1.1, "x": -8.631058, "y": 132.9583 }, + { "time": 1.2, "x": 4.346024, "y": 132.92914 } + ], + "scale": [ + { "time": 1.1, "x": 0.8635677, "y": 0.8635677 }, + { "time": 1.1666666, "x": 0.9445455, "y": 0.9445455 }, + { "time": 1.2, "x": 1.5108734, "y": 1.0808847 } + ], + "shear": [ + { "time": 1.1, "y": 24.02799 } + ] + }, + "flare3": { + "rotate": [ + { "time": 1.1666666, "value": 2.877605 } + ], + "translate": [ + { "time": 1.1666666, "x": 3.244141, "y": 114.80896 } + ], + "scale": [ + { "time": 1.1666666, "x": 0.6682259, "y": 0.6682259 } + ], + "shear": [ + { "time": 1.1666666, "y": 38.59206 } + ] + }, + "flare4": { + "rotate": [ + { "time": 1.1666666, "value": -8.636183 } + ], + "translate": [ + { "time": 1.1666666, "x": -3.8203425, "y": 194.06 }, + { "time": 1.2666667, "x": -1.821258, "y": 198.46616, "curve": "stepped" }, + { "time": 1.3, "x": -1.9382625, "y": 187.80707 } + ], + "scale": [ + { "time": 1.1666666, "x": 0.5447413, "y": 0.5447413 }, + { "time": 1.2666667, "x": 0.7566731, "y": 0.7566731 } + ], + "shear": [ + { "time": 1.1666666, "x": 7.419382, "y": -22.03984 } + ] + }, + "flare5": { + "translate": [ + { "time": 1.2, "x": -11.174988, "y": 176.42078 }, + { "time": 1.2333333, "x": -8.563156, "y": 179.0431, "curve": "stepped" }, + { "time": 1.3, "x": -14.569656, "y": 168.69334 } + ], + "scale": [ + { "time": 1.2333333, "x": 1.146029 }, + { "time": 1.3, "x": 0.7027114, "y": 0.6102919 } + ], + "shear": [ + { "time": 1.2, "x": 6.897617 } + ] + }, + "flare6": { + "rotate": [ + { "time": 1.2333333, "value": -5.36348 }, + { "time": 1.2666667, "value": -0.5357718 } + ], + "translate": [ + { "time": 1.2333333, "x": 14.51686, "y": 204.6748 }, + { "time": 1.2666667, "x": 19.15874, "y": 212.8976, "curve": "stepped" }, + { "time": 1.3, "x": 9.226883, "y": 202.8528 } + ], + "scale": [ + { "time": 1.2333333, "x": 0.7772842, "y": 0.4904852 }, + { "time": 1.2666667, "x": 0.7772842, "y": 0.6571744 }, + { "time": 1.3, "x": 0.4746967, "y": 0.4013442 } + ] + }, + "flare7": { + "rotate": [ + { "time": 1.1, "value": 5.982827 }, + { "time": 1.1333333, "value": 32.82419 } + ], + "translate": [ + { "time": 1.1, "x": -6.340728, "y": 112.97925 }, + { "time": 1.1333333, "x": 2.662873, "y": 111.59957 } + ], + "scale": [ + { "time": 1.1, "x": 0.5884216, "y": 0.5884216 } + ], + "shear": [ + { "time": 1.1333333, "x": -19.934156 } + ] + }, + "flare8": { + "rotate": [ + { "time": 1.2333333, "value": -6.846075 } + ], + "translate": [ + { "time": 1.1666666, "x": 66.67122, "y": 125.5245, "curve": "stepped" }, + { "time": 1.2, "x": 58.23973, "y": 113.53304, "curve": "stepped" }, + { "time": 1.2333333, "x": 40.14647, "y": 114.69013 } + ], + "scale": [ + { "time": 1.1666666, "x": 1.313432, "y": 1.2030426 }, + { "time": 1.2333333, "x": 1.0375577, "y": 0.9503547 } + ], + "shear": [ + { "time": 1.2, "y": -13.007996 } + ] + }, + "flare9": { + "rotate": [ + { "time": 1.1666666, "value": 2.903958 } + ], + "translate": [ + { "time": 1.1666666, "x": 28.44858, "y": 151.3508, "curve": "stepped" }, + { "time": 1.2, "x": 48.80466, "y": 191.08945, "curve": "stepped" }, + { "time": 1.2333333, "x": 52.00254, "y": 182.52245, "curve": "stepped" }, + { "time": 1.2666667, "x": 77.01112, "y": 195.957 } + ], + "scale": [ + { "time": 1.1666666, "x": 0.871415, "y": 1.0726658 }, + { "time": 1.2, "x": 0.9265085, "y": 0.9443878 }, + { "time": 1.2333333, "x": 1.1650134, "y": 1.335881 } + ], + "shear": [ + { "time": 1.1666666, "x": 7.952582, "y": 25.483856 } + ] + }, + "flare10": { + "rotate": [ + { "time": 1.1666666, "value": 2.183265 } + ], + "translate": [ + { "time": 1.1666666, "x": 55.64471, "y": 137.64316, "curve": "stepped" }, + { "time": 1.2, "x": 90.49197, "y": 151.0721, "curve": "stepped" }, + { "time": 1.2333333, "x": 114.0629, "y": 153.05193, "curve": "stepped" }, + { "time": 1.2666667, "x": 90.4351, "y": 164.60985 } + ], + "scale": [ + { "time": 1.1666666, "x": 2.657358, "y": 0.8913977 }, + { "time": 1.2, "x": 3.313913, "y": 1.425258 }, + { "time": 1.2333333, "x": 2.871108, "y": 0.9239545 }, + { "time": 1.2666667, "x": 2.3166406, "y": 0.774553 } + ], + "shear": [ + { "time": 1.1666666, "x": -1.3484306 } + ] + }, + "front-bracer": { + "rotate": [ + { + "time": 1.0666667, + "value": 0.6630783, + "curve": [ 1.1083333, 0.6630783, 1.2209586, 44.94986 ] + }, + { + "time": 1.2333333, + "value": 49.25002, + "curve": [ 1.2626122, 59.42411, 1.341795, 68.06456 ] + }, + { + "time": 1.3666667, + "value": 68.33766, + "curve": [ 1.4087822, 68.80012, 1.4755195, 4.900186 ] + }, + { + "time": 1.5, + "value": -2.049054, + "curve": [ 1.5290676, -10.300376, 1.694666, -15.950796 ] + }, + { + "time": 1.7333333, + "value": -17.37979, + "curve": [ 1.807065, -20.10463, 1.877747, -21.18554 ] + }, + { + "time": 1.9333333, + "value": -21.075684, + "curve": [ 2.073296, -20.799067, 2.146349, -7.634647 ] + }, + { + "time": 2.166667, + "value": -3.6379185, + "curve": [ 2.1857605, 0.1180954, 2.274763, 15.28247 ] + }, + { + "time": 2.333333, + "value": 21.77728, + "curve": [ 2.392207, 28.30568, 2.574896, 37.6557 ] + }, + { + "time": 2.7, + "value": 39.43075, + "curve": [ 2.946578, 42.92933, 3.020272, 42.46212 ] + }, + { "time": 3.166667, "value": 42.46212 } + ] + }, + "front-fist": { + "rotate": [ + { + "time": 1.1, + "value": 6.320977, + "curve": [ 1.1101445, 3.311444, 1.1529943, -5.070633 ] + }, + { + "time": 1.2333333, + "value": -5.12947, + "curve": [ 1.3112984, -5.18657, 1.3644074, 34.64959 ] + }, + { + "time": 1.4666667, + "value": 34.53249, + "curve": [ 1.5743637, 34.40917, 1.5473908, -55.78042 ] + }, + { + "time": 1.8666667, + "value": -54.70204, + "curve": [ 1.9466665, -54.70204, 2.029893, -53.93735 ] + }, + { + "time": 2.1333334, + "value": -42.44453, + "curve": [ 2.214545, -33.42147, 2.3576686, -4.427096 ] + }, + { + "time": 2.4, + "value": 0.03237247, + "curve": [ 2.443959, 4.663282, 2.53568, 8.200353 ] + }, + { + "time": 2.6333334, + "value": 8.197518, + "curve": [ 2.733491, 8.194706, 2.804373, -0.6711826 ] + }, + { + "time": 2.9, + "value": -0.8171186, + "curve": [ 3.127076, -1.163653, 3.0930974, 0 ] + }, + { "time": 3.166667 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "time": 1.0666667, + "value": 32.08181, + "curve": [ 1.1083333, 32.08181, 1.1916667, 35.16107 ] + }, + { + "time": 1.2333333, + "value": 35.16107, + "curve": [ 1.2583333, 35.16107, 1.3171477, 2.227778 ] + }, + { + "time": 1.3333334, + "value": -4.73641, + "curve": [ 1.3505374, -12.13869, 1.428912, -34.96195 ] + }, + { + "time": 1.6, + "value": -34.76919, + "curve": [ 1.7646465, -34.5837, 1.8974327, -17.25133 ] + }, + { "time": 1.9333333 } + ], + "translate": [ + { "x": -899.4143, "y": 4.465324, "curve": "stepped" }, + { + "time": 1.0666667, + "x": -533.9344, + "y": 363.7509, + "curve": [ 1.0741596, -480.8532, 1.180085, -261.3058, 1.093905, 362.3, 1.195378, 267.7686 ] + }, + { + "time": 1.2333333, + "x": -201.2317, + "y": 199.9273, + "curve": [ 1.2686588, -161.37817, 1.2941303, -140.3243, 1.27432, 126.66837, 1.3083333, 77.12312 ] + }, + { + "time": 1.3333334, + "x": -124.0785, + "y": 0.20110783, + "curve": [ 1.4261836, -85.60126, 1.6333333, -69.06195, 1.4497523, 0.4776425, 1.6333333, 0 ] + }, + { "time": 1.7333333, "x": -69.06195 } + ] + }, + "front-foot-tip": { + "rotate": [ + { "time": 1.0666667, "value": 42.55, "curve": "stepped" }, + { "time": 1.1333333, "value": 42.55 }, + { "time": 1.2333333, "value": 17.713627 }, + { "time": 1.3666667, "value": 3.6307945 }, + { "time": 1.4333333 } + ] + }, + "front-shoulder": { + "translate": [ + { + "time": 1.3333334, + "curve": [ 1.4878056, 0, 1.7172107, 0.2088337, 1.4878056, 0, 1.6875666, -30.28685 ] + }, + { + "time": 1.9, + "x": 0.8290405, + "y": -30.28685, + "curve": [ 2.078422, 1.434429, 2.274303, 2.877649, 2.070929, -30.28685, 2.28912, 4.477253 ] + }, + { + "time": 2.4333334, + "x": 2.885666, + "y": 4.593845, + "curve": [ 2.604077, 2.894274, 2.6767845, -0.67696, 2.570489, 4.704731, 2.6941264, -2.4257364 ] + }, + { + "time": 2.766667, + "x": -0.6713352, + "y": -2.4671345, + "curve": [ 2.865951, -0.665121, 2.985806, -0.07066536, 2.881529, -2.4677744, 3.0362694, -0.06334877 ] + }, + { "time": 3.166667 } + ] + }, + "front-thigh": { + "translate": [ + { "time": 1.1, "x": -6.409607, "y": 18.23201, "curve": "stepped" }, + { "time": 1.1333333, "x": -6.409607, "y": 18.23201 }, + { "time": 1.2, "x": 1.6055756, "y": 3.6637325 }, + { "time": 1.2333333, "x": 4.500519, "y": -3.147476 }, + { "time": 1.3666667, "x": -3.7928925, "y": 2.9377594 }, + { "time": 1.4, "x": -8.373123, "y": 8.724655 }, + { "time": 1.4333333, "x": -11.259293, "y": 16.99144 }, + { "time": 1.4666667, "x": -9.890228, "y": 24.72952, "curve": "stepped" }, + { "time": 1.8666667, "x": -9.890228, "y": 24.72952 }, + { "time": 2.1 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "time": 1.0666667, + "value": 118.03253, + "curve": [ 1.0746608, 93.63927, 1.357676, -34.03235 ] + }, + { + "time": 1.6666666, + "value": -33.93648, + "curve": [ 1.807726, -33.89273, 1.879483, -25.00093 ] + }, + { + "time": 1.9666667, + "value": -25.19053, + "curve": [ 2.0903125, -25.459396, 2.312267, -34.57672 ] + }, + { + "time": 2.3666666, + "value": -38.36267, + "curve": [ 2.464673, -45.18345, 2.557451, -60.09786 ] + }, + { + "time": 2.833333, + "value": -61.09861, + "curve": [ 2.843413, -61.06094, 3.160012, -60.86928 ] + }, + { "time": 3.166667, "value": -60.86928 } + ] + }, + "gun": { + "rotate": [ + { + "time": 1.2666667, + "curve": [ 1.35, 0, 1.549312, 7.491627 ] + }, + { + "time": 1.6, + "value": 9.502806, + "curve": [ 1.6634295, 12.019538, 1.8455456, 19.57741 ] + }, + { + "time": 1.9333333, + "value": 19.430107, + "curve": [ 1.9850718, 19.403255, 2.057294, 2.97505 ] + }, + { + "time": 2.2, + "value": 2.9547074, + "curve": [ 2.3040185, 3.552295, 2.458333, 10.79515 ] + }, + { + "time": 2.5, + "value": 10.79515, + "curve": [ 2.642083, 10.79515, 2.8727686, -2.5369945 ] + }, + { + "time": 2.9333334, + "value": -2.54512, + "curve": [ 3.089635, -2.5660934, 3.080185, 0 ] + }, + { "time": 3.166667 } + ] + }, + "hair1": { + "rotate": [ + { + "time": 1.2333333, + "curve": [ 1.2833333, 0, 1.3487782, 3.988499 ] + }, + { + "time": 1.4333333, + "value": 6.581089, + "curve": [ 1.49729, 8.542103, 1.6833333, 9.353794 ] + }, + { + "time": 1.7666667, + "value": 9.353794, + "curve": [ 1.825, 9.353794, 1.9451995, -8.706432 ] + }, + { + "time": 2, + "value": -11.145393, + "curve": [ 2.057664, -13.711807, 2.2, -14.967854 ] + }, + { + "time": 2.266667, + "value": -14.967854, + "curve": [ 2.3666666, -14.967854, 2.5666666, 18.77291 ] + }, + { + "time": 2.666667, + "value": 18.77291, + "curve": [ 2.733333, 18.77291, 2.816955, 8.285915 ] + }, + { + "time": 2.8666666, + "value": 6.508964, + "curve": [ 2.987968, 2.173035, 3.058226, 0 ] + }, + { "time": 3.166667 } + ] + }, + "hair2": { + "rotate": [ + { + "time": 1.0666667, + "value": 26.193165, + "curve": [ 1.1583333, 26.193165, 1.367548, 25.99863 ] + }, + { + "time": 1.4333333, + "value": 24.43079, + "curve": [ 1.5339297, 22.033314, 1.9999084, -29.14474 ] + }, + { + "time": 2.2, + "value": -29.14474, + "curve": [ 2.291666, -29.14474, 2.475, 6.709568 ] + }, + { + "time": 2.5666666, + "value": 6.709568, + "curve": [ 2.675, 6.709568, 2.81385, -5.059501 ] + }, + { + "time": 2.9, + "value": -5.059501, + "curve": [ 2.972896, -5.059501, 3.12329, 0 ] + }, + { "time": 3.166667 } + ] + }, + "hair3": { + "rotate": [ + { + "time": 1.4333333, + "curve": [ 1.45, 0, 1.4517294, 11.28679 ] + }, + { + "time": 1.5, + "value": 11.212746, + "curve": [ 1.596384, 11.064898, 1.572934, -14.166687 ] + }, + { + "time": 1.7333333, + "value": -20.39627, + "curve": [ 1.8514245, -24.982697, 1.9430795, -28.45235 ] + }, + { + "time": 2.2, + "value": -28.748043, + "curve": [ 2.3166666, -28.748043, 2.55, 7.042751 ] + }, + { + "time": 2.666667, + "value": 7.042751, + "curve": [ 2.791667, 7.042751, 2.885336, -5.194847 ] + }, + { + "time": 2.966667, + "value": -5.194847, + "curve": [ 3.037153, -5.194847, 3.09618, 0 ] + }, + { "time": 3.166667 } + ] + }, + "hair4": { + "rotate": [ + { + "time": 1.0666667, + "value": 5.207474, + "curve": [ 1.1083333, 5.207474, 1.1916667, 26.19316 ] + }, + { + "time": 1.2333333, + "value": 26.19316, + "curve": [ 1.3166667, 26.19316, 1.4833333, 10.625244 ] + }, + { + "time": 1.5666667, + "value": 10.625244, + "curve": [ 1.626899, 10.625244, 1.6422284, 17.90603 ] + }, + { + "time": 1.7, + "value": 17.936363, + "curve": [ 1.761277, 17.968536, 1.774489, 8.223702 ] + }, + { + "time": 1.8, + "value": 3.326546, + "curve": [ 1.8392456, -4.207123, 1.95, -22.67175 ] + }, + { + "time": 2, + "value": -22.67175, + "curve": [ 2.025, -22.67175, 2.122745, -21.85688 ] + }, + { + "time": 2.166667, + "value": -18.710205, + "curve": [ 2.228136, -14.306343, 2.293769, -0.2952652 ] + }, + { + "time": 2.3666666, + "value": 6.364601, + "curve": [ 2.433311, 12.453148, 2.493856, 19.2148 ] + }, + { + "time": 2.6, + "value": 19.2148, + "curve": [ 2.7287974, 19.2148, 2.853675, 6.745182 ] + }, + { + "time": 2.9333334, + "value": 4.623581, + "curve": [ 3.089936, 0.4526749, 3.061636, 0 ] + }, + { "time": 3.166667 } + ] + }, + "head": { + "rotate": [ + { + "time": 1.0666667, + "value": 16.39647, + "curve": [ 1.132726, 9.897343, 1.206983, 1.865156 ] + }, + { + "time": 1.3333334, + "value": 1.6744652, + "curve": [ 1.45959, 1.5641422, 1.5468354, 47.54059 ] + }, + { + "time": 1.7333333, + "value": 47.55231, + "curve": [ 1.8973297, 47.56262, 2.0415375, 5.680721 ] + }, + { + "time": 2.0666666, + "value": 0.8596192, + "curve": [ 2.074335, -0.611648, 2.086115, -2.8090944 ] + }, + { + "time": 2.1, + "value": -5.305158, + "curve": [ 2.145329, -13.066894, 2.215558, -23.64832 ] + }, + { + "time": 2.266667, + "value": -23.70736, + "curve": [ 2.33438, -23.78559, 2.426235, -13.429327 ] + }, + { + "time": 2.466667, + "value": -9.18142, + "curve": [ 2.497845, -5.905727, 2.6044135, 2.527153 ] + }, + { + "time": 2.666667, + "value": 2.524849, + "curve": [ 2.737512, 2.239935, 2.8498166, -8.761124 ] + }, + { + "time": 2.9333334, + "value": -8.665838, + "curve": [ 3.036013, -8.548687, 3.089751, -7.094767 ] + }, + { "time": 3.166667, "value": -6.74768 } + ], + "scale": [ + { + "time": 1.3333334, + "curve": [ 1.3916667, 1, 1.5261834, 1.0002627, 1.3916667, 1, 1.5083333, 1.0427603 ] + }, + { + "time": 1.5666667, + "x": 0.9917999, + "y": 1.0427603, + "curve": [ 1.597676, 0.9853176, 1.6760827, 0.9547964, 1.583889, 1.0427603, 1.6718276, 1.04001 ] + }, + { + "time": 1.7333333, + "x": 0.954496, + "y": 1.028987, + "curve": [ 1.8428998, 0.9539212, 1.9333333, 1, 1.8252528, 1.0125135, 1.9333333, 1 ] + }, + { "time": 2 } + ] + }, + "head-control": { + "translate": [ + { + "time": 1.2333333, + "curve": [ 1.250452, 0, 1.4742417, 6.891655, 1.250452, 0, 1.4959948, 0.979061 ] + }, + { + "time": 1.6666666, + "x": 11.99051, + "y": -6.416015, + "curve": [ 1.742927, 14.01123, 1.86048, 14.329775, 1.78509, -11.547222, 1.86048, -27.10343 ] + }, + { + "time": 1.9666667, + "x": 13.907715, + "y": -26.87759, + "curve": [ 2.0738876, 13.48729, 2.243662, 8.129967, 2.0738876, -26.65262, 2.214605, -21.78112 ] + }, + { + "time": 2.3, + "x": 6.068374, + "y": -16.63897, + "curve": [ 2.415614, 1.8376002, 2.496731, -1.4142227, 2.4174454, -9.566895, 2.526046, -1.7173506 ] + }, + { + "time": 2.5666666, + "x": -3.780899, + "y": -1.70785, + "curve": [ 2.661321, -6.98407, 2.760468, -8.76135, 2.6924124, -1.6784445, 2.821366, -15.747234 ] + }, + { + "time": 2.9, + "x": -8.31778, + "y": -16.697033, + "curve": [ 2.961594, -8.12198, 3.082401, -0.04269974, 2.958362, -17.38989, 3.088793, 0 ] + }, + { "time": 3.166667 } + ] + }, + "hip": { + "rotate": [ + { + "time": 1.0666667, + "value": 22.74372, + "curve": [ 1.162949, 18.836576, 1.7701715, 8.767227 ] + }, + { + "time": 1.9, + "value": 7.816543, + "curve": [ 2.271076, 5.099299, 2.890143, 0 ] + }, + { "time": 3.166667 } + ], + "translate": [ + { "x": -899.4144, "y": 4.465348, "curve": "stepped" }, + { + "time": 1.0666667, + "x": -694.1554, + "y": 183.27863, + "curve": [ 1.0907408, -602.081, 1.1377125, -427.5905, 1.11462, 185.6005, 1.1708443, 133.18236 ] + }, + { + "time": 1.2333333, + "x": -316.9727, + "y": 55.29398, + "curve": [ 1.3169248, -220.2709, 1.5121044, -123.21176, 1.2707292, 8.68248, 1.461251, -83.18494 ] + }, + { + "time": 1.6, + "x": -95.52516, + "y": -112.22975, + "curve": [ 1.718346, -58.24684, 2.036681, -22.542114, 1.8576818, -166.17126, 2.109496, -31.40001 ] + }, + { + "time": 2.166667, + "x": -14.823854, + "y": -31.12268, + "curve": [ 2.293638, -7.284553, 2.4421756, -7.199183, 2.27447, -30.599716, 2.392674, -36.75752 ] + }, + { + "time": 2.6, + "x": -7.200024, + "y": -36.9614, + "curve": [ 2.854397, -7.20138, 3.0706224, -11.871496, 2.785653, -36.26684, 3.0823655, -22.98303 ] + }, + { "time": 3.166667, "x": -11.972925, "y": -23.15497 } + ] + }, + "neck": { + "rotate": [ + { + "time": 1.0666667, + "value": -3.573036, + "curve": [ 1.145731, -3.655647, 1.150022, -13.50034 ] + }, + { + "time": 1.2333333, + "value": -13.500336, + "curve": [ 1.4281882, -13.500328, 1.4427327, 11.58388 ] + }, + { + "time": 1.5666667, + "value": 11.418663, + "curve": [ 1.658189, 11.296658, 1.775, 3.7834435 ] + }, + { + "time": 1.8666667, + "value": 3.7834435, + "curve": [ 1.92043, 3.7834435, 2.036419, 8.012905 ] + }, + { + "time": 2.1, + "value": 7.932539, + "curve": [ 2.265776, 7.723005, 2.420065, 3.864254 ] + }, + { + "time": 2.533333, + "value": 3.864254, + "curve": [ 2.783333, 3.864254, 3.0040054, 3.7834435 ] + }, + { "time": 3.166667, "value": 3.7834435 } + ] + }, + "portal": { + "rotate": [ + {}, + { "time": 3.166667, "value": 600 } + ] + }, + "portal-root": { + "translate": [ + { + "x": -458.3517, + "y": 105.19089, + "curve": [ 0.3327713, -458.2243, 0.6693856, -457.8555, 0.9339023, 105.19089, 0.6710526, 105.19087 ] + }, + { + "time": 1, + "x": -456.0179, + "y": 105.19087, + "curve": [ 1.338546, -454.1363, 2.208128, -447.2761, 1.35, 105.19087, 2.05, 105.19089 ] + }, + { + "time": 2.4, + "x": -439.11795, + "y": 105.19089, + "curve": [ 2.462957, -436.4411, 2.5015614, -432.91815, 2.487001, 105.19089, 2.5115554, 105.09302 ] + }, + { + "time": 2.6, + "x": -432.5778, + "y": 105.09302, + "curve": [ 2.7837846, -431.9423, 2.977665, -446.5953, 2.771785, 105.09302, 2.9331985, 105.19088 ] + }, + { "time": 3.033333, "x": -457.4193, "y": 105.19087 } + ], + "scale": [ + { + "x": 0.002608195, + "y": 0.005767732, + "curve": [ 0.3290564, 0.04379778, 0.3469796, 0.11661968, 0.3290564, 0.09685391, 0.3697024, 0.2491073 ] + }, + { + "time": 0.4, + "x": 0.17486975, + "y": 0.3867049, + "curve": [ 0.629778, 0.619394, 0.6625375, 0.7229963, 0.6094745, 1.338042, 0.6452585, 1.5238047 ] + }, + { + "time": 0.7333333, + "x": 0.7239759, + "y": 1.519575, + "curve": [ 0.798251, 0.7248562, 0.906569, 0.6467103, 0.796669, 1.5166358, 0.8947418, 1.4241506 ] + }, + { + "time": 1, + "x": 0.6450333, + "y": 1.4264193, + "curve": [ 1.0945556, 0.6433359, 1.1387775, 0.688223, 1.088583, 1.4283284, 1.1145828, 1.5133462 ] + }, + { + "time": 1.2333333, + "x": 0.685406, + "y": 1.515699, + "curve": [ 1.3248137, 0.6826806, 1.5084356, 0.6355962, 1.342993, 1.5178717, 1.4665205, 1.3996894 ] + }, + { + "time": 1.6, + "x": 0.6335794, + "y": 1.40109, + "curve": [ 1.7278892, 0.6307624, 1.9456956, 0.6868346, 1.7224177, 1.4023747, 1.9238144, 1.5224925 ] + }, + { + "time": 2.0666666, + "x": 0.688478, + "y": 1.5224925, + "curve": [ 2.189336, 0.6901446, 2.288777, 0.6487232, 2.141666, 1.5224925, 2.265034, 1.416818 ] + }, + { + "time": 2.4, + "x": 0.6501576, + "y": 1.4264193, + "curve": [ 2.493888, 0.6513685, 2.5038354, 0.7662067, 2.5077126, 1.4340816, 2.5430565, 1.5664625 ] + }, + { + "time": 2.6, + "x": 0.7658835, + "y": 1.568168, + "curve": [ 2.730467, 0.7649903, 3.005668, 0.09835615, 2.76687, 1.5643423, 2.997261, 0.09953152 ] + }, + { "time": 3.033333, "x": 0.006712961, "y": 0.014844964 } + ] + }, + "portal-shade": { + "translate": [ + { "x": -29.67969 } + ], + "scale": [ + { "x": 0.7142011, "y": 0.7142011 } + ] + }, + "portal-streaks1": { + "rotate": [ + {}, + { "time": 3.166667, "value": 1200 } + ], + "translate": [ + { + "x": 15.154297, + "curve": [ 0.16216215, 15.154297, 0.4324325, 12.600327, 0.16216215, -3.051758E-5, 0.4324325, -3.8612854 ] + }, + { + "time": 0.6666667, + "x": 10.89768, + "y": -6.435455, + "curve": [ 0.7941177, 9.93388, 0.9117647, 9.21103, 0.7941177, -7.70707, 0.9117647, -8.660782 ] + }, + { + "time": 1, + "x": 9.21103, + "y": -8.660782, + "curve": [ 1.0833334, 9.21103, 1.25, 21.52939, 1.0833334, -8.660782, 1.265098, -4.903187 ] + }, + { + "time": 1.3333334, + "x": 21.52939, + "y": -3.1892934, + "curve": [ 1.5, 21.52939, 1.939234, 12.30119, 1.4457347, -0.3660576, 1.9, 6.26146 ] + }, + { + "time": 2.0666666, + "x": 11.25953, + "y": 6.26146, + "curve": [ 2.238511, 9.854843, 2.388786, 9.679258, 2.208333, 6.26146, 2.523289, 0.5087212 ] + }, + { + "time": 2.5666666, + "x": 9.386615, + "y": -0.799057, + "curve": [ 2.657042, 9.23793, 2.841667, 9.21103, 2.646262, -3.198731, 2.841667, -8.905502 ] + }, + { "time": 2.9333334, "x": 9.21103, "y": -8.905502 } + ], + "scale": [ + { + "curve": [ 0.16666667, 1, 0.5, 1.0526782, 0.16666667, 1, 0.5, 1.0526782 ] + }, + { + "time": 0.6666667, + "x": 1.0526782, + "y": 1.0526782, + "curve": [ 0.8333333, 1.0526782, 1.1666666, 0.98572, 0.8333333, 1.0526782, 1.1666666, 0.98572 ] + }, + { + "time": 1.3333334, + "x": 0.98572, + "y": 0.98572, + "curve": [ 1.5, 0.98572, 1.8333334, 1.0526782, 1.5, 0.98572, 1.8333334, 1.0526782 ] + }, + { "time": 2, "x": 1.0526782, "y": 1.0526782 } + ] + }, + "portal-streaks2": { + "rotate": [ + {}, + { "time": 3.166667, "value": 600 } + ], + "translate": [ + { "x": -2.111206 }, + { "time": 1, "x": -2.111206, "y": 6.630691 }, + { "time": 1.9333333, "x": -2.111206 } + ], + "scale": [ + { + "x": 1.0138458, + "y": 1.0138458, + "curve": [ 0.2286043, 0.908657, 0.5014533, 0.7550034, 0.2415624, 0.8915996, 0.5023928, 0.76759 ] + }, + { + "time": 0.8666667, + "x": 0.744747, + "y": 0.744747, + "curve": [ 1.2819105, 0.7330853, 2.020576, 0.6993992, 1.2702395, 0.7194394, 2.070725, 0.7086046 ] + }, + { + "time": 2.2, + "x": 0.699859, + "y": 0.7044076, + "curve": [ 2.315273, 0.7001541, 2.420857, 0.7939516, 2.310818, 0.70081, 2.484517, 0.7969156 ] + }, + { + "time": 2.5666666, + "x": 0.7939414, + "y": 0.7939414, + "curve": [ 2.734262, 0.7939298, 2.9900744, 0.3229577, 2.713767, 0.7886156, 3.019252, 0.3411524 ] + }, + { "time": 3.166667, "x": 0, "y": 0 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "time": 1.0666667, + "value": 108.71448, + "curve": [ 1.082331, 108.29144, 1.4370247, 50.72934 ] + }, + { + "time": 1.5666667, + "value": 24.8727, + "curve": [ 1.620189, 14.19789, 1.659529, -11.741982 ] + }, + { + "time": 1.7333333, + "value": -11.738415, + "curve": [ 1.9605454, -11.727437, 2.172043, 1.6552868 ] + }, + { + "time": 2.266667, + "value": 7.876571, + "curve": [ 2.33138, 12.131332, 2.438686, 18.653133 ] + }, + { + "time": 2.533333, + "value": 18.72252, + "curve": [ 2.78829, 18.90943, 3.14492, -0.29708695 ] + }, + { "time": 3.166667 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "time": 1.0666667, "value": 41.59875, "curve": "stepped" }, + { + "time": 1.2333333, + "value": 41.59875, + "curve": [ 1.2583333, 41.59875, 1.379043, 35.45793 ] + }, + { + "time": 1.4, + "value": 30.09105, + "curve": [ 1.4119207, 27.03835, 1.4333333, 10.648298 ] + }, + { "time": 1.4333333, "value": -0.28445435 }, + { "time": 1.6, "value": 2.438535 } + ], + "translate": [ + { "x": -899.4143, "y": 4.465324, "curve": "stepped" }, + { + "time": 1.0666667, + "x": -591.1311, + "y": 438.4623, + "curve": [ 1.0760857, -539.7665, 1.2062325, -268.1041, 1.1173495, 418.4433, 1.2102692, 333.1787 ] + }, + { + "time": 1.2333333, + "x": -225.28467, + "y": 304.5344, + "curve": [ 1.2650212, -175.21776, 1.3934208, -74.2127, 1.2961503, 226.51976, 1.4014887, 49.61011 ] + }, + { + "time": 1.4333333, + "x": -52.31879, + "y": 0.20110783, + "curve": [ 1.454237, -40.85228, 1.6164665, 40.87122, 1.4661087, 0.1682722, 1.6135045, 0.04275261 ] + }, + { "time": 1.6666666, "x": 45.86647, "y": 0.014911354 }, + { "time": 1.9333333, "x": 48.86993 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "time": 0.9, + "value": 39.23973, + "curve": [ 0.9684647, 39.93325, 1.2674664, 85.31066 ] + }, + { + "time": 1.4666667, + "value": 112.26816, + "curve": [ 1.555168, 124.2449, 1.5761636, 126.4438 ] + }, + { + "time": 1.6333333, + "value": 126.44372, + "curve": [ 1.7818086, 126.44356, 1.992362, 94.55132 ] + }, + { + "time": 2.1, + "value": 79.96207, + "curve": [ 2.2158396, 64.26122, 2.407094, 34.36 ] + }, + { + "time": 2.5666666, + "value": 33.38406, + "curve": [ 2.8148015, 31.86654, 3.099837, 39.19888 ] + }, + { "time": 3.166667, "value": 39.19888 } + ] + }, + "torso": { + "rotate": [ + { + "time": 1.0666667, + "value": 27.01542, + "curve": [ 1.1870607, 26.857056, 1.29125, 7.810417 ] + }, + { + "time": 1.3333334, + "value": -2.616394, + "curve": [ 1.4023846, -19.72492, 1.4290673, -48.64304 ] + }, + { + "time": 1.4666667, + "value": -56.31092, + "curve": [ 1.5086123, -64.86512, 1.6203593, -77.14185 ] + }, + { + "time": 1.7333333, + "value": -77.33606, + "curve": [ 1.8370242, -76.88617, 1.8949383, -71.32242 ] + }, + { + "time": 2, + "value": -57.51919, + "curve": [ 2.104223, -43.82614, 2.188923, -28.58867 ] + }, + { + "time": 2.3, + "value": -29.02788, + "curve": [ 2.413384, -29.47621, 2.513067, -36.78525 ] + }, + { + "time": 2.666667, + "value": -36.78525, + "curve": [ 2.814392, -36.94723, 2.9471095, -22.87543 ] + }, + { "time": 3.166667, "value": -22.87543 } + ] + }, + "torso2": { + "rotate": [ + { + "time": 1, + "curve": [ 1.117, 0, 1.25506, 24.936674 ] + }, + { + "time": 1.4, + "value": 24.936674, + "curve": [ 1.4766635, 24.936674, 1.5902743, -17.620535 ] + }, + { + "time": 1.6333333, + "value": -19.480213, + "curve": [ 1.7171756, -23.1013, 1.783559, -26.121367 ] + }, + { + "time": 1.9333333, + "value": -26.13695, + "curve": [ 2.067079, -26.150864, 2.157711, 4.304803 ] + }, + { + "time": 2.3, + "value": 4.219494, + "curve": [ 2.450183, 4.129454, 2.5790224, -1.7621814 ] + }, + { + "time": 2.733333, + "value": -1.800186, + "curve": [ 2.8159394, -1.820532, 2.857218, -2.935091 ] + }, + { + "time": 2.9333334, + "value": -2.99251, + "curve": [ 3.055751, -3.0848584, 3.0896554, 0 ] + }, + { "time": 3.166667 } + ] + }, + "torso3": { + "rotate": [ + { + "time": 1.3, + "curve": [ 1.35175, 0, 1.4081576, 6.465316 ] + }, + { + "time": 1.4666667, + "value": 6.43365, + "curve": [ 1.5501256, 6.389892, 1.7226946, -5.045167 ] + }, + { + "time": 1.7333333, + "value": -5.525421, + "curve": [ 1.7818483, -7.715482, 1.8426183, -16.94456 ] + }, + { + "time": 1.9666667, + "value": -16.86463, + "curve": [ 2.110735, -16.7757, 2.25872, -3.9745846 ] + }, + { + "time": 2.4, + "value": -2.426651, + "curve": [ 2.5251245, -1.1212268, 2.639004, -0.4973135 ] + }, + { + "time": 2.733333, + "value": -0.4892304, + "curve": [ 2.931302, -0.4722646, 2.998757, -2.148 ] + }, + { "time": 3.166667, "value": -2.148 } + ] + } + }, + "ik": { + "rear-leg-ik": [ + { "time": 3.166667, "softness": 10, "bendPositive": false } + ] + } + }, + "run": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" } + ] + } + }, + "bones": { + "aim-constraint-target": { + "rotate": [ + { "value": 30.570744 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "value": -147.0368, + "curve": [ 0.03288975, -113.40238, 0.16121684, 44.34079 ] + }, + { + "time": 0.23333333, + "value": 43.48135, + "curve": [ 0.23966667, 43.40587, 0.2819871, 35.7228 ] + }, + { + "time": 0.3, + "value": 0.2902248, + "curve": [ 0.3466916, 0.2766973, 0.3957438, 4.266659 ] + }, + { + "time": 0.4, + "curve": [ 0.4237695, -23.799583, 0.525, -181.3858 ] + }, + { + "time": 0.5666666, + "value": -181.3858, + "curve": [ 0.5916666, -181.3858, 0.6416666, -169.0875 ] + }, + { "time": 0.6666667, "value": -147.0368 } + ] + }, + "back-shoulder": { + "translate": [ + { + "curve": [ 0.08333333, 0, 0.25, 0, 0.08333333, 0, 0.25, 8.93015 ] + }, + { + "time": 0.3333333, + "y": 8.93015, + "curve": [ 0.4166667, 0, 0.5833333, 0, 0.4166667, 8.93015, 0.5833333, 0 ] + }, + { "time": 0.6666667 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 20.536366, + "curve": [ 0.05242157, 11.417128, 0.0888624, 0.1265936 ] + }, + { + "time": 0.13333334, + "value": 0.1466589, + "curve": [ 0.18554536, 0.1702223, 0.22147074, 26.29081 ] + }, + { + "time": 0.23333333, + "value": 32.369, + "curve": [ 0.24664006, 39.18712, 0.2860968, 61.44734 ] + }, + { + "time": 0.3333333, + "value": 61.58177, + "curve": [ 0.3705727, 61.68774, 0.4199115, 55.79158 ] + }, + { "time": 0.4666667, "value": 49.67855 }, + { "time": 0.6666667, "value": 20.536366 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16143, + "curve": [ 0.0142863, -38.79975, 0.03571006, -43.26606 ] + }, + { + "time": 0.06666667, + "value": -43.36955, + "curve": [ 0.10190062, -43.48734, 0.18198346, -28.460545 ] + }, + { + "time": 0.2, + "value": -23.04251, + "curve": [ 0.23049556, -13.871703, 0.2638955, 3.857522 ] + }, + { + "time": 0.3333333, + "value": 3.699075, + "curve": [ 0.3797016, 3.6420546, 0.535222, -16.222647 ] + }, + { "time": 0.5666666, "value": -21.28619 }, + { "time": 0.6666667, "value": -36.16143 } + ] + }, + "front-foot": { + "rotate": [ + { "value": 4.495182 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": -62.53822, + "curve": [ 0.01524261, -74.19112, 0.05595425, -103.19018 ] + }, + { + "time": 0.06666667, + "value": -111.07755, + "curve": [ 0.09160133, -129.4365, 0.18928672, -146.55014 ] + }, + { + "time": 0.23333333, + "value": -146.32286, + "curve": [ 0.2845242, -146.0587, 0.319893, -125.0951 ] + }, + { "time": 0.3333333, "value": -117.2421 }, + { + "time": 0.5, + "value": -35.07189, + "curve": [ 0.5216232, -28.64422, 0.545697, -24.83766 ] + }, + { + "time": 0.5666666, + "value": -24.90468, + "curve": [ 0.5953259, -24.996273, 0.6233758, -40.82229 ] + }, + { "time": 0.6666667, "value": -62.53822 } + ], + "translate": [ + { "x": 16.34054, "y": 0.18180084 }, + { + "time": 0.06666667, + "x": -101.43166, + "y": 8.04301, + "curve": [ 0.08527876, -131.34503, 0.12872964, -207.6919, 0.07963452, 14.90011, 0.12395438, 113.27577 ] + }, + { + "time": 0.16666667, + "x": -207.91826, + "y": 145.8111, + "curve": [ 0.1963201, -208.12917, 0.20963398, -202.915, 0.1856314, 160.2571, 0.206384, 163.47583 ] + }, + { + "time": 0.23333333, + "x": -189.94456, + "y": 163.85147, + "curve": [ 0.2698811, -169.9423, 0.3099357, -126.19253, 0.269217, 164.35164, 0.31597915, 85.96635 ] + }, + { + "time": 0.3333333, + "x": -90.56034, + "y": 78.57102, + "curve": [ 0.35471895, -57.99226, 0.3763082, -29.14028, 0.3497986, 71.55447, 0.3755576, 66.39534 ] + }, + { + "time": 0.4, + "x": 2.8686295, + "y": 66.38254, + "curve": [ 0.4121183, 19.24104, 0.46935335, 90.72872, 0.4288288, 66.36746, 0.46877515, 70.66057 ] + }, + { + "time": 0.5, + "x": 117.17877, + "y": 70.4559, + "curve": [ 0.5220905, 136.24426, 0.5417671, 151.32806, 0.5394703, 70.19718, 0.5545733, 38.2537 ] + }, + { + "time": 0.5666666, + "x": 151.4943, + "y": 25.28957, + "curve": [ 0.5782436, 146.75656, 0.5864146, 133.1328, 0.5718832, 19.69725, 0.582487, 12.229093 ] + }, + { "time": 0.6, "x": 115.01626, "y": 0.1018036 }, + { "time": 0.6666667, "x": 16.34054, "y": 0.18180084 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -0.2517306, + "curve": [ 0.008333334, -0.2517306, 0.05643159, 1.7333364 ] + }, + { + "time": 0.06666667, + "value": -7.676131, + "curve": [ 0.0754344, -43.12603, 0.14960335, -130.4444 ] + }, + { + "time": 0.2, + "value": -130.0761, + "curve": [ 0.23899044, -129.79117, 0.2717762, -126.80317 ] + }, + { + "time": 0.3, + "value": -116.2428, + "curve": [ 0.33295065, -103.91382, 0.3484584, -86.10217 ] + }, + { + "time": 0.3666667, + "value": -71.07932, + "curve": [ 0.3858575, -55.24571, 0.4147747, -32.43816 ] + }, + { + "time": 0.4333333, + "value": -21.634546, + "curve": [ 0.4704729, -0.014346838, 0.541709, 33.42213 ] + }, + { + "time": 0.5666666, + "value": 33.1958, + "curve": [ 0.6215921, 32.69772, 0.5690261, 0.6415044 ] + }, + { "time": 0.6666667, "value": -0.2517306 } + ] + }, + "front-leg-target": { + "translate": [ + { "x": -13.945175, "y": -30.34133 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": -0.7361145, + "y": 11.219177, + "curve": [ 0.06111111, -0.7361145, 0.14399, 1.168911, 0.06111111, 11.219177, 0.14298694, -17.925644 ] + }, + { + "time": 0.23333333, + "x": 1.187132, + "y": -17.8975, + "curve": [ 0.5402858, 1.2497454, 0.5583333, -0.7361145, 0.5447007, -17.800505, 0.5583333, 11.219177 ] + }, + { "time": 0.6666667, "x": -0.7361145, "y": 11.219177 } + ] + }, + "front-thigh": { + "translate": [ + { + "x": -5.136677, + "y": 11.130936, + "curve": [ 0.03324323, -7.770458, 0.11222646, -9.025787, 0.034, 11.130936, 0.1075726, 9.73772 ] + }, + { + "time": 0.16666667, + "x": -9.034784, + "y": 7.98743, + "curve": [ 0.2301002, -9.045264, 0.3136078, -1.3446236, 0.23623653, 5.926863, 0.2795449, 3.223648 ] + }, + { + "time": 0.3333333, + "x": 0.4135113, + "y": 3.19467, + "curve": [ 0.3521194, 2.087921, 0.448605, 11.15783, 0.3841316, 3.1587524, 0.4489366, 4.982999 ] + }, + { + "time": 0.5, + "x": 11.166422, + "y": 6.760218, + "curve": [ 0.5709641, 10.791886, 0.6208135, -1.8259034, 0.5415985, 8.20802, 0.625, 11.130936 ] + }, + { "time": 0.6666667, "x": -5.136677, "y": 11.130936 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -39.03467, + "curve": [ 0.05055879, -0.10101318, 0.14481726, 88.36118 ] + }, + { + "time": 0.23333333, + "value": 88.3612, + "curve": [ 0.2797953, 88.765, 0.3235971, 59.5175 ] + }, + { + "time": 0.3333333, + "value": 51.12628, + "curve": [ 0.3576108, 30.20255, 0.4447371, -74.91441 ] + }, + { + "time": 0.5666666, + "value": -75.8174, + "curve": [ 0.5989908, -76.05678, 0.6416666, -55.72052 ] + }, + { "time": 0.6666667, "value": -39.03467 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.364543, + "curve": [ 0.022356797, 16.282055, 0.08747823, 20.251215 ] + }, + { + "time": 0.13333334, + "value": 20.186804, + "curve": [ 0.168223, 20.32252, 0.25445935, -8.823136 ] + }, + { + "time": 0.2666667, + "value": -11.87723, + "curve": [ 0.2907614, -17.905375, 0.3436026, -24.105413 ] + }, + { + "time": 0.4, + "value": -23.880844, + "curve": [ 0.4478289, -23.690395, 0.5327503, -15.46561 ] + }, + { "time": 0.5666666, "value": -8.685678 }, + { "time": 0.6666667, "value": 12.364543 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -6.81118, + "curve": [ 0.0866619, -6.81118, 0.1434748, -5.746094 ] + }, + { + "time": 0.16666667, + "value": -4.295494, + "curve": [ 0.18288106, -3.281319, 0.2086277, 2.788338 ] + }, + { + "time": 0.23333333, + "value": 2.779537, + "curve": [ 0.2621102, 2.769287, 0.3045487, -6.631756 ] + }, + { + "time": 0.3333333, + "value": -6.643287, + "curve": [ 0.4193444, -6.67775, 0.4895841, -4.840439 ] + }, + { + "time": 0.5, + "value": -4.376785, + "curve": [ 0.518275, -3.5632935, 0.5736673, 2.3180084 ] + }, + { + "time": 0.6, + "value": 2.328674, + "curve": [ 0.6431814, 2.346161, 0.6333333, -6.81118 ] + }, + { "time": 0.6666667, "value": -6.81118 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -6.81118, + "curve": [ 0.013779226, -3.171306, 0.1089859, 43.93197 ] + }, + { + "time": 0.13333334, + "value": 43.94526, + "curve": [ 0.1770633, 43.96914, 0.1918259, -13.758546 ] + }, + { + "time": 0.2666667, + "value": -13.83195, + "curve": [ 0.3016804, -13.72252, 0.3221319, -8.864155 ] + }, + { + "time": 0.3333333, + "value": -6.598316, + "curve": [ 0.3486682, -3.496372, 0.4357065, 41.10004 ] + }, + { + "time": 0.4666667, + "value": 41.05412, + "curve": [ 0.5104914, 40.98914, 0.5491832, -14.055373 ] + }, + { + "time": 0.6, + "value": -14.181606, + "curve": [ 0.6304989, -14.257366, 0.6561362, -9.03967 ] + }, + { "time": 0.6666667, "value": -6.81118 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -6.81118, + "curve": [ 0.07915676, -6.834999, 0.108384, 0.2951547 ] + }, + { + "time": 0.13333334, + "value": 1.9601116, + "curve": [ 0.1772737, 4.892408, 0.20833735, 6.282898 ] + }, + { + "time": 0.23333333, + "value": 6.2904, + "curve": [ 0.3127078, 6.314222, 0.3833106, 3.487982 ] + }, + { + "time": 0.4, + "value": 2.580549, + "curve": [ 0.442394, 0.2754993, 0.5234759, -6.81118 ] + }, + { "time": 0.6, "value": -6.81118 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.81118, + "curve": [ 0.011210872, -4.062782, 0.10833333, 24.92299 ] + }, + { + "time": 0.13333334, + "value": 24.92299, + "curve": [ 0.15833333, 24.92299, 0.20833333, -10.621323 ] + }, + { + "time": 0.23333333, + "value": -10.621323, + "curve": [ 0.2541667, -10.621323, 0.31185055, -9.72602 ] + }, + { + "time": 0.3333333, + "value": -6.39663, + "curve": [ 0.3555912, -2.947105, 0.4375, 24.92807 ] + }, + { + "time": 0.4666667, + "value": 24.92807, + "curve": [ 0.4916667, 24.92807, 0.575, -9.775085 ] + }, + { + "time": 0.6, + "value": -9.775085, + "curve": [ 0.6166667, -9.775085, 0.654536, -8.62735 ] + }, + { "time": 0.6666667, "value": -6.81118 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.143766, + "curve": [ 0.02012745, 11.991796, 0.03863542, 8.93962 ] + }, + { + "time": 0.06666667, + "value": 8.926325, + "curve": [ 0.12159517, 8.900274, 0.23190995, 15.799082 ] + }, + { + "time": 0.2666667, + "value": 15.80678, + "curve": [ 0.3250607, 15.819712, 0.3570971, 8.947962 ] + }, + { + "time": 0.4, + "value": 8.927942, + "curve": [ 0.44371665, 8.90755, 0.5677775, 15.798948 ] + }, + { + "time": 0.6, + "value": 15.76724, + "curve": [ 0.6316618, 15.736086, 0.648973, 14.051775 ] + }, + { "time": 0.6666667, "value": 13.143766 } + ], + "scale": [ + { + "curve": [ 0.013515493, 0.9957332, 0.06835206, 0.9908737, 0.02733998, 1.005166, 0.08333333, 1.0123813 ] + }, + { + "time": 0.1, + "x": 0.990646, + "y": 1.0123813, + "curve": [ 0.12777777, 0.990646, 0.2054961, 1.0184776, 0.12777777, 1.0123813, 0.19723263, 0.9879228 ] + }, + { + "time": 0.23333333, + "x": 1.0184796, + "y": 0.9880367, + "curve": [ 0.2718352, 1.0184824, 0.3052763, 1.007659, 0.26181215, 0.9881266, 0.310745, 0.9947102 ] + }, + { + "time": 0.3333333, + "curve": [ 0.3506023, 0.995286, 0.4166667, 0.9871599, 0.358576, 1.0059115, 0.4166667, 1.012646 ] + }, + { + "time": 0.4333333, + "x": 0.9871599, + "y": 1.012646, + "curve": [ 0.4666667, 0.9871599, 0.5333333, 1.0197783, 0.4666667, 1.012646, 0.5333333, 0.988688 ] + }, + { + "time": 0.5666666, + "x": 1.0197783, + "y": 0.988688, + "curve": [ 0.5916666, 1.0197783, 0.6520706, 1.0043895, 0.5916666, 0.988688, 0.6436351, 0.9958277 ] + }, + { "time": 0.6666667 } + ] + }, + "head-control": { + "translate": [ + { + "y": -9.940754, + "curve": [ 0.05833333, 0, 0.175, -15.319916, 0.0436757, -4.192164, 0.175, 4.996334 ] + }, + { + "time": 0.23333333, + "x": -15.319916, + "y": 4.996334, + "curve": [ 0.3166667, -15.319916, 0.4287859, -9.741898, 0.3166667, 4.996334, 0.3821865, -31.713127 ] + }, + { + "time": 0.4666667, + "x": -7.808456, + "y": -31.59026, + "curve": [ 0.5068303, -5.758491, 0.6166667, 0, 0.548879, -31.47069, 0.6278209, -13.325505 ] + }, + { "time": 0.6666667, "y": -9.940754 } + ] + }, + "hip": { + "rotate": [ + { "value": -8.238106 } + ], + "translate": [ + { + "x": -3.595178, + "y": -34.10118, + "curve": [ 0.04166667, -3.836378, 0.1176159, 7.619495, 0.04166667, -33.74106, 0.11178646, 20.546356 ] + }, + { + "time": 0.16666667, + "x": 7.607398, + "y": 20.35568, + "curve": [ 0.1942442, 7.600595, 0.21030916, 5.061855, 0.20362726, 20.65172, 0.21742456, -8.689377 ] + }, + { + "time": 0.23333333, + "x": 1.6768702, + "y": -18.475845, + "curve": [ 0.27868885, -4.991243, 0.2966124, -5.63762, 0.2538157, -31.075775, 0.2916608, -34.54651 ] + }, + { + "time": 0.3333333, + "x": -5.755511, + "y": -35.00304, + "curve": [ 0.3786888, -5.901124, 0.4511913, 6.801747, 0.3841243, -35.55946, 0.4284051, 17.59712 ] + }, + { + "time": 0.5, + "x": 6.613358, + "y": 17.013046, + "curve": [ 0.5363964, 6.472878, 0.5448888, 3.56219, 0.5326953, 16.74632, 0.54835, -8.713715 ] + }, + { + "time": 0.5666666, + "x": 0.3517065, + "y": -18.81471, + "curve": [ 0.5966279, -4.065155, 0.6416666, -3.4504576, 0.5843817, -28.583954, 0.6416666, -34.31725 ] + }, + { "time": 0.6666667, "x": -3.595178, "y": -34.10118 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.884876, + "curve": [ 0.02355112, 11.402178, 0.075, 9.74365 ] + }, + { + "time": 0.1, + "value": 9.74365, + "curve": [ 0.125, 9.74365, 0.20833333, 13.35947 ] + }, + { + "time": 0.23333333, + "value": 13.35947, + "curve": [ 0.2583333, 13.35947, 0.3214549, 12.19964 ] + }, + { + "time": 0.3333333, + "value": 11.884876, + "curve": [ 0.3645646, 11.05729, 0.4083333, 9.719053 ] + }, + { + "time": 0.4333333, + "value": 9.719053, + "curve": [ 0.4583333, 9.719053, 0.5416667, 13.35947 ] + }, + { + "time": 0.5666666, + "value": 13.35947, + "curve": [ 0.5916666, 13.35947, 0.6356394, 12.479662 ] + }, + { "time": 0.6666667, "value": 11.884876 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": 28.284866 }, + { + "time": 0.23333333, + "value": -11.117936, + "curve": [ 0.2520901, -14.118498, 0.2973188, -19.369314 ] + }, + { + "time": 0.3333333, + "value": -19.37952, + "curve": [ 0.4346901, -19.408234, 0.5219483, 38.96215 ] + }, + { + "time": 0.5666666, + "value": 38.86711, + "curve": [ 0.6189629, 38.75598, 0.6442117, 32.01072 ] + }, + { "time": 0.6666667, "value": 28.284866 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": -6.497833 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": 18.55221 }, + { + "time": 0.23333333, + "value": 167.8415, + "curve": [ 0.24598274, 153.66016, 0.2561177, 129.7404 ] + }, + { + "time": 0.2666667, + "value": 124.3219, + "curve": [ 0.2955411, 124.428, 0.3131148, 129.925 ] + }, + { + "time": 0.3666667, + "value": 129.8712, + "curve": [ 0.4211775, 128.31995, 0.5194363, 0.9795736 ] + }, + { + "time": 0.5666666, + "curve": [ 0.5995562, 0.2691778, 0.6421174, 4.729006 ] + }, + { "time": 0.6666667, "value": 18.55221 } + ], + "translate": [ + { + "x": -176.39333, + "y": 134.11803, + "curve": [ 0.01817169, -142.2634, 0.05366483, -94.4109, 0.010235077, 120.9575, 0.04357376, 84.08058 ] + }, + { + "time": 0.06666667, + "x": -73.56457, + "y": 76.68465, + "curve": [ 0.08583902, -42.82485, 0.19448525, 101.19695, 0.09776284, 66.72555, 0.198365, 60.87754 ] + }, + { "time": 0.23333333, "x": 98.31728, "y": 32.16878 }, + { "time": 0.2666667, "x": 49.1316, "y": -0.6330318 }, + { + "time": 0.4, + "x": -147.8964, + "y": 0.3197541, + "curve": [ 0.4144494, -168.7802, 0.4780037, -284.7576, 0.4302233, 30.085405, 0.47836655, 129.1384 ] + }, + { + "time": 0.5, + "x": -283.3694, + "y": 167.1215, + "curve": [ 0.5261605, -285.6596, 0.5481881, -280.5382, 0.5157872, 194.8402, 0.5500097, 216.5319 ] + }, + { + "time": 0.5666666, + "x": -266.9802, + "y": 216.1206, + "curve": [ 0.5811586, -256.2662, 0.6427142, -206.5363, 0.6103095, 214.8186, 0.6499278, 145.32756 ] + }, + { "time": 0.6666667, "x": -176.39333, "y": 134.11803 } + ] + }, + "rear-leg-target": { + "translate": [ + { "x": 85.00298, "y": -33.59399 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -16.41337, + "y": 1.553418, + "curve": [ 0.01329846, -15.666842, 0.18333334, -8.545134, 0.02999618, 2.3940766, 0.18333334, 6.169795 ] + }, + { + "time": 0.23333333, + "x": -8.545134, + "y": 6.169795, + "curve": [ 0.3083333, -8.545134, 0.4916667, -19.75406, 0.3083333, 6.169795, 0.4916667, 0.6147775 ] + }, + { + "time": 0.5666666, + "x": -19.75406, + "y": 0.6147775, + "curve": [ 0.5916666, -19.75406, 0.6411845, -18.06293, 0.5916666, 0.6147775, 0.6317572, 0.7811694 ] + }, + { "time": 0.6666667, "x": -16.41337, "y": 1.553418 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.50333, + "curve": [ 0.028292393, 23.741745, 0.1277068, -79.86003 ] + }, + { + "time": 0.23333333, + "value": -79.86928, + "curve": [ 0.380056, -79.88212, 0.4030929, 63.25032 ] + }, + { + "time": 0.5666666, + "value": 64.13361, + "curve": [ 0.6073362, 64.35324, 0.6441763, 53.09538 ] + }, + { "time": 0.6666667, "value": 40.50333 } + ], + "translate": [ + { + "x": -3.786807, + "y": -0.7673931, + "curve": [ 0.04393777, -4.57923, 0.16938667, -5.475494, 0.04393777, 0.9303658, 0.16938667, 2.850609 ] + }, + { + "time": 0.23333333, + "x": -5.475494, + "y": 2.850609, + "curve": [ 0.34626475, -5.475494, 0.4753447, -2.684357, 0.34626475, 2.850609, 0.4753447, -3.129387 ] + }, + { + "time": 0.5666666, + "x": -2.684357, + "y": -3.129387, + "curve": [ 0.6106853, -2.684357, 0.6416666, -3.3359296, 0.6106853, -3.129387, 0.6416666, -1.7333956 ] + }, + { "time": 0.6666667, "x": -3.786807, "y": -0.7673931 } + ] + }, + "torso": { + "rotate": [ + { + "value": -37.65892, + "curve": [ 0.03438962, -37.13966, 0.10666874, -36.20868 ] + }, + { + "time": 0.13333334, + "value": -36.21151, + "curve": [ 0.15832105, -36.21416, 0.20853826, -38.80227 ] + }, + { + "time": 0.23333333, + "value": -38.79141, + "curve": [ 0.2591656, -38.78009, 0.3134857, -38.02602 ] + }, + { + "time": 0.3333333, + "value": -37.65892, + "curve": [ 0.3574979, -37.21197, 0.4000104, -36.21151 ] + }, + { + "time": 0.4333333, + "value": -36.21151, + "curve": [ 0.4583333, -36.21151, 0.5391698, -38.80016 ] + }, + { + "time": 0.5666666, + "value": -38.80016, + "curve": [ 0.5916668, -38.80015, 0.644527, -37.99963 ] + }, + { "time": 0.6666667, "value": -37.65892 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 3.4965944, + "curve": [ 0.06971177, 3.506942, 0.075, 8.690938 ] + }, + { + "time": 0.1, + "value": 8.69094, + "curve": [ 0.13874887, 8.69094, 0.21436596, 6.899573 ] + }, + { + "time": 0.23333333, + "value": 6.329458, + "curve": [ 0.2661681, 5.34252, 0.28525335, 3.4847515 ] + }, + { + "time": 0.3333333, + "value": 3.483698, + "curve": [ 0.3976253, 3.482288, 0.4083333, 8.68357 ] + }, + { + "time": 0.4333333, + "value": 8.68357, + "curve": [ 0.4583333, 8.68357, 0.5514198, 6.795305 ] + }, + { + "time": 0.5666666, + "value": 6.259716, + "curve": [ 0.597618, 5.172464, 0.6416666, 3.4928834 ] + }, + { "time": 0.6666667, "value": 3.4965944 } + ] + }, + "torso3": { + "rotate": [ + { + "value": 4.52226, + "curve": [ 0.06670141, 4.538608, 0.075, -7.267916 ] + }, + { + "time": 0.1, + "value": -7.267916, + "curve": [ 0.125, -7.267916, 0.2265727, 0.8404685 ] + }, + { + "time": 0.23333333, + "value": 1.2426214, + "curve": [ 0.2544456, 2.498479, 0.300799, 4.508696 ] + }, + { + "time": 0.3333333, + "value": 4.52226, + "curve": [ 0.3859158, 4.544183, 0.4083333, -7.354608 ] + }, + { + "time": 0.4333333, + "value": -7.354608, + "curve": [ 0.4583333, -7.354608, 0.5494212, -0.13630033 ] + }, + { + "time": 0.5666666, + "value": 0.9513377, + "curve": [ 0.5862055, 2.183612, 0.6318744, 4.538621 ] + }, + { "time": 0.6666667, "value": 4.52226 } + ] + } + }, + "ik": { + "front-leg-ik": [ + { "softness": 10, "bendPositive": false }, + { "time": 0.5666666, "softness": 14.8, "bendPositive": false }, + { "time": 0.6, "softness": 48.2, "bendPositive": false }, + { "time": 0.6666667, "softness": 10, "bendPositive": false } + ], + "rear-leg-ik": [ + { "bendPositive": false }, + { "time": 0.16666667, "softness": 22.5, "bendPositive": false }, + { "time": 0.3, "softness": 61.4, "bendPositive": false }, + { "time": 0.6666667, "bendPositive": false } + ] + }, + "events": [ + { "time": 0.23333333, "name": "footstep" }, + { "time": 0.5666666, "name": "footstep" } + ] + }, + "run-to-idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-bracer": { + "rotate": [ + { + "value": 8.79112, + "curve": [ 0.04088889, 8.79112, 0.11455758, 6.297712 ] + }, + { + "time": 0.16666667, + "value": 6.40873, + "curve": [ 0.2011747, 6.48225, 0.2408889, 42.46212 ] + }, + { "time": 0.2666667, "value": 42.46212 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": 38.2605, + "curve": [ 0.04088889, 38.2605, 0.1269512, -2.193311 ] + }, + { + "time": 0.16666667, + "value": -2.996897, + "curve": [ 0.208581, -3.8449726, 0.2408889, 0 ] + }, + { "time": 0.2666667 } + ], + "scale": [ + { + "x": 0.8437909, + "curve": [ 0.06666667, 0.8437909, 0.2, 1, 0.06666667, 1, 0.2, 1 ] + }, + { "time": 0.2666667 } + ] + }, + "front-foot-target": { + "translate": [ + { + "x": -16.498466, + "y": 3.40506, + "curve": [ 0.03333333, -16.498466, 0.1, -69.06195, 0.03333333, 3.40506, 0.1, 0 ] + }, + { "time": 0.13333334, "x": -69.06195 } + ] + }, + "front-shoulder": { + "translate": [ + { "x": 4.907959, "y": 11.54062 }, + { "time": 0.2666667 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -80.6061, + "curve": [ 0.06666667, -80.6061, 0.2, -60.86928 ] + }, + { "time": 0.2666667, "value": -60.86928 } + ] + }, + "gun": { + "rotate": [ + { + "value": 2.276992, + "curve": [ 0.04088889, 2.276992, 0.10457134, 15.343413 ] + }, + { + "time": 0.16666667, + "value": 15.31988, + "curve": [ 0.20540346, 15.305198, 0.2408889, 0 ] + }, + { "time": 0.2666667 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.03333333, 0, 0.1, 10.762588 ] + }, + { + "time": 0.13333334, + "value": 10.762588, + "curve": [ 0.16666667, 10.762588, 0.23333333, 0 ] + }, + { "time": 0.2666667 } + ] + }, + "hair2": { + "rotate": [ + { + "curve": [ 0.013892582, -2.278984, 0.04199818, -7.836777 ] + }, + { + "time": 0.06666667, + "value": -7.818661, + "curve": [ 0.10774196, -7.788499, 0.16569327, 6.57153 ] + }, + { + "time": 0.2, + "value": 6.667625, + "curve": [ 0.2215867, 6.728088, 0.2552269, 1.977066 ] + }, + { "time": 0.2666667 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.03333333, 0, 0.1, 0.8756008 ] + }, + { + "time": 0.13333334, + "value": 0.8756008, + "curve": [ 0.16666667, 0.8756008, 0.23333333, 0 ] + }, + { "time": 0.2666667 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.03333333, 0, 0.1, 15.97303 ] + }, + { + "time": 0.13333334, + "value": 15.97303, + "curve": [ 0.16666667, 15.97303, 0.23333333, 0 ] + }, + { "time": 0.2666667 } + ] + }, + "head": { + "rotate": [ + { + "curve": [ 0.05, 0, 0.08333333, 2.670654 ] + }, + { + "time": 0.13333334, + "value": 2.670654, + "curve": [ 0.15, 2.670654, 0.25, -6.74768 ] + }, + { "time": 0.2666667, "value": -6.74768 } + ] + }, + "head-control": { + "translate": [ + { "x": -10.115814, "y": 8.708984 }, + { "time": 0.2666667 } + ] + }, + "hip": { + "translate": [ + { + "x": -28.77872, + "y": -72.95576, + "curve": [ 0.0362704, -28.63402, 0.2, -10.84824, 0.13512376, -62.34809, 0.2, -23.15497 ] + }, + { "time": 0.2666667, "x": -11.972925, "y": -23.15497 } + ] + }, + "neck": { + "rotate": [ + {}, + { "time": 0.2666667, "value": 3.7834435 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 57.24359, + "curve": [ 0.06666667, 57.24359, 0.2, 0 ] + }, + { "time": 0.2666667 } + ] + }, + "rear-foot-target": { + "translate": [ + { + "x": 33.15137, + "y": 31.6077, + "curve": [ 0.01666667, 33.15137, 0.05, 24.412033, 0.01666667, 31.6077, 0.04116466, 20.72947 ] + }, + { + "time": 0.06666667, + "x": 24.412033, + "y": 0.1898204, + "curve": [ 0.11666667, 24.412033, 0.21666667, 48.86993, 0.11666667, 0.1898204, 0.21666667, 0 ] + }, + { "time": 0.2666667, "x": 48.86993 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 55.30082, + "curve": [ 0.06666667, 55.30082, 0.2, 39.19888 ] + }, + { "time": 0.2666667, "value": 39.19888 } + ] + }, + "torso": { + "rotate": [ + { + "value": -12.97502, + "curve": [ 0.03333333, -12.97502, 0.10291763, -14.80918 ] + }, + { + "time": 0.13333334, + "value": -16.633377, + "curve": [ 0.16759777, -18.688416, 0.23333333, -22.87543 ] + }, + { "time": 0.2666667, "value": -22.87543 } + ], + "scale": [ + { + "x": 0.9634942, + "y": 1.074131, + "curve": [ 0.06666667, 0.9634942, 0.13178295, 1, 0.06666667, 1.074131, 0.13178295, 1 ] + }, + { "time": 0.2666667 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.04088889, 0, 0.1068563, 3.03463 ] + }, + { + "time": 0.16666667, + "value": 3.03463, + "curve": [ 0.2051437, 3.03463, 0.2408889, 0 ] + }, + { "time": 0.2666667 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.04866667, 0, 0.16607822, 0.6565394 ] + }, + { + "time": 0.2, + "value": 0.6551018, + "curve": [ 0.23155688, 0.6537645, 0.24866667, -2.148 ] + }, + { "time": 0.2666667, "value": -2.148 } + ] + } + } + }, + "shoot": { + "slots": { + "muzzle": { + "rgba": [ + { "time": 0.13333334, "color": "ffffffff" }, + { "time": 0.2, "color": "ffffff62" } + ], + "attachment": [ + { "time": 0.03333333, "name": "muzzle01" }, + { "time": 0.06666667, "name": "muzzle02" }, + { "time": 0.1, "name": "muzzle03" }, + { "time": 0.13333334, "name": "muzzle04" }, + { "time": 0.16666667, "name": "muzzle05" }, + { "time": 0.2 } + ] + }, + "muzzle-glow": { + "rgba": [ + { "color": "ff0c0c00" }, + { + "time": 0.03333333, + "color": "ffc9adff", + "curve": [ 0.2548387, 1, 0.2731183, 1, 0.2548387, 0.764635, 0.2731183, 0.3981355, 0.2548387, 0.6506967, 0.2731183, 0.2199929, 0.2548387, 1, 0.2731183, 1 ] + }, + { "time": 0.3, "color": "ff400cff" }, + { "time": 0.6333333, "color": "ff0c0c00" } + ], + "attachment": [ + { "name": "muzzle-glow" } + ] + }, + "muzzle-ring": { + "rgba": [ + { + "time": 0.03333333, + "color": "d8baffff", + "curve": [ 0.20246167, 0.847044, 0.2138418, 0.843966, 0.20246167, 0.7294118, 0.2138418, 0.7294118, 0.20246167, 1, 0.2138418, 1, 0.20246167, 0.9962264, 0.2138418, 0.21132076 ] + }, + { "time": 0.23333333, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.03333333, "name": "muzzle-ring" }, + { "time": 0.23333333 } + ] + }, + "muzzle-ring2": { + "rgba": [ + { + "time": 0.03333333, + "color": "d8baffff", + "curve": [ 0.17427363, 0.847044, 0.18375705, 0.843966, 0.17427363, 0.7294118, 0.18375705, 0.7294118, 0.17427363, 1, 0.18375705, 1, 0.17427363, 0.9962264, 0.18375705, 0.21132076 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.03333333, "name": "muzzle-ring" }, + { "time": 0.2 } + ] + }, + "muzzle-ring3": { + "rgba": [ + { + "time": 0.03333333, + "color": "d8baffff", + "curve": [ 0.17427363, 0.847044, 0.18375705, 0.843966, 0.17427363, 0.7294118, 0.18375705, 0.7294118, 0.17427363, 1, 0.18375705, 1, 0.17427363, 0.9962264, 0.18375705, 0.21132076 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.03333333, "name": "muzzle-ring" }, + { "time": 0.2 } + ] + }, + "muzzle-ring4": { + "rgba": [ + { + "time": 0.03333333, + "color": "d8baffff", + "curve": [ 0.17427363, 0.847044, 0.18375705, 0.843966, 0.17427363, 0.7294118, 0.18375705, 0.7294118, 0.17427363, 1, 0.18375705, 1, 0.17427363, 0.9962264, 0.18375705, 0.21132076 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.03333333, "name": "muzzle-ring" }, + { "time": 0.2 } + ] + } + }, + "bones": { + "gun": { + "rotate": [ + { + "time": 0.06666667, + "curve": [ 0.09373267, 25.889433, 0.1123115, 45.26556 ] + }, + { + "time": 0.13333334, + "value": 45.34824, + "curve": [ 0.1922297, 45.27915, 0.17955977, -0.09420347 ] + }, + { "time": 0.6333333 } + ] + }, + "gun-tip": { + "translate": [ + {}, + { "time": 0.3, "x": 3.151428, "y": 0.3925476 } + ], + "scale": [ + { "x": 0.3660886, "y": 0.3660886 }, + { "time": 0.03333333, "x": 1.4526132, "y": 1.4526132 }, + { "time": 0.3, "x": 0.3660886, "y": 0.3660886 } + ] + }, + "muzzle": { + "translate": [ + { "x": -11.021545, "y": 25.164276 } + ] + }, + "muzzle-ring": { + "translate": [ + { "time": 0.03333333 }, + { "time": 0.23333333, "x": 64.47002 } + ], + "scale": [ + { "time": 0.03333333 }, + { "time": 0.23333333, "x": 5.950701, "y": 5.950701 } + ] + }, + "muzzle-ring2": { + "translate": [ + { "time": 0.03333333 }, + { "time": 0.2, "x": 172.5692 } + ], + "scale": [ + { "time": 0.03333333 }, + { "time": 0.2, "x": 4, "y": 4 } + ] + }, + "muzzle-ring3": { + "translate": [ + { "time": 0.03333333 }, + { "time": 0.2, "x": 277.1667 } + ], + "scale": [ + { "time": 0.03333333 }, + { "time": 0.2, "x": 2, "y": 2 } + ] + }, + "muzzle-ring4": { + "translate": [ + { "time": 0.03333333 }, + { "time": 0.2, "x": 392.0556 } + ] + }, + "rear-bracer": { + "translate": [ + { + "time": 0.03333333, + "curve": [ 0.07454277, -3.783108, 0.08333333, -4.361145, 0.08020648, -2.70222, 0.08333333, -2.880127 ] + }, + { + "time": 0.1, + "x": -4.361145, + "y": -2.880127, + "curve": [ 0.13333334, -4.361145, 0.16790563, 0.1801529, 0.13333334, -2.880127, 0.1672763, 0 ] + }, + { "time": 0.23333333 } + ] + }, + "rear-upper-arm": { + "translate": [ + { + "time": 0.03333333, + "curve": [ 0.04513854, 0.908549, 0.08333333, 3.456565, 0.04365119, 0.8643327, 0.08333333, 3.319756 ] + }, + { + "time": 0.1, + "x": 3.456565, + "y": 3.319756, + "curve": [ 0.13333334, 3.456565, 0.1757862, -0.09847545, 0.13333334, 3.319756, 0.16949686, 0 ] + }, + { "time": 0.23333333 } + ] + } + } + }, + "walk": { + "bones": { + "back-foot-tip": { + "rotate": [ + { "value": 4.087345 }, + { "time": 0.03333333, "value": 3.052846 }, + { + "time": 0.1, + "value": -59.00914, + "curve": [ 0.1236928, -72.96686, 0.1688272, -100.0528 ] + }, + { + "time": 0.23333333, + "value": -99.7063, + "curve": [ 0.3260634, -99.20817, 0.34862125, -37.39541 ] + }, + { + "time": 0.3666667, + "value": -17.84707, + "curve": [ 0.387521, 4.744033, 0.4514076, 32.35068 ] + }, + { + "time": 0.5, + "value": 32.39831, + "curve": [ 0.5374549, 32.43502, 0.5656413, 6.425618 ] + }, + { "time": 0.5666666, "value": 1.9995908 }, + { "time": 1, "value": 4.087345 } + ] + }, + "back-shoulder": { + "translate": [ + { + "x": -0.18066406, + "y": -4.490013, + "curve": [ 0.13333334, -0.18066406, 0.3333333, 7.685893, 0.13333334, -4.490013, 0.3333333, 2.77058 ] + }, + { + "time": 0.4666667, + "x": 7.685893, + "y": 2.77058, + "curve": [ 0.6, 7.685893, 0.8583333, -0.18066406, 0.6, 2.77058, 0.8583333, -4.490013 ] + }, + { "time": 1, "x": -0.18066406, "y": -4.490013 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 13.566517, + "curve": [ 0.021665983, 9.70724, 0.1470159, -3.779979 ] + }, + { + "time": 0.3666667, + "value": -3.6853304, + "curve": [ 0.4572524, -3.659578, 0.4793066, 0.8338775 ] + }, + { + "time": 0.5, + "value": 4.053596, + "curve": [ 0.5130476, 6.083689, 0.6349344, 30.8047 ] + }, + { + "time": 0.8, + "value": 30.91521, + "curve": [ 0.9739746, 31.002415, 0.9800564, 18.353865 ] + }, + { "time": 1, "value": 13.566517 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -28.72383, + "curve": [ 0.02368659, -31.7421, 0.1760204, -43.39537 ] + }, + { + "time": 0.3666667, + "value": -43.59644, + "curve": [ 0.4030356, -43.64886, 0.4704281, -40.14865 ] + }, + { + "time": 0.5, + "value": -35.63085, + "curve": [ 0.5466347, -28.591816, 0.624065, -4.573129 ] + }, + { + "time": 0.7333333, + "value": -4.592627, + "curve": [ 0.8906477, -4.620701, 0.9538756, -24.27828 ] + }, + { "time": 1, "value": -28.48091 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": 18.190496, + "curve": [ 0.010253842, 11.169012, 0.04303193, 1.3740194 ] + }, + { "time": 0.1, "value": 0.4737756 }, + { + "time": 0.23333333, + "value": 0.549647, + "curve": [ 0.3635588, 0.3049073, 0.5154175, -80.48494 ] + }, + { + "time": 0.7333333, + "value": -80.78354, + "curve": [ 0.788268, -80.38087, 0.9209627, 17.41829 ] + }, + { "time": 1, "value": 18.190496 } + ], + "translate": [ + { + "x": 139.2134, + "y": 22.940594, + "curve": [ 0.025, 139.2134, 0.06885808, 111.46258, 0.031141926, 3.245279, 0.075, 0.06223501 ] + }, + { "time": 0.1, "x": 96.6911, "y": 0.06223501 }, + { + "time": 0.5, + "x": -94.8686, + "y": -0.02649164, + "curve": [ 0.5182838, -106.82498, 0.575, -152.5596, 0.5337463, 5.423584, 0.5570473, 38.45566 ] + }, + { + "time": 0.6, + "x": -152.5596, + "y": 57.05291, + "curve": [ 0.6333333, -152.5596, 0.6880029, -128.047, 0.6428554, 75.60812, 0.7, 84.14295 ] + }, + { + "time": 0.7333333, + "x": -109.42177, + "y": 84.14297, + "curve": [ 0.7710902, -93.90832, 0.8318373, -30.64482, 0.7872631, 84.14297, 0.7985512, 89.6509 ] + }, + { + "time": 0.8666667, + "x": 16.99742, + "y": 75.25434, + "curve": [ 0.9026193, 66.17633, 0.9666666, 139.2134, 0.9315786, 61.53487, 0.9666666, 44.02184 ] + }, + { "time": 1, "x": 139.2134, "y": 22.940594 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": 28.964193, + "curve": [ 0.05626451, 28.744823, 0.04890398, 19.603014 ] + }, + { "time": 0.06666667, "value": 1.675728 }, + { + "time": 0.5, + "value": -10.004452, + "curve": [ 0.525, -10.004452, 0.5923562, -54.69306 ] + }, + { + "time": 0.6, + "value": -59.66399, + "curve": [ 0.6228758, -74.54068, 0.674358, -101.77973 ] + }, + { + "time": 0.7333333, + "value": -101.77972, + "curve": [ 0.8121933, -101.7797, 0.8554094, -84.66802 ] + }, + { + "time": 0.8666667, + "value": -63.52591, + "curve": [ 0.8694085, -58.3765, 0.975, 28.964195 ] + }, + { "time": 1, "value": 28.964195 } + ] + }, + "front-leg-target": { + "translate": [ + { + "x": -2.83342, + "y": -8.48053, + "curve": [ 0.008333334, -2.83342, 0.05833333, 0.09416199, 0.0010207203, 4.973398, 0.05833333, 6.677925 ] + }, + { + "time": 0.06666667, + "x": 0.09416199, + "y": 6.677925, + "curve": [ 0.3, 0.09416199, 0.7666666, -2.83342, 0.3, 6.677925, 0.7666666, -8.48053 ] + }, + { "time": 1, "x": -2.83342, "y": -8.48053 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.460663, + "y": 9.368988, + "curve": [ 0.1624987, 1.4141464, 0.3326475, -1.6649847, 0.1624987, 9.368988, 0.3011157, -7.232888 ] + }, + { + "time": 0.5, + "x": -1.5982952, + "y": -7.269668, + "curve": [ 0.7353738, -1.5045013, 0.847223, 1.460663, 0.7233681, -7.310975, 0.8375013, 9.32247 ] + }, + { "time": 1, "x": 1.460663, "y": 9.368988 } + ] + }, + "front-thigh": { + "translate": [ + { + "x": 17.154694, + "y": -0.0851593, + "curve": [ 0.17816044, 17.1408, 0.2949699, -4.258095, 0.008833333, -0.0851593, 0.475, 0.021209717 ] + }, + { + "time": 0.5, + "x": -4.263954, + "y": 0.021209717, + "curve": [ 0.7050302, -4.26981, 0.8475542, 17.14552, 0.525, 0.021209717, 0.975, -0.0851593 ] + }, + { "time": 1, "x": 17.154694, "y": -0.0851593 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -9.513367, + "curve": [ 0.0214478, -13.319992, 0.05789917, -19.404175 ] + }, + { + "time": 0.1, + "value": -19.404175, + "curve": [ 0.2377866, -19.68686, 0.33747205, 7.779631 ] + }, + { + "time": 0.3666667, + "value": 16.196716, + "curve": [ 0.39864385, 25.41603, 0.4965658, 60.19389 ] + }, + { + "time": 0.6, + "value": 60.26086, + "curve": [ 0.7185024, 60.12991, 0.8452276, 27.61441 ] + }, + { + "time": 0.8666667, + "value": 22.449387, + "curve": [ 0.8918752, 16.37623, 0.9789886, -3.2677646 ] + }, + { "time": 1, "value": -9.513367 } + ] + }, + "gun": { + "rotate": [ + { + "value": -14.673275, + "curve": [ 0.08551843, -14.673275, 0.20198414, 8.30991 ] + }, + { + "time": 0.23333333, + "value": 12.136024, + "curve": [ 0.2789693, 17.70582, 0.3914901, 25.794325 ] + }, + { + "time": 0.5, + "value": 25.77012, + "curve": [ 0.6313128, 25.740833, 0.6943456, 4.530927 ] + }, + { + "time": 0.7333333, + "value": -0.6513629, + "curve": [ 0.7676219, -5.209029, 0.9023453, -14.40159 ] + }, + { "time": 1, "value": -14.673275 } + ] + }, + "gun-tip": { + "rotate": [ + { "time": 0.23333333, "value": 0.1086235 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.027893247, 1.242131, 0.01634026, 3.4572334 ] + }, + { + "time": 0.1, + "value": 3.452011, + "curve": [ 0.15888935, 3.448334, 0.1887935, 0.2309022 ] + }, + { + "time": 0.23333333, + "value": -2.2886696, + "curve": [ 0.265451, -4.316047, 0.3046157, -5.922498 ] + }, + { + "time": 0.3666667, + "value": -5.93975, + "curve": [ 0.4464736, -5.961938, 0.5196544, 3.4063644 ] + }, + { + "time": 0.6, + "value": 3.423363, + "curve": [ 0.7168543, 3.417797, 0.7715329, -5.931904 ] + }, + { + "time": 0.8666667, + "value": -5.965309, + "curve": [ 0.9329224, -5.988567, 0.9819044, -0.9372777 ] + }, + { "time": 1 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -2.790066, + "curve": [ 0.07374832, -2.8390694, 0.12107787, 25.0846 ] + }, + { + "time": 0.23333333, + "value": 24.98932, + "curve": [ 0.3498563, 24.89042, 0.427126, -2.862324 ] + }, + { + "time": 0.5, + "value": -2.799221, + "curve": [ 0.5753732, -2.733959, 0.6522827, 24.50276 ] + }, + { + "time": 0.7333333, + "value": 24.54565, + "curve": [ 0.8276176, 24.59554, 0.9316076, -2.692043 ] + }, + { "time": 1, "value": -2.790066 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.06667267, 0, 0.1593553, -10.48392 ] + }, + { + "time": 0.23333333, + "value": -10.492886, + "curve": [ 0.3338235, -10.49989, 0.4386607, -0.08680725 ] + }, + { + "time": 0.5, + "value": -0.08680725, + "curve": [ 0.5688103, -0.08680725, 0.658053, -10.74765 ] + }, + { + "time": 0.7333333, + "value": -10.697582, + "curve": [ 0.8333084, -10.631088, 0.9472112, 0 ] + }, + { "time": 1 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.013939, + "curve": [ 0.10559352, -5.969406, 0.1507493, 18.62226 ] + }, + { + "time": 0.23333333, + "value": 18.723427, + "curve": [ 0.3355302, 18.69581, 0.40528485, -11.373627 ] + }, + { + "time": 0.5, + "value": -11.454224, + "curve": [ 0.626311, -11.45571, 0.6293055, 18.93505 ] + }, + { + "time": 0.7333333, + "value": 18.919914, + "curve": [ 0.8333666, 18.919914, 0.9129916, -6.060696 ] + }, + { "time": 1, "value": -6.013939 } + ], + "translate": [ + { "x": 0.03475952, "y": 1.3458252 } + ] + }, + "head": { + "rotate": [ + { + "value": -12.234505, + "curve": [ 0.06143671, -12.234504, 0.19128084, -7.449013 ] + }, + { + "time": 0.2666667, + "value": -7.434601, + "curve": [ 0.3406891, -7.42045, 0.4206042, -12.234505 ] + }, + { + "time": 0.5, + "value": -12.234505, + "curve": [ 0.5671493, -12.26333, 0.6940113, -7.456505 ] + }, + { + "time": 0.7666666, + "value": -7.472237, + "curve": [ 0.8529694, -7.490928, 0.942855, -12.234505 ] + }, + { "time": 1, "value": -12.234505 } + ], + "scale": [ + { + "curve": [ 0.03916667, 1, 0.08446944, 0.9912923, 0.03916667, 1, 0.08446944, 1.0190994 ] + }, + { + "time": 0.13333334, + "x": 0.9912923, + "y": 1.0190994, + "curve": [ 0.20465556, 0.9912923, 0.3176702, 1.0191765, 0.20465556, 1.0190994, 0.3367928, 0.9916709 ] + }, + { + "time": 0.4, + "x": 1.0190022, + "y": 0.9915339, + "curve": [ 0.4560374, 1.018884, 0.4936612, 1.001296, 0.483147, 0.9913536, 0.49272755, 0.9987176 ] + }, + { + "time": 0.5, + "curve": [ 0.5076706, 0.9984317, 0.5844694, 0.9912923, 0.5099203, 1.001749, 0.5844694, 1.0190994 ] + }, + { + "time": 0.6333333, + "x": 0.9912923, + "y": 1.0190994, + "curve": [ 0.7046556, 0.9912923, 0.8176701, 1.0191765, 0.7046556, 1.0190994, 0.8367927, 0.9916709 ] + }, + { + "time": 0.9, + "x": 1.0190022, + "y": 0.9915339, + "curve": [ 0.9560374, 1.018884, 0.9553667, 1, 0.9831469, 0.9913536, 0.9553667, 1 ] + }, + { "time": 1 } + ] + }, + "head-control": { + "translate": [ + { + "x": -6.45993, + "y": -8.401773, + "curve": [ 0.05273332, -5.314346, 0.1667785, -3.638252, 0.0930327, -8.401774, 0.1959178, -3.8102424 ] + }, + { + "time": 0.23333333, + "x": -3.638252, + "y": -1.3223945, + "curve": [ 0.3092998, -3.638252, 0.4364251, -5.842407, 0.2746537, 1.4250946, 0.3798138, 10.303744 ] + }, + { + "time": 0.5, + "x": -7.034508, + "y": 10.285416, + "curve": [ 0.53829, -7.752487, 0.6595171, -10.53656, 0.5982466, 10.27043, 0.6943732, 1.5578316 ] + }, + { + "time": 0.7333333, + "x": -10.53656, + "y": -1.2572263, + "curve": [ 0.7973798, -10.53656, 0.9333333, -7.908203, 0.7684355, -3.793518, 0.8749288, -8.401772 ] + }, + { "time": 1, "x": -6.45993, "y": -8.401773 } + ] + }, + "hip": { + "rotate": [ + { "value": -4.354578 } + ], + "translate": [ + { + "x": -2.8556595, + "y": -13.858932, + "curve": [ 0.025, -2.84362, 0.0672245, -2.815521, 0.02826383, -19.13565, 0.05413223, -24.01763 ] + }, + { + "time": 0.1, + "x": -2.609104, + "y": -24.187546, + "curve": [ 0.14349824, -2.335156, 0.20189807, -1.788381, 0.1520444, -23.984085, 0.21322107, -14.811488 ] + }, + { + "time": 0.2666667, + "x": -1.2142082, + "y": -7.122375, + "curve": [ 0.3076929, -0.8572894, 0.3451087, -0.5055015, 0.3060169, -1.6301517, 0.3410871, 3.152566 ] + }, + { + "time": 0.3666667, + "x": -0.3309364, + "y": 3.1525726, + "curve": [ 0.4099607, 0.01963806, 0.458473, 0.25751495, 0.4266791, 3.304947, 0.48069695, -6.751709 ] + }, + { + "time": 0.5, + "x": 0.2593346, + "y": -10.585007, + "curve": [ 0.553076, 0.2616577, 0.5589796, 0.1951599, 0.5192444, -14.406647, 0.5481416, -23.88285 ] + }, + { + "time": 0.6, + "x": -0.16674805, + "y": -23.7083, + "curve": [ 0.6630032, -0.7226028, 0.7975605, -2.094368, 0.702288, -23.364, 0.8024796, 3.5312805 ] + }, + { + "time": 0.8666667, + "x": -2.45504, + "y": 3.4846344, + "curve": [ 0.900976, -2.634102, 0.9666666, -2.871712, 0.9130171, 3.4509735, 0.9666666, -7.635769 ] + }, + { "time": 1, "x": -2.8556595, "y": -13.858932 } + ] + }, + "muzzle-ring": { + "rotate": [ + { "time": 0.23333333, "value": 0.1086235 } + ] + }, + "muzzle-ring2": { + "rotate": [ + { "time": 0.2666667, "value": 0.1086235 } + ] + }, + "muzzle-ring3": { + "rotate": [ + { "time": 0.2666667, "value": 0.1086235 } + ] + }, + "muzzle-ring4": { + "rotate": [ + { "time": 0.2666667, "value": 0.1086235 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.7811, + "curve": [ 0.02514851, 17.929705, 0.07101186, 18.4591 ] + }, + { + "time": 0.13333334, + "value": 18.457026, + "curve": [ 0.1866547, 18.455263, 0.2853263, 17.33772 ] + }, + { + "time": 0.3666667, + "value": 17.33654, + "curve": [ 0.4048635, 17.336, 0.4699174, 17.59838 ] + }, + { + "time": 0.5, + "value": 17.789774, + "curve": [ 0.5176707, 17.9022, 0.5816134, 18.46532 ] + }, + { + "time": 0.6333333, + "value": 18.46029, + "curve": [ 0.7092406, 18.45292, 0.8148, 17.319715 ] + }, + { + "time": 0.8666667, + "value": 17.322073, + "curve": [ 0.9082929, 17.323965, 0.9711425, 17.56992 ] + }, + { "time": 1, "value": 17.7811 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.059132, + "curve": [ 0.04404857, 11.161348, 0.06296488, 11.485394 ] + }, + { + "time": 0.1, + "value": 11.48998, + "curve": [ 0.21508875, 11.49362, 0.3358774, 2.9205174 ] + }, + { + "time": 0.3666667, + "value": 0.8411312, + "curve": [ 0.4164524, -2.521204, 0.4980461, -10.835702 ] + }, + { + "time": 0.6, + "value": -10.82903, + "curve": [ 0.7620489, -10.713412, 0.8446016, -3.045681 ] + }, + { + "time": 0.8666667, + "value": -1.341797, + "curve": [ 0.9168805, 2.535763, 0.977475, 8.81012 ] + }, + { "time": 1, "value": 10.059132 } + ] + }, + "rear-foot-target": { + "rotate": [ + { + "value": -32.81834, + "curve": [ 0.03517772, -42.68637, 0.05715114, -70.49265 ] + }, + { + "time": 0.1, + "value": -70.5925, + "curve": [ 0.23636356, -70.77538, 0.3351397, -9.873116 ] + }, + { + "time": 0.3666667, + "value": -1.5615536, + "curve": [ 0.39346445, 5.503226, 0.4766666, 13.96162 ] + }, + { + "time": 0.5, + "value": 13.96162, + "curve": [ 0.5190303, 13.96162, 0.5078729, 0.13215438 ] + }, + { "time": 0.5666666, "value": -0.2792717 }, + { + "time": 0.7333333, + "value": -0.28445435, + "curve": [ 0.8271056, -0.05950618, 0.9580701, -21.071537 ] + }, + { "time": 1, "value": -32.81834 } + ], + "translate": [ + { + "x": -167.3188, + "y": 0.5788574, + "curve": [ 0.02248509, -180.5451, 0.075, -235.51065, 0.04540817, 0.5788575, 0.075, 30.11717 ] + }, + { + "time": 0.1, + "x": -235.51065, + "y": 39.9159, + "curve": [ 0.14210087, -235.51065, 0.20833333, -201.7273, 0.1383412, 54.94375, 0.17957518, 60.77969 ] + }, + { + "time": 0.23333333, + "x": -176.32953, + "y": 61.47771, + "curve": [ 0.2724341, -136.60674, 0.3205719, -45.17649, 0.2747891, 62.016, 0.32139045, 56.60431 ] + }, + { + "time": 0.3666667, + "x": 8.439873, + "y": 49.66912, + "curve": [ 0.4028122, 51.03225, 0.4857448, 66.86314, 0.4012378, 44.37368, 0.4802278, 23.10683 ] + }, + { "time": 0.5, "x": 66.57163, "y": 14.215683 }, + { "time": 0.5333333, "x": 52.58388, "y": 0.6018922 }, + { "time": 1, "x": -167.3188, "y": 0.5788574 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -17.706324, + "y": -4.631317, + "curve": [ 0.03644444, -19.80997, 0.0431217, -20.85699, 0.03644444, -4.631317, 0.04951704, -7.031244 ] + }, + { + "time": 0.1, + "x": -20.94829, + "y": -7.064457, + "curve": [ 0.1620024, -21.04781, 0.4, 7.791963, 0.2, -7.130247, 0.40004575, -1.8982906 ] + }, + { + "time": 0.5, + "x": 7.791963, + "y": -1.9355936, + "curve": [ 0.6121496, 7.692922, 0.875, -10.491075, 0.5922905, -1.970035, 0.9168845, -3.2536535 ] + }, + { "time": 1, "x": -17.706324, "y": -4.631317 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 28.27774, + "curve": [ 0.03390831, 30.940815, 0.06758396, 32.04713 ] + }, + { + "time": 0.1, + "value": 31.88103, + "curve": [ 0.1942905, 31.013386, 0.3364573, -0.11212158 ] + }, + { + "time": 0.3666667, + "value": -7.11055, + "curve": [ 0.4211193, -19.725266, 0.5301549, -46.211 ] + }, + { + "time": 0.6, + "value": -45.74681, + "curve": [ 0.7075172, -45.03224, 0.8438387, -13.561066 ] + }, + { + "time": 0.8666667, + "value": -6.483352, + "curve": [ 0.9088265, 6.58815, 0.9575854, 24.209595 ] + }, + { "time": 1, "value": 28.27774 } + ] + }, + "torso": { + "rotate": [ + { + "value": -20.71889, + "curve": [ 0.02514851, -20.57028, 0.07101186, -20.040886 ] + }, + { + "time": 0.13333334, + "value": -20.04296, + "curve": [ 0.1866547, -20.044724, 0.2853263, -21.16227 ] + }, + { + "time": 0.3666667, + "value": -21.16345, + "curve": [ 0.4048635, -21.16399, 0.4699174, -20.90161 ] + }, + { + "time": 0.5, + "value": -20.71021, + "curve": [ 0.5176707, -20.597786, 0.5816134, -20.03467 ] + }, + { + "time": 0.6333333, + "value": -20.039696, + "curve": [ 0.7092406, -20.047066, 0.8148, -21.180275 ] + }, + { + "time": 0.8666667, + "value": -21.17792, + "curve": [ 0.9082929, -21.176025, 0.9711425, -20.93007 ] + }, + { "time": 1, "value": -20.71889 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 1.0006008, + "curve": [ 0.005584249, 1.196775, 0.08436342, 2.8825326 ] + }, + { + "time": 0.13333334, + "value": 2.8825326, + "curve": [ 0.2047951, 2.8825326, 0.28441125, -1.1665286 ] + }, + { + "time": 0.3666667, + "value": -1.1665286, + "curve": [ 0.41125, -1.1665286, 0.4809279, 0.57091 ] + }, + { + "time": 0.5, + "value": 1.0006008, + "curve": [ 0.5145121, 1.3275578, 0.5900208, 2.834224 ] + }, + { + "time": 0.6333333, + "value": 2.848558, + "curve": [ 0.6827311, 2.8649056, 0.7959066, -1.204437 ] + }, + { + "time": 0.8666667, + "value": -1.204437, + "curve": [ 0.9160316, -1.204437, 0.983916, 0.6246002 ] + }, + { "time": 1, "value": 1.0006008 } + ] + }, + "torso3": { + "rotate": [ + { "value": -1.810024 } + ] + } + }, + "ik": { + "front-leg-ik": [ + { + "softness": 25.7, + "bendPositive": false, + "curve": [ 0.008333334, 1, 0.025, 1, 0.008333334, 25.7, 0.025, 9.9 ] + }, + { + "time": 0.03333333, + "softness": 9.9, + "bendPositive": false, + "curve": [ 0.15, 1, 0.3833333, 1, 0.15, 9.9, 0.3833333, 43.2 ] + }, + { + "time": 0.5, + "softness": 43.2, + "bendPositive": false, + "curve": [ 0.625, 1, 0.875, 1, 0.625, 43.2, 0.8455136, 45.56755 ] + }, + { "time": 1, "softness": 25.7, "bendPositive": false } + ], + "rear-leg-ik": [ + { "softness": 5, "bendPositive": false }, + { "time": 0.4333333, "softness": 4.9, "bendPositive": false }, + { "time": 0.5, "softness": 28.81148, "bendPositive": false }, + { "time": 0.6, "softness": 43.8, "bendPositive": false }, + { "time": 1, "softness": 5, "bendPositive": false } + ] + }, + "events": [ + { "name": "footstep" }, + { "time": 0.5, "name": "footstep" } + ] + } +} +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-pro.skel b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-pro.skel new file mode 100644 index 0000000..cfcbd39 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-pro.skel differ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-run.atlas b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-run.atlas new file mode 100644 index 0000000..638ec8d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-run.atlas @@ -0,0 +1,44 @@ +spineboy-run.png + size: 1826, 634 + filter: Linear, Linear + pma: true +spineboy-pro-run + index: 8 + bounds: 914, 2, 302, 314 + offsets: 12, 22, 316, 341 +spineboy-pro-run + index: 8 + bounds: 914, 2, 302, 314 + offsets: 12, 22, 316, 341 +spineboy-pro-run + index: 8 + bounds: 914, 2, 302, 314 + offsets: 12, 22, 316, 341 +spineboy-pro-run + index: 8 + bounds: 914, 2, 302, 314 + offsets: 12, 22, 316, 341 +spineboy-pro-run + index: 8 + bounds: 914, 2, 302, 314 + offsets: 12, 22, 316, 341 +spineboy-pro-run + index: 8 + bounds: 914, 2, 302, 314 + offsets: 12, 22, 316, 341 +spineboy-pro-run + index: 8 + bounds: 914, 2, 302, 314 + offsets: 12, 22, 316, 341 +spineboy-pro-run + index: 8 + bounds: 914, 2, 302, 314 + offsets: 12, 22, 316, 341 +spineboy-pro-run + index: 8 + bounds: 914, 2, 302, 314 + offsets: 12, 22, 316, 341 +spineboy-pro-run + index: 8 + bounds: 914, 2, 302, 314 + offsets: 12, 22, 316, 341 diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-run.png b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-run.png new file mode 100644 index 0000000..b8c78c8 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy-run.png differ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy.atlas b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy.atlas new file mode 100644 index 0000000..33f0db1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy.atlas @@ -0,0 +1,84 @@ +spineboy.png + size: 1024, 256 + filter: Linear, Linear + scale: 0.5 +crosshair + bounds: 186, 17, 45, 45 +eye-indifferent + bounds: 137, 17, 47, 45 +eye-surprised + bounds: 623, 45, 47, 45 +front-bracer + bounds: 613, 3, 29, 40 +front-fist-closed + bounds: 278, 2, 38, 41 +front-fist-open + bounds: 233, 18, 43, 44 +front-foot + bounds: 72, 39, 63, 35 +front-shin + bounds: 952, 41, 41, 92 +front-thigh + bounds: 995, 120, 23, 56 +front-upper-arm + bounds: 995, 69, 23, 49 +goggles + bounds: 167, 64, 131, 83 +gun + bounds: 300, 45, 105, 102 +head + bounds: 29, 76, 136, 149 +hoverboard-board + bounds: 167, 149, 246, 76 +hoverboard-thruster + bounds: 674, 8, 30, 32 +hoverglow-small + bounds: 813, 60, 137, 38 +mouth-grind + bounds: 416, 13, 47, 30 +mouth-oooo + bounds: 367, 13, 47, 30 +mouth-smile + bounds: 318, 13, 47, 30 +muzzle-glow + bounds: 706, 15, 25, 25 +muzzle-ring + bounds: 2, 120, 25, 105 +muzzle01 + bounds: 554, 50, 67, 40 +muzzle02 + bounds: 484, 48, 68, 42 +muzzle03 + bounds: 685, 42, 83, 53 +muzzle04 + bounds: 407, 45, 75, 45 +muzzle05 + bounds: 2, 36, 68, 38 +neck + bounds: 2, 97, 18, 21 +portal-bg + bounds: 550, 92, 133, 133 +portal-flare1 + bounds: 484, 16, 56, 30 +portal-flare2 + bounds: 810, 27, 57, 31 +portal-flare3 + bounds: 869, 28, 58, 30 +portal-shade + bounds: 415, 92, 133, 133 +portal-streaks1 + bounds: 685, 97, 126, 128 +portal-streaks2 + bounds: 813, 100, 125, 125 +rear-bracer + bounds: 644, 7, 28, 36 +rear-foot + bounds: 554, 18, 57, 30 +rear-shin + bounds: 770, 6, 38, 89 +rear-thigh + bounds: 991, 178, 28, 47 +rear-upper-arm + bounds: 995, 23, 20, 44 +torso + bounds: 940, 135, 49, 90 diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy.png b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy.png new file mode 100644 index 0000000..6f76c57 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/export/spineboy.png differ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/license.txt b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/license.txt new file mode 100644 index 0000000..ba9fe3d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/license.txt @@ -0,0 +1,8 @@ +Copyright (c) 2013, Esoteric Software LLC + +The images in this project may be redistributed as long as they are accompanied +by this license file. The images may not be used for commercial use of any +kind. + +The project file is released into the public domain. It may be used as the basis +for derivative work. \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/spineboy-ess.spine b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/spineboy-ess.spine new file mode 100644 index 0000000..1594eac Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/spineboy-ess.spine differ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/spineboy-pro.spine b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/spineboy-pro.spine new file mode 100644 index 0000000..112fba1 Binary files /dev/null and b/DateToSpine/third_party/spine-runtimes/4.3/examples/spineboy/spineboy-pro.spine differ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/flags.cmake b/DateToSpine/third_party/spine-runtimes/4.3/flags.cmake new file mode 100644 index 0000000..76bc23c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/flags.cmake @@ -0,0 +1,21 @@ +option(SPINE_SANITIZE "Build with sanitization" OFF) +option(SPINE_SET_COMPILER_FLAGS "Set compiler flags" ON) + +if (NOT SPINE_SET_COMPILER_FLAGS) + return() +endif() + +if(MSVC) + message("MSCV detected") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS") +else() + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic -Wno-unused-parameter -std=c99") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wnon-virtual-dtor -pedantic -Wno-unused-parameter -std=c++11 -fno-exceptions -fno-rtti") + if (${SPINE_SANITIZE}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize=undefined") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize=undefined") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address -fsanitize=undefined") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address -fsanitize=undefined") + endif() +endif() diff --git a/DateToSpine/third_party/spine-runtimes/4.3/generate-bindings.sh b/DateToSpine/third_party/spine-runtimes/4.3/generate-bindings.sh new file mode 100755 index 0000000..60bf4b3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/generate-bindings.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +set -euo pipefail + +# Script to generate all Spine runtime bindings +# This script regenerates bindings for C, Flutter, and iOS + +# Get the directory containing this script +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +rm -rf "$SCRIPT_DIR/spine-c/codegen/spine-cpp-types.json" +rm -rf "$SCRIPT_DIR/spine-c/codegen/node_modules" +rm -rf "$SCRIPT_DIR/spine-flutter/codegen/node_modules" +rm -rf "$SCRIPT_DIR/spine-ios/codegen/node_modules" + +# Source logging utilities +source "$SCRIPT_DIR/formatters/logging/logging.sh" + +log_title "Generating all Spine runtime bindings" + +# Generate C bindings and test compilation +log_info "Generating C bindings" +( + cd "$SCRIPT_DIR/spine-c" + ./build.sh codegen +) + +# Generate Flutter bindings +log_info "Generating Dart bindings" +( + cd "$SCRIPT_DIR/spine-flutter" + ./generate-bindings.sh +) + +# Generate iOS Swift bindings +log_info "Generating Swift bindings for iOS" +( + cd "$SCRIPT_DIR/spine-ios" + ./generate-bindings.sh +) + +log_summary "All bindings generated successfully" diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/.vscode/launch.json b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/.vscode/launch.json new file mode 100644 index 0000000..5bcbea2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/.vscode/launch.json @@ -0,0 +1,22 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "headless test (cpp)", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/headless-test", + "args": [ + "${workspaceFolder}/../examples/spineboy/export/spineboy-pro.json", + "${workspaceFolder}/../examples/spineboy/export/spineboy-pma.atlas", + "run" + ], + "stopAtEntry": false, + "cwd": "${workspaceFolder}/build", + "environment": [], + "externalConsole": false, + "MIMode": "lldb", + "preLaunchTask": "CMake: build" + } + ] +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/CMakeLists.txt b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/CMakeLists.txt new file mode 100644 index 0000000..35ce553 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.10) +project(spine-cpp) + +include(${CMAKE_CURRENT_LIST_DIR}/../flags.cmake) + +option(SPINE_NO_FILE_IO "Disable file I/O operations" OFF) + +include_directories(include) +file(GLOB INCLUDES "include/**/*.h") +file(GLOB SOURCES "src/**/*.cpp") + +add_library(spine-cpp STATIC ${SOURCES} ${INCLUDES}) +target_include_directories(spine-cpp PUBLIC include) + +if(SPINE_NO_FILE_IO) + target_compile_definitions(spine-cpp PRIVATE SPINE_NO_FILE_IO) +endif() + +# Install target +install(TARGETS spine-cpp EXPORT spine-cpp_TARGETS DESTINATION dist/lib) +install(FILES ${INCLUDES} DESTINATION dist/include) + +# Export target +export( + EXPORT spine-cpp_TARGETS + FILE ${CMAKE_CURRENT_BINARY_DIR}/spine-cppTargets.cmake + NAMESPACE "Spine::") + +# Optional tests +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + add_executable(headless-test ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp) + target_link_libraries(headless-test spine-cpp) + + add_executable(map-test ${CMAKE_CURRENT_SOURCE_DIR}/tests/MapTest.cpp) + target_link_libraries(map-test spine-cpp) + + enable_testing() + add_test(NAME map-test COMMAND map-test) + + if(SPINE_NO_FILE_IO) + target_compile_definitions(headless-test PRIVATE SPINE_NO_FILE_IO) + endif() + + # Static variants (Linux only, but not with sanitizers) + if(UNIX AND NOT APPLE AND NOT SPINE_SANITIZE) + add_executable(headless-test-static ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp) + target_link_libraries(headless-test-static spine-cpp) + target_link_options(headless-test-static PRIVATE -static) + + if(SPINE_NO_FILE_IO) + target_compile_definitions(headless-test-static PRIVATE SPINE_NO_FILE_IO) + endif() + endif() +endif() \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/CMakePresets.json b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/CMakePresets.json new file mode 100644 index 0000000..3aa553b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/CMakePresets.json @@ -0,0 +1,35 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "debug", + "displayName": "Debug Config", + "description": "Debug build using Ninja generator", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + }, + { + "name": "release", + "inherits": "debug", + "displayName": "Release Config", + "description": "Release build using Ninja generator", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + } + ], + "buildPresets": [ + { + "name": "debug", + "configurePreset": "debug" + }, + { + "name": "release", + "configurePreset": "release" + } + ] +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/LICENSE b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/LICENSE new file mode 100644 index 0000000..517ff9f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/LICENSE @@ -0,0 +1,26 @@ +Spine Runtimes License Agreement +Last updated April 5, 2025. Replaces all prior versions. + +Copyright (c) 2013-2025, Esoteric Software LLC + +Integration of the Spine Runtimes into software or otherwise creating +derivative works of the Spine Runtimes is permitted under the terms and +conditions of Section 2 of the Spine Editor License Agreement: +https://esotericsoftware.com/spine-editor-license + +Otherwise, it is permitted to integrate the Spine Runtimes into software +or otherwise create derivative works of the Spine Runtimes (collectively, +"Products"), provided that each user of the Products must obtain their own +Spine Editor license and redistribution of the Products in any form must +include this license and copyright notice. + +THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, +BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/README.md b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/README.md new file mode 100644 index 0000000..2f2d12d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/README.md @@ -0,0 +1,56 @@ +# spine-cpp + +The spine-cpp runtime provides basic functionality to load and manipulate [spine](http://esotericsoftware.com) skeletal animation data using C++. It does not perform rendering but can be extended to enable spine animations for other projects that utilize C++. + +## Licensing + +You are welcome to evaluate the Spine Runtimes and the examples we provide in this repository free of charge. + +You can integrate the Spine Runtimes into your software free of charge, but users of your software must have their own [Spine license](https://esotericsoftware.com/spine-purchase). Please make your users aware of this requirement! This option is often chosen by those making development tools, such as an SDK, game toolkit, or software library. + +In order to distribute your software containing the Spine Runtimes to others that don't have a Spine license, you need a [Spine license](https://esotericsoftware.com/spine-purchase) at the time of integration. Then you can distribute your software containing the Spine Runtimes however you like, provided others don't modify it or use it to create new software. If others want to do that, they'll need their own Spine license. + +For the official legal terms governing the Spine Runtimes, please read the [Spine Runtimes License Agreement](http://esotericsoftware.com/spine-runtimes-license) and Section 2 of the [Spine Editor License Agreement](http://esotericsoftware.com/spine-editor-license#s2). + +## Spine version + +spine-cpp works with data exported from spine 4.3.xx. + +spine-cpp supports all spine features. + +## Usage + +### [Please see the spine-cpp guide for full documentation](http://esotericsoftware.com/spine-cpp) + +## Setup + +### Manual Copy + +1. Download the spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it as a zip via the download button above. +2. Copy the contents of the `spine-cpp/spine-cpp/src` and `spine-cpp/spine-cpp/include` directories into your project. Be sure your header search is configured to find the contents of the `spine-cpp/spine-cpp/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files. + +### CMake + +You can use CMake's FetchContent to include spine-cpp in your project: + +```cmake +include(FetchContent) +FetchContent_Declare( + spine-runtimes + GIT_REPOSITORY https://github.com/EsotericSoftware/spine-runtimes.git + GIT_TAG 4.3 +) +FetchContent_MakeAvailable(spine-runtimes) + +add_subdirectory(${spine-runtimes_SOURCE_DIR}/spine-cpp ${spine-runtimes_BINARY_DIR}/spine-cpp) +target_link_libraries(your_target PRIVATE spine-cpp) +``` + +## Runtimes extending spine-cpp +- [spine-glfw](../spine-glfw) +- [spine-sdl](../spine-sdl) +- [spine-sfml](../spine-sfml/cpp) +- [spine-godot](../spine-godot) +- [spine-ue](../spine-ue) +- [spine-flutter (via spine-c & FFI)](../spine-flutter) +- [spine-ios (via spine-c & FFI)](../spine-ios) \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/build.sh b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/build.sh new file mode 100755 index 0000000..4e2069c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/build.sh @@ -0,0 +1,68 @@ +#!/bin/bash +set -e + +cd "$(dirname "$0")" + +# Source logging utilities +source ../formatters/logging/logging.sh + +# Parse arguments +BUILD_TYPE="debug" +NOFILEIO="" +SANITIZE="" +CLEAN="" + +for arg in "$@"; do + case $arg in + clean) + CLEAN="true" + ;; + release) + BUILD_TYPE="release" + ;; + debug) + BUILD_TYPE="debug" + ;; + nofileio) + NOFILEIO="-DSPINE_NO_FILE_IO=ON" + ;; + sanitize) + SANITIZE="-DSPINE_SANITIZE=ON" + ;; + *) + log_fail "Unknown argument: $arg" + log_detail "Usage: $0 [clean] [release|debug] [nofileio] [sanitize]" + exit 1 + ;; + esac +done + +log_title "spine-cpp build" + +# Clean if requested +if [ "$CLEAN" = "true" ]; then + log_action "Cleaning build directory" + rm -rf build + log_ok +fi + +# Configure and build +log_action "Configuring $BUILD_TYPE build" +if CMAKE_OUTPUT=$(cmake --preset=$BUILD_TYPE $NOFILEIO $SANITIZE . 2>&1); then + log_ok +else + log_fail + log_error_output "$CMAKE_OUTPUT" + exit 1 +fi + +log_action "Building" +if BUILD_OUTPUT=$(cmake --build --preset=$BUILD_TYPE 2>&1); then + log_ok +else + log_fail + log_error_output "$BUILD_OUTPUT" + exit 1 +fi + +log_summary "✓ Build successful" \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/docs.md b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/docs.md new file mode 100644 index 0000000..8400cc5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/docs.md @@ -0,0 +1,1011 @@ +# spine-c Runtime Documentation + +> **Licensing** +> +> Please see the [Spine Runtimes License](/spine-runtimes-license) before integrating the Spine Runtimes into your applications. + +# Introduction +spine-c is a generic runtime for integrating Spine animations in game engines and frameworks written in C, C++, Swift, Rust, Objective-C or any other language that can natively interface with C. + +spine-c provides functionality to + +* [Load Spine skeletons](/spine-loading-skeleton-data) exported to JSON or binary files. +* [Load texture atlases](/spine-loading-skeleton-data) storing the images used by the Spine skeletons. +* Manage and apply [skins](/spine-runtime-skins) to the skeleton. +* Manage and apply [animations](/spine-applying-animations) to the skeleton. +* Manipulate and compute data required for rendering and physics based on the current [skeleton pose, slots & attachments states](/spine-runtime-skeletons). + +As the spine-c runtime is a generic, engine independent runtime, users are required to implement a set of functions to provide engine specific file i/o and image loading to the spine-c runtime, render the data generated by the spine-c runtime via the engine's rendering system, and optionally integrate the data with the engine's physics system if more advanced use cases such as rag dolls are required. + +The spine-c runtime is written using C99 to guarantee compatibility with a wide range of platforms and compilers. + +Other official Spine runtimes are based on spine-c and can serve as examples for integration with your engine of choice: + +* [spine-sfml](/git/spine-runtimes/tree/spine-sfml/c), a runtime for [SFML](http://www.sfml-dev.org/). +* [spine-sdl](/git/spine-runtimes/tree/spine-sdl/), a runtime for [SDL](https://www.libsdl.org/). + +The following sections give a brief, engine independent overview of the spine-c runtime and how to use it. Most of the official Spine runtimes based on spine-c will encapsulate (parts of) the spine-c API in their own, easier to use API. It is still beneficial to understand the basics of the underlying spine-c runtime. + +> **Note:** This guide assumes you are familiar with the basic [runtime architecture](/spine-runtime-architecture) and terminology used by Spine. Please also consult the [API reference](/spine-api-reference) to explore more advanced functions of the runtime. + +# Exporting Spine assets for spine-c +![](/img/spine-runtimes-guide/spine-ue4/export.png) +Please follow the instructions in the Spine User Guide on how to + +1. [Export skeleton & animation data](/spine-export) to JSON or our binary format +2. [Export texture atlases containing the images of your skeleton](/spine-texture-packer) + +An export of the skeleton data and texture atlas of your skeleton will yield the following files: + +![](/img/spine-runtimes-guide/spine-ue4/exported-files.png) + +1. `skeleton-name.json` or `skeleton-name.skel`, containing your skeleton and animation data. +2. `skeleton-name.atlas`, containing information about the texture atlas. +3. One or more `.png` files, each representing one page of your texture atlas containing the packed images your skeleton uses. + +> **Note:** Instead of creating one texture atlas per skeleton, you may also pack the images of multiple skeletons into a single texture atlas. Please refer to the [texture packing guide](/spine-texture-packer). + +# Loading Spine assets +spine-c provides APIs to load texture atlases, Spine skeleton data (bones, slots, attachments, skins, animations) and define mix times between animations through [animation state data](/spine-applying-animations#Mix-times). These three types of data, also known as setup pose data, are generally loaded once and then shared by every game object. The sharing mechanism is achieved by giving each game object its own skeleton and [animation state](/spine-applying-animations#AnimationState-API), also known as instance data. + +> **Note:** For a more detailed description of the overall loading architecture consult the generic [Spine Runtime Documentation](/spine-loading-skeleton-data). + +## Loading texture atlases +Texture atlas data is stored in a custom [atlas format](/spine-atlas-format) that describes the location of individual images within atlas pages. The atlas pages themselves are stored as plain `.png` files next to the atlas. + +spine-c provides the functions [spAtlas_createFromFile](/git/spine-runtimes/blob/spine-c/spine-c/src/spine/Atlas.c#L301) and [spAtlas_create](/git/spine-runtimes/blob/spine-c/spine-c/src/spine/Atlas.c#L167) for this task. The former loads the atlas from a file, the latter reads the atlas from memory. If loading the atlas failed, the functions return 0. + +``` +// Load the atlas from a file. The last argument is a void* that will be +// stored in atlas->rendererObject. +spAtlas* atlas = spAtlas_createFromFile("myatlas.atlas", 0); + +// Load the atlas from memory, giving the memory location, the number +// of bytes and the directory relative to which atlas page textures +// should be loaded. The last argument is a void* that will be stored +// in atlas-rendererObject. +spAtlas* atlas = spAtlas_create(atlasInMemory, atlasDataLengthInBytes, dir, 0); +``` + +## Loading skeleton data +Skeleton data (bones, slots, attachments, skins, animations) can be exported to human readable [JSON](/spine-json-format) or a custom [binary format](/spine-binary-format). spine-c stores skeleton data in `spSkeletonData` structs. + +For loading the skeleton data from a JSON export, we create a `spSkeletonJson` which takes the previously loaded `spAtlas`, set the scale of the skeleton and finally read the skeleton data from the file: + +``` +// Create a spSkeletonJson used for loading and set the scale +// to make the loaded data two times as big as the original data +spSkeletonJson* json = spSkeletonJson_create(atlas); +json->scale = 2; + +// Load the skeleton .json file into a spSkeletonData +spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, filename); + +// If loading failed, print the error and exit the app +if (!skeletonData) { + printf("%s\n", json->error); + spSkeletonJson_dispose(json); + exit(0); +} + +// Dispose the spSkeletonJson as we no longer need it after loading. +spSkeletonJson_dispose(json); +``` + +Loading skeleton data from a binary export works the same, except we use a `spSkeletonBinary` instead: + +``` +// Create a spSkeletonJson used for loading and set the scale +// to make the loaded data two times as big as the original data +spSkeletonBinary* binary = spSkeletonBinary_create(atlas); +binary->scale = 2; + +// Load the skeleton .skel file into a spSkeletonData +spSkeletonData* skeletonData = spSkeletonBinary_readSkeletonDataFile(binary, filename); + +// If loading failed, print the error and exit the app +if (!skeletonData) { + printf("%s\n", binary->error); + spSkeletonBinary_dispose(json); + exit(0); +} + +// Dispose the spSkeletonBinary as we no longer need it after loading. +SkeletonBinary_dispose(json); +``` + +## Preparing animation state data +Spine supports smooth transitions (crossfades) when switching from one animation to another. The crossfades are achieved by mixing one animation with another for a specific mix time. The spine-c runtime provides the `spAnimationStateData` struct to define these mix times: + +``` +// Create the spAnimationStateData +spAnimationStateData* animationStateData = spAnimationStateData_create(skeletonData); + +// Set the default mix time between any pair of animations in seconds. +spAnimationStateData_setDefaultMix(animationStateData, 0.1f); + +// Set the mix time between from the "jump" to the "walk" animation to 0.2 seconds, +// overwriting the default mix time for this from/to pair. +spAnimationStateData_setMixByName(animationStateData, "jump", "walk", 0.2f); +``` + +The mix times defined in `spAnimationStateData` can also be overwritten explicitly when applying animations (see below). + +# Skeletons +Setup pose data (skeleton data, texture atlases) are supposed to be shared between game objects. spine-c provides the `spSkeleton` struct to facilitate this sharing. Every game object receives its own instance of `spSkeleton` which in turn references an `spSkeletonData` and `spAtlas` instance as data sources. + +The `spSkeleton` can be freely modified, e.g. by procedurally modifying bones, applying animations or setting attachments and skins specific to a game object, while the underlying skeleton data and texture atlas stay in tact. This mechanism and setup allow sharing `spSkeletonData` and `spAtlas` instances by any amount of game objects. + +## Creating skeletons +To create a `spSkeleton` instance, call `spSkeleton_create`: + +``` +spSkeleton* skeleton = spSkeleton_create(skeletonData); +``` + +Every game object will need its own `spSkeleton`. The bulk of the data remains in `spSkeletonData` and `spAtlas` and will be shared by all `spSkeleton` instances to vastly reduce memory consumption and texture switches. The life-time of an `spSkeleton` is thus coupled with the life-time of its corresponding game object. + +## Bones +A skeleton is a hierarchy of bones, with slots attached to bones, and attachments attached to slots. + +### Finding bones +All bones in a skeleton have a unique name by which they can be fetched from the skeleton: + +``` +// returns 0 if no bone of that name could be found +spBone* bone = spSkeleton_findBone("mybone"); +``` + +### Local transform +A bone is affected by its parent bone, all the way back to the root bone. E.g. when rotating a bone, all its child bones and all their children are also rotated. To accomplish these hierarchical transformations, each bone has a local transformation relative to its parent bone consisting of: + +* `x` and `y` coordinates relative to the parent. +* `rotation` in degrees. +* `scaleX` and `scaleY`. +* `shearX` and `shearY` in degrees. + +The local transform of a bone can be manipulated procedurally or via applying an animation. The former allows to implement dynamic behavior like having a bone point at a mouse cursor, let feet bones follow the terrain etc. Both procedural modification of the local transform as well as applying animations can be done simultaneously. The end result will be a single combined local transform. + +### World transform +Once all the local transforms are setup, either through procedurally modifying the local transforms of bones or by applying animations, we need the world transform of each bone for rendering and physics. + +The calculation starts at the root bone, and then recursively calculates all child bone world transforms. The calculation also applies [IK](/spine-ik-constraints), [transform](/spine-transform-constraints) and [path](/spine-path-constraints) constraints defined by the artist in the Spine editor. + +To calculate the world transforms, we need to first update the skeleton's frame time for physics, followed by calculating the actual transforms: + +``` +spSkeleton_update(deltaTime); +spSkeleton_updateWorldTransform(skeleton, SP_PHYSICS_UPDATE); +``` + +`deltaTime` specifies the time passed between the current and last frame, given in seconds. The second parameter to `spSkeleton_updateWorldTransform` specifies if and how physics should be applied. `SP_PHYSICS_UPDATE` is a good default value. + +The result is stored on each bone, and consists of: + +* `a`, `b`, `c`, and `d`, a 2x2 column major matrix encoding rotation, scale and shear of the bone. +* `worldX`, `worldY`, storing the world position of the bone. + +Note that `worldX` and `worldY` are offset by `skeleton->x` and `skeleton->y`. These two fields can be used to position the skeleton in your game engine's world coordinate system. + +In general, the bones world transforms should never be modified directly. Instead, they should always be derived from the local transforms of the bones in the skeleton by calling `spSkeleton_updateWorldTransform`. The local transforms can be set either procedurally, e.g. setting the rotation of a bone so it points to the mouse cursor, or by applying animations (see below), or both. Once the (procedural) animation is applied, `spSkeleton_updateWorldTransform` is called and the resulting world transforms are recalculated based on the local transform as well as any constraints that are applied to bones. + +### Converting between coordinate systems +It is often easier to manipulate bones in the world coordinate system, as this is where coordinates from other entities or input events are usually given. However, since the world transform should not be directly manipulated, we need to apply any changes to a bone based on world coordinate system calculations to the local transform of that bone. + +The spine-c runtimes provides functions to extract rotation and scale information from the 2x2 world transform matrix of a bone, and transform locations and rotations from local space to world space and vice versa. All these functions assume that the bones' world transforms have been calculated before by calling `spSkeleton_updateWorldTransform`: + +``` +spBone* bone = spSkeleton_findBone("mybone"); + +// Get the rotation of a bone in world space relative to the world space x-axis in degrees +float rotationX = spBone_getWorldRotationX(bone); + +// Get the rotation of a bone in world space relative to the world space y-axis in degrees +float rotationY = spBone_getWorldRotationY(bone); + +// Get the scale of a bone in world space relative to the world space x-axis +float scaleX = spBone_getWorldScaleX(bone); + +// Get the scale of a bone in world space relative to the world space y-axis +float scaleY = spBone_getWorldScaleY(bone); + +// Transform a position given in world space to a bone's local space +float localX = 0, localY = 0; +spBone_worldToLocal(bone, worldX, worldY, &localX, &localY); + +// Transform a position given in a bone's local space to world space +float worldX = 0, worldY = 0; +spBone_localToWorld(bone, localX, localY, &worldX, &worldY); + +// Transform a rotation given in the bone's world transform relative to the world space x-axis to // a rotation given in local space relative to the local space x-axis in degrees. +float localRotationX = spBone_worldToLocalRotationX(bone) + +// Transform a rotation given in the bone's world transform relative to the world space y-axis to // a rotation given in local space relative to the local space y-axis in degrees. +float localRotationY = spBone_worldToLocalRotationY(bone) +``` + +> **Note:** Your modifications to the local transform of a bone (and thereby all its children) will be reflect in the bone's world transform after the next call to `spSkeleton_updateWorldTransform`. + +## Positioning +By default, a skeleton is assumed to be at the origin of the game's world coordinate system. To position a skeleton in a game's world coordinate system, you can use the `x` and `y` field: + +``` +// make a skeleton follow a game object in world space +skeleton->x = myGameObject->worldX; +skeleton->y = myGameObject->worldY; +``` + +> **Note:** Your modifications to the skeleton `x` and `y` fields will be reflect in the bone world transforms after the next call to `spSkeleton_updateWorldTransform`. + +## Flipping +A skeleton can be flipped vertically or horizontally. This allows reusing animations made for one direction for the opposing direction, or for working in coordinate systems with the y-axis pointing downwards (Spine assumes y-axis up by default): + +``` +// flip vertically around the x-axis +skeleton->scaleY = -1; + +// flip horizontally around the y-axis +skeleton->scaleX = -1; +``` + +> **Note:** Your modifications to the skeleton `scaleX` and `scaleY` fields will be reflected in the bone world transforms after the next call to `spSkeleton_updateWorldTransform`. + +## Setting skins +The artist creating the Spine skeleton may have added multiple [skins](/spine-runtime-skins) to the skeleton to add visual variations of the same skeleton, e.g. a female and male version. The spine-c runtime stores skins in instances of `spSkin`. + +A [skin at runtime](/spine-runtime-skins) is a map defining which [attachment](/spine-basic-concepts#Attachments) goes into which [slot](/spine-basic-concepts#Slots) of the skeleton. Every skeleton has at least one skin which defines which attachment is on what slot in the skeleton's setup pose. Additional skins have a name to identify them. + +Setting a skin on a skeleton via spine-c: + +``` +// set a skin by name +spSkeleton_setSkin(skeleton, "my_skin_name"); + +// set the default setup pose skin by passing 0 +spSkeleton_setSkin(skeleton, 0); +``` + +> **Note:** Setting a skin takes into account what skin and hence which attachments have previously been set. Please refer to the generic runtime guide for [more information on setting skins](/spine-runtime-skins#Skin-changes). + +## Setting attachments +spine-c allows setting a single attachment on a skeleton's slot directly, e.g. to switch out weapons. The attachment is first searched in the active skin, and if this fails, in the default setup pose skin: + +``` +// Set the attachment called "sword" on the "hand" slot +spSkeleton_setAttachment(skeleton, "hand", "sword"); + +// Clear the attachment on the slot "hand" so nothing is shown +spSkeleton_setAttachment(skeleton, "hand", 0); +``` + +### Tinting +You can tint all attachments in a skeleton by setting the skeleton's color: + +``` +spSkeleton* skeleton = ... + +// tint all attachments with red and make the skeleton half translucent. +skeleton->r = 1.0f; +skeleton->g = 0.0f; +skeleton->b = 0.0f; +skeleton->a = 0.5f; +``` + +> **Note:** Colors in spine-c are given as RGBA, with values for each channel in the range [0-1]. + +When rendering a skeleton, the renderer walks though the draw order of slots on the skeleton and renders the currently active attachment on each slot. In addition to the skeleton's color, every slot also has a color which can be manipulated at runtime: + +``` +spSlot* slot = skeleton->findSlotByName("mySlot"); +slot->r = 0.0f; +slot->g = 1.0f; +slot->b = 0.0f; +slot->a = 1.0f; +``` + +Note that slot colors can also be animated. If you manually change a slot's color and then apply an animation that keys that slot's color, your manual change will be overwritten. + +# Applying animations +The Spine editor lets artists create multiple, uniquely named [animations](/spine-animating). An animation is a set of [timelines](/spine-api-reference#Timeline). Each timeline specifies at what frame what property of a bone or the skeleton should change to what value. There are many different types of timelines, from timelines defining the transform of a bone over time, to timelines that change the drawing order. Timelines are part of the skeleton data and stored in `spSkeletonData` in spine-c. + +## Timeline API +spine-c provides a [timeline API](/spine-applying-animations#Timeline-API) should the need arise to directly work with timelines. This low-level functionality allows you to fully customize the way animations defined by your artist are applied to a skeleton. + +## Animation state API +In almost all cases, you should use the [animation state API](/spine-applying-animations#AnimationState-API) instead of the timeline API. The animation state API makes task such as applying animations over time, queueing animations, mixing between animations, and applying multiple animations at the same time considerably easier than the low-level timeline API. The animation state API uses the timeline API internally and can thus be seen as a wrapper. + +spine-c represents an animation state via the `spAnimationState` struct. Just like skeletons, an `spAnimationState` is instantiated per game object. In general, you will have one `spSkeleton` and one `spAnimationState` instance per game object in your game. And just like `spSkeleton`, the `spAnimationState` will share `spSkeletonData` (wherein animations and their timelines are stored) and `spAnimationStateData` (wherein mix times are stored) with all other `spAnimationState` instances sourcing the same skeleton data. + +### Creating animation states +To create an `spAnimationState`instance, call `spAnimationState_create`: + +``` +spAnimationState* animationState = spAnimationState_create(animationStateData); +``` + +The function takes an `spAnimationStateData` which is usually created when the skeleton data is loaded, and which defines the default mix time as well as mix times between specific animations for [crossfades](/spine-applying-animations#Mix-times). + +### Tracks & Queueing +An animation state manages one or more [tracks](/spine-applying-animations#Tracks). Each track is a list of animations that should be played back in the order they were added to the track. This is known as [queuing](/spine-applying-animations#Queuing). Tracks are indexed starting from 0. + +You can queue an animation on a track like this: + +``` +// Add the animation "walk" to track 0, without delay, and let it loop indefinitely +int track = 0; +int loop = 1; +float delay = 0; +spAnimationState_addAnimationByName(animationState, track, "walk", loop, delay); +``` + +You can queue multiple animations at once as a fire and forget way to create animation sequences: + +``` +// Start walking (note the looping) +spAnimationState_addAnimationByName(animationState, 0, "walk", 1, 0); + +// Jump after 3 seconds +spAnimationState_addAnimationByName(animationState, 0, "jump", 0, 3); + +// Once we are done jumping, idle indefinitely +spAnimationState_addAnimationByName(animationState, 0, "idle", 1, 0); +``` + +You can also clear all animations queued in a track: + +``` +// Clear all animations queued on track 0 +spAnimationState_clearTrack(animationState, 0); + +// Clear all animations queued on all tracks +spAnimationState_clearTracks(animationState); +``` + +Instead of clearing and adding a new animation to a track, you can call `spAnimationState_setAnimationByName`. This will clear all tracks, but remember what the last played back animation was before clearing and crossfade to the newly set animation. This way you can smoothly transition from one animation sequence to the next. You can add more animations to the track after calling `spAnimationState_setAnimationByName` by calling `spAnimationState_addAnimationByName`: + +``` +// Whatever is currently playing on track 0, clear the track and crossfade +// to the "shot" animation, which should not be looped (last parameter). +spAnimationState_setAnimationByName(animationState, 0, "shot", 0); + +// After shooting, we want to idle again +spAnimationState_addAnimationByName(animationState, 0, "idle", 1, 0); +``` + +To crossfade to the setup pose of the skeleton from an animation, you can use `spAnimationState_setEmptyAnimation`, `spAnimationState_addEmptyAnimation`, where the former clears the current track and crossfades to the skeleton, and the later enqueues a crossfade to the setup pose as part of the animation sequence on the track: + +``` +// Whatever is currently playing on track 0, clear the track and crossfade +// to the setup pose for 0.5 seconds (mix time) with a delay of 1 second. +spAnimationState_setEmptyAnimation(animationState, 0, 0.5f, 1); + +// Add a crossfade to the setup pose for 0.5 seconds as part of the animation +// sequence in track 0 +spAnimationState_addEmptyAnimation(animationState, 0, 0.5f) +``` + +For simple games, using a single track is usually enough to achieve your goals. More complex games may want to queue animations on separate tracks, e.g. to simultaneously play back a walk animation while shooting. This is where the real power of Spine comes into play: + +``` +// Apply the "walk" animation on track 0 indefinitely. +spAnimationState_setAnimationByName(animationState, 0, "walk", 1); + +// Simultaneously apply a "shot" animation on track 1 once. +spAnimationState_setAnimationByName(animationState, 1, "shot", 0); +``` + +Note that if you apply animations simultaneously like that, animations on the higher track will overwrite animations on the lower track for every value both animations have keyed. For authoring animations, this means to make sure two animations to be played back simultaneously don't key the same values in the skeleton, e.g. the same bone, attachment, color etc. + +You can control the mixing of animations on different track via [track entries](/spine-applying-animations#TrackEntry) + +### Track Entries +Every time you enqueue an animation on a track of an animation state, the corresponding functions will return an `spTrackEntry` instance. This track entry allows you to further customize both the queued animation, as well as its mixing behaviour with regards to animations on the same or other tracks. See the [TrackEntry documentation](/spine-api-reference#TrackEntry) for a full list of fields you can modify. + +As an example, lets assume the mix time between a "walk" and "run" animation defined in an `spAnimationStateData` is to high for this specific game object in its current situation. You can modify the mix time between "walk" and "run" ad-hoc, just for this specific queued animation: + +``` +// Walk indefinitely +spAnimationState_setAnimationByName(animationState, 0, "walk", 1); + +// At some point, queue the run animation. We want to speed up the mixing +// between "walk" and "run" defined in the `spAnimationStateData` (let's say 0.5 seconds) +// for this one specific call to be faster (0.1 seconds). +spTrackEntry* entry = spAnimationState_addAnimationByName(animationState, 0, "run", 1, 0); +entry->mixDuration = 0.1f; +``` + +You can hold on to the `spTrackEntry` to modify it over time. The `spTrackEntry` will be valid for as long as the animation is queued on that track. Once the animation is completed, the `spTrackEntry` will be deallocated. Any subsequent access will be invalid and likely result in a segfault. You can register a listener to get notified when the animation and hence the track entry are no longer valid. + +### Events +An animation state generates events while playing back queued animations to notify a listener about changes: + +* An animation **started**. +* An animation was **interrupted**, e.g. by clearing a track. +* An animation was **completed**, which may occur multiple times if looped. +* An animation has **ended**, either due to interruption or it has completed and is not looped. +* An animation and its corresponding `spTrackEntry` have been **disposed** and are no longer valid. +* A [user defined **event**](/spine-events) was fired. + +You can listen for these events by registering a function either with the animation state, or with individual `spTrackEntry` instances returned by the animation state. + +``` +// Define the function that will be called when an event happens +void myListener(spAnimationState* state, spEventType type, spTrackEntry* entry, spEvent* event) { + switch (type) { + // + case SP_ANIMATION_START: + printf("Animation %s started on track %i\n", entry->animation->data->name, entry->trackIndex); + break; + case SP_ANIMATION_INTERRUPT: + printf("Animation %s interrupted on track %i\n", entry->animation->data->name, entry->trackIndex); + break; + case SP_ANIMATION_END: + printf("Animation %s ended on track %i\n", entry->animation->data->name, entry->trackIndex); + break; + case SP_ANIMATION_COMPLETE: + printf("Animation %s completed on track %i\n", entry->animation->data->name, entry->trackIndex); + break; + case SP_ANIMATION_DISPOSE: + printf("Track entry for animation %s disposed on track %i\n", entry->animation->data->name, entry->trackIndex); + break; + case SP_ANIMATION_EVENT: + printf("User defined event for animation %s on track %i\n", entry->animation->data->name, entry->trackIndex); + printf("Event: %s: %d, %f, %s\n", event->data->name, event->intValue, event->floatValue, event->stringValue); + break; + default: + printf("Unknown event type: %i", type); + } +} + +// Register the function as a listener on the animation state. It will be called for all +// animations queued on the animation state. +animationState->listener = myListener; + +// Or you can register the function as a listener for events for a specific animation you enqueued +spTrackEntry* trackEntry = spAnimationState_setAnimationByName(animationState, 0, "walk", 1); +trackEntry->listener = myListener; +``` + +User defined events are perfect to markup times in an animation at which sounds should be played back, e.g. foot steps. + +Changes made to the animation state within a listener, such as setting a new animation, are not applied to skeletons until the next time `spAnimationState_apply` is called. You can immediately apply the changes within the listener: + +``` +void myListener(spAnimationState* state, spEventType type, spTrackEntry* entry, spEvent* event) { + if (somecondition) { + spAnimationState_setAnimation(state, 0, "run", 0); + spAnimationState_update(0); + spAnimationState_apply(skeleton); + } +} +``` + +### Applying animation states +Animation states are inherently time-based. To advance their state, you will need to update them every tick, supplying the amount of time that has passed since the last update in seconds: + +``` +spAnimationState_update(deltaTime); +``` + +This will advance the playback of animations on each track, coordinate crossfades and call any listeners you might have registered. + +After updating the animation state, you generally want to apply it to a skeleton to update its bones local transforms, attachments, slot colors, draw order and anything else that can be animated: + +``` +spAnimationState_apply(skeleton); +``` + +With the skeleton posed and animated, you finally update its frame time and bones' world transforms to prepare it for rendering or physics: + +``` +spSkeleton_update(deltaTime); +spSkeleton_updateWorldTransform(skeleton); +``` + +# Memory management +We have tried to make spine-c memory as straight forward as possible. Any struct that is allocated via `spStructName_create` needs to be deallocated with the corresponding `spStructName_dispose`. The life-times of structs depends on what type of struct it is. General rules of thumb: + +* Create setup pose data shared by instance data (`spAtlas`, `spSkeletonData`, `spAnimationStateData`) at game or level startup, dispose it at game or level end. +* Create instance data (`spSkeleton`, `spAnimationState`) when the corresponding game object is created, dispose it when the corresponding game object is destroyed. + +Track entries (`spTrackEntry`) are valid from a call to one of the enqueuing animation state functions (`spAnimationState_setAnimationByName`, `spAnimationState_addAnimationByName`, `spAnimationState_setEmptyAnimation`, `spAnimationState_addEmptyAnimation`) until the `SP_ANIMATION_DISPOSE` event is send to your listener. Accessing the track entry after this event will likely result in a segmentation fault. + +When creating structs, you often pass in other structs as references. The referencing struct will never dispose the referenced struct. E.g. an `spSkeleton` references an `spSkeletonData` which in turn references an `spAtlas`. + +* Disposing the `spSkeleton` will not dispose the `spSkeletonData` nor the `spAtlas`. This makes sense, as the `spSkeletonData` is likely shared by other `spSkeleton`instances. +* Disposing the `spSkeletonData` will not dispose the `spAtlas`. This also makes sense, as the `spAtlas` may be shared by other `spSkeletonData` instances, e.g. if the atlas contains the images of multiple skeletons. + +If you use a custom allocator, you can overwrite Spine's allocation strategy (using `malloc`, `realloc` and `free`, by changing the defines in [extension.h](/git/spine-runtimes/blob/spine-c/spine-c/include/spine/extension.h#L65-L67). + +# Putting it all together +Here's a simplified example of how to put all the above together, from loading and instantiating to applying animations (scroll to see all the code): + +``` +// Setup pose data, shared by all skeletons +spAtlas* atlas; +spSkeletonData* skeletonData; +spAnimationStateData* animationStateData; + +// 5 skeleton instances and their animation states +spSkeleton* skeleton[5]; +spAnimationState* animationState[5]; +char* animationNames[] = { "walk", "run", "shot" }; + +void setup() { + // setup your engine so textures can be loaded for atlases, create a window, etc. + engine_setup(); + + // Load the texture atlas + atlas = spAtlas_createFromFile("spineboy.atlas", 0); + if (!atlas) { + printf("Failed to load atlas"); + exit(0); + } + + // Load the skeleton data + spSkeletonJson* json = spSkeletonJson_create(atlas); + skeletonData = spSkeletonJson_readSkeletonDataFile(json, "spineboy.json"); + if (!skeletonData) { + printf("Failed to load skeleton data"); + spAtlas_dispose(atlas); + exit(0); + } + spSkeletonJson_dispose(json); + + // Setup mix times + animationStateData = spAnimationStateData_create(skeletonData); + animationStateData->defaultMix = 0.5f; + spAnimationStateData_setMixByName("walk", "run", 0.2f); + spAnimationStateData_setMixByName("walk", "shot", 0.1f); +} + +void mainLoop() { + // Create 5 skeleton instances and animation states + // representing 5 game objects + for (int i = 0; i < 5; i++) { + // Create the skeleton and put it at a random position + spSkeleton* skeleton = spSkeleton_create(skeletonData); + skeleton->x = random(0, 200); + skeleton->y = random(0, 200); + + // Create the animation state and enqueue a random animation, looping + spAnimationState animationState = spAnimationState_create(animationStateData); + spAnimationState_setAnimation(animationState, 0, animationNames[random(0, 3)], 1); + } + + while (engine_gameIsRunning()) { + engine_clearScreen(); + + // update the game objects + for (int i = 0; i < 5; i++) { + spSkeleton* skeleton = skeletons[i]; + spAnimationState* animationState = animationStates[i]; + + // First update the animation state by the delta time + spAnimationState_update(animationState, engine_getDeltaTime()); + + // Next, apply the state to the skeleton + spAnimationState_apply(animationState, skeleton); + + // Update the skeleton's frame time for physics + spSkeleton_update(engine_getDeltaTime()); + + // Calculate world transforms for rendering + spSkeleton_updateWorldTransform(skeleton, SP_PHYSICS_UPDATE); + + // Hand off rendering the skeleton to the engine + engine_drawSkeleton(skeleton); + } + } + + // Dispose of the instance data. Normally you'd do this when + // a game object is disposed. + for (int i = 0; i < 5) { + spSkeleton_dispose(skeleton); + spAnimationState_dispose(animationState); + } +} + +void dispose() { + // dispose all the shared resources + spAtlas_dispose(atlas); + spSkeletonData_dispose(skeletonData); + spAnimationStateData_dispose(animationStateData); +} + +int main(int argc, char* argv) { + setup(); + mainLoop(); + dispose(); +} +``` + +Note the distinction of setup pose data (`spAtlas`, `spSkeletonData`, `spAnimationStateData`) and instance data (`spSkeleton`, `spAnimationState`) and their different life-times. + +# Integrating spine-c in your engine +## Integrating the sources +spine-c is a set a of C header and implementation files found in the [spine-c/spine-c](/git/spine-runtimes/tree/spine-c/spine-c) folder of the runtime Git repository. You can either copy the sources into your project, or use CMake's `FetchContent` + +### Copy sources +1. Clone the [Spine runtime repository](https://github.com/EsotericSoftware/spine-runtimes). Use the [version branch](/spine-versioning) corresponding with your Spine Editor branch. +2. Copy the sources from the [spine-c/spine-c/src/spine](/git/spine-runtimes/tree/spine-c/spine-c/src/spine) folder to the source folder of your project and make sure they are part of the compilation step of your project. +3. copy the folder `spine` containing the headers from the [spine-c/spine-c/include](/git/spine-runtimes/tree/spine-c/spine-c/include/spine) folder to the header folder of your project and make sure they are part of the include path the compiler uses to look up headers. Make sure to keep the `spine` folder as the spine-c sources include headers via `#include "spine/xxx.h"`. + +### CMake `FetchContent` +Starting with Spine version 4.2, you can also use CMake's `FetchContent` feature to easily integrate the spine-c runtime in your project, as illustrated by this example `CMakeLists.txt` file. + +``` +cmake_minimum_required(VERSION 3.14) +project(MyProject C) + +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(FETCHCONTENT_QUIET NO) + +# Fetch the spine-runtimes repository and make the spine-c library available +include(FetchContent) +FetchContent_Declare( + spine-runtimes + GIT_REPOSITORY https://github.com/esotericsoftware/spine-runtimes.git + GIT_TAG 4.2 + GIT_SHALLOW TRUE +) +FetchContent_MakeAvailable(spine-runtimes) +FetchContent_GetProperties(spine-runtimes) +if(NOT spine-runtimes_POPULATED) + FetchContent_Populate(spine-runtimes) +endif() +add_subdirectory(${spine-runtimes_SOURCE_DIR}/spine-c ${CMAKE_BINARY_DIR}/spine-runtimes) + + +# Create a simple C executable +file(GLOB SOURCES "src/*.c") +add_executable(MyExecutable ${SOURCES}) +target_include_directories(MyExecutable PRIVATE src/) + +# Link the spine-c library +target_link_libraries(MyExecutable spine-c) + +``` + +## Implementing extension functions +If you compile your project you will receive linker errors for the functions the spine-c runtime expects you to implement. E.g. compiling with Clang will yield something like: + +``` +Undefined symbols for architecture x86_64: + "__spAtlasPage_createTexture", referenced from: + _spAtlas_create in libspine-c.a(Atlas.c.o) + "__spAtlasPage_disposeTexture", referenced from: + _spAtlasPage_dispose in libspine-c.a(Atlas.c.o) + "__spUtil_readFile", referenced from: + _spAtlas_createFromFile in libspine-c.a(Atlas.c.o) + _spSkeletonBinary_readSkeletonDataFile in libspine-c.a(SkeletonBinary.c.o) + _spSkeletonJson_readSkeletonDataFile in libspine-c.a(SkeletonJson.c.o) +ld: symbol(s) not found for architecture x86_64 +``` + +The 3 functions the linker can not find are called extension functions. The spine-c runtime expects you to implement these via APIs provided by your engine. The extension functions are defined in [extension.h](/git/spine-runtimes/blob/spine-c/spine-c/include/spine/extension.h#L144-L150). + +> **Note:** if you are using any of the official Spine runtimes that are based on the spine-c runtime, these functions plus rendering are already implemented for you. You can ignore this section. + +### Implementing _spUtil_readFile +spine-c uses the `_spUtil_readFile` function to read the full content [JSON and binary skeleton files (.json/.skel)](/spine-export) exported from the Spine editor, as well as [texture atlas files (.atlas)](/spine-texture-packer#Texture-Packing) into memory. Use the "Find usages" or equivalent function of your C/C++ IDE to see where `_spUtil_readFile` is called. + +The signature of `_spUtil_readFile` is as follows: + +``` +char* _spUtil_readFile (const char* path, int* length); +``` + +The function takes a UTF-8 path to the file it should read, as well as a pointer to an `int` in which the function will store the number of bytes read from the file. The function returns `0` in case the file could not be read or a pointer to a memory block the function allocated and read all bytes of the file into. + +Code that calls `_spUtil_readFile` is supposed to deallocate the returned memory once it is done processing the data. All code in spine-c that uses this function will make sure the memory is deallocated so you do not have to worry about it. + +The memory is supposed to be allocated with the [MALLOC or CALLOC macros](/git/spine-runtimes/blob/spine-c/spine-c/include/spine/extension.h#L65-L66) defined in `extension.h`. The spine-c code will then deallocate the memory using the [FREE](/git/spine-runtimes/blob/spine-c/spine-c/include/spine/extension.h#L85) macro. You can redefine `MALLOC`, `CALLOC` and `FREE` to use a custom memory allocation scheme throughout the spine-c runtime. + +The simplest implementation of `_spUtil_readFile` looks like this: + +``` +char* _spUtil_readFile (const char* path, int* length){ + return _readFile(path, length); +} +``` + +It uses a function called `_readFile` which is provided by spine-c in [extension.c](/git/spine-runtimes/blob/spine-c/spine-c/src/spine/extension.c#L64). `_readFile` uses `fopen` to read the file relative to the current working directory. + +If your engine uses a more sophisticated way of managing files, e.g. by packing them into a single compressed file with an internal file structure, you can implement `_spUtil_readFile` using your engine's file i/o API. + +### Implementing _spAtlasPage_createTexture and _spAtlasPage_disposeTexture +spine-c uses the `_spAtlasPage_createTexture` function to load and create an engine specific texture representation for a single page of a [texture atlas](/spine-texture-packer) exported for a Spine skeleton by the Spine editor. The function is called as part of [spAtlas_create](/git/spine-runtimes/blob/spine-c/spine-c/src/spine/Atlas.c#L167) and [spAtlas_createFromFile](/git/spine-runtimes/blob/spine-c/spine-c/src/spine/Atlas.c#L301), the code responsible for reading a Spine texture atlas file (.atlas) and the corresponding image files (usually .png) making up the pages of the atlas. + +The signature of `_spAtlasPage_createTexture` is as follows: + +``` +void _spAtlasPage_createTexture (spAtlasPage* self, const char* path); +``` + +The function is supposed to load the atlas page image file to an engine specific texture and store it on the `spAtlasPage` passed to the function. The `spAtlasPage` structure has a special field called `rendererObject` of type `void*` in which the engine specific texture should be stored. This engine specific texture stored in `rendererObject` is then later used to render a Spine skeleton using the engine APIs. + +The function is also supposed to set the width and height of the `spAtlasPage` in pixels according to the texture file loaded by the engine. This data is required to compute texture coordinates by spine-c. + +The `path` parameter is the path to the page image file, relative to the `.atlas` file path passed to [spAtlas_createFromFile](/git/spine-runtimes/blob/spine-c/spine-c/src/spine/Atlas.c#L301) or relative to the `dir` parameter passed to [spAtlas_create](/git/spine-runtimes/blob/spine-c/spine-c/src/spine/Atlas.c#L167). These two functions are used to load a texture atlas from a file or a memory block respectively. + +For the purpose of illustration, assume your engine provides the following API to work with textures: + +``` +typedef struct Texture { + // ... OpenGL handle, image data, whatever ... + int width; + int height; +} Texture; + +Texture* engine_loadTexture(const char* file); +void engine_disposeTexture(Texture* texture); +``` + +Implementing `_spAtlasPage_createTexture` is then as simple as: + +``` +void _spAtlasPage_createTexture (AtlasPage* self, const char* path){ + Texture* texture = engine_loadTexture(path); + + // if texture loading failed, self->rendererObject, self->width and + // self->height remain 0 and we simply return. + if (!texture) return; + + // store the Texture on the rendererObject so we can + // retrieve it later for rendering. + self->rendererObject = texture; + + // store the texture width and height on the spAtlasPage + // so spine-c can calculate texture coordinates for + // rendering. + self->width = texture->width; + self->height = texture->height; +} +``` + +The second function that needs to be implemented is `_spAtlasPage_disposeTexture`. It is responsible for disposing the texture of an `spAtlasPage` when the corresponding `spAtlas` is disposed via a call to [spAtlas_dispose](/git/spine-runtimes/blob/spine-c/spine-c/src/spine/Atlas.c#L327). The signature of `_spAtlasPage_disposeTexture` is as follows: + +``` +void _spAtlasPage_disposeTexture (spAtlasPage* self); +``` + +Given our assumed engine API, an implementation would look like this: + +``` +void _spAtlasPage_disposeTexture (spAtlasPage* self) { + // if the rendererObject is not set, loading failed + // so we do not need to dispose of anything. + if (!self->rendererObject) return; + + // Dispose the texture + Texture* texture = (Texture*)self->rendererObject; + engine_disposeTexture(texture); +} +``` + +## Implementing Rendering +Rendering a Spine skeleton means rendering all currently active attachments in the current [draw order](/spine-basic-concepts#Slots). The draw order is defined as an [array of slots](/git/spine-runtimes/blob/spine-c/spine-c/include/spine/Skeleton.h#L54) on the skeleton. + +Drawable attachments ([regions](/spine-regions), [(deformable) meshes](/spine-meshes)) define UV mapped, vertex colored, triangle meshes. The [rendererObject](/git/spine-runtimes/blob/spine-c/spine-c/include/spine/RegionAttachment.h#L52) on a drawable attachment stores a reference to the texture atlas region to which the triangles of the attachment mesh are mapped to. + +Assuming you already have animated your skeleton, either procedurally or via an animation state, and that you have updated the skeleton bones' world transform via a call to `spSkeleton_updateWorldTransform`, you can render a skeleton as follows: + +* For each slot in the draw order array of the skeleton + * Fetch the currently active attachment from the slot (can be null if no attachment is active) + * Fetch the blend mode from the slot and translate it to your engine's API + * Calculate the tint color based on the skeleton's and slot's color + * Check the type of the attachment + * If it is a region attachment + * Compute its world vertices by calling `spRegionAttachment_computeWorldVertices` + * Fetch the atlas page texture from the attachment's render object + * Calculate the tint color of the attachment by multiplying the skeleton, slot, and attachment color, given as RGBA in the range [0-1] per channel + * Combine the world space vertices, UVs and color into a triangle mesh + * Bind the texture through your engine's API + * Submit the mesh for rendering + * If it is a mesh attachment + * Compute its world vertices by calling `spVertexAttachment_computeWorldVertices` + * Fetch the atlas page texture from the attachment's render object + * Calculate the tint color of the attachment by multiplying the skeleton, slot, and attachment color, given as RGBA in the range [0-1] per channel + * Combine the world space vertices, UVs and color into a triangle mesh + * Bind the texture through your engine's API + * Submit the mesh for rendering + +Translating this to your engine should be trivial, provided your engine allows rendering of UV mapped, vertex colored triangle meshes. For illustration purposes, let's assume the following engine API: + +``` +// A single vertex with UV +typedef struct Vertex { + // Position in x/y plane + float x, y; + + // UV coordinates + float u, v; + + // Color, each channel in the range from 0-1 + // (Should really be a 32-bit RGBA packed color) + float r, g, b, a; +} Vertex; + +enum BlendMode { + // See http://esotericsoftware.com/git/spine-runtimes/blob/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BlendMode.java#L37 + // for how these translate to OpenGL source/destination blend modes. + BLEND_NORMAL, + BLEND_ADDITIVE, + BLEND_MULTIPLY, + BLEND_SCREEN, +} + +// Draw the given mesh. +// - vertices is a pointer to an array of Vertex structures +// - start defines from which vertex in the vertices array to start +// - count defines how many vertices to use for rendering (should be divisible by 3, as we render triangles, each triangle requiring 3 vertices) +// - texture the texture to use +// - blendMode the blend mode to use +void engine_drawMesh(Vertex* vertices, int start, int count, Texture* texture, BlendMode blendmode); +``` + +The rendering process can then be implemented like this: + +``` +#define MAX_VERTICES_PER_ATTACHMENT 2048 +float worldVerticesPositions[MAX_VERTICES_PER_ATTACHMENT]; +Vertex vertices[MAX_VERTICES_PER_ATTACHMENT]; + +// Little helper function to add a vertex to the scratch buffer. Index will be increased +// by one after a call to this function. +void addVertex(float x, float y, float u, float v, float r, float g, float b, float a, int* index) { + Vertex* vertex = &vertices[*index]; + vertex->x = x; + vertex->y = y; + vertex->u = u; + vertex->v = v; + vertex->r = r; + vertex->g = g; + vertex->b = b; + vertex->a = a; + *index += 1; +} + +void drawSkeleton(spSkeleton* skeleton) { + // For each slot in the draw order array of the skeleton + for (int i = 0; i < skeleton->slotsCount; ++i) { + spSlot* slot = skeleton->drawOrder[i]; + + // Fetch the currently active attachment, continue + // with the next slot in the draw order if no + // attachment is active on the slot + spAttachment* attachment = slot->attachment; + if (!attachment) continue; + + // Fetch the blend mode from the slot and + // translate it to the engine blend mode + BlendMode engineBlendMode; + switch (slot->data->blendMode) { + case SP_BLEND_MODE_NORMAL: + engineBlendMode = BLEND_NORMAL; + break; + case SP_BLEND_MODE_ADDITIVE: + engineBlendMode = BLEND_ADDITIVE; + break; + case SP_BLEND_MODE_MULTIPLY: + engineBlendMode = BLEND_MULTIPLY; + break; + case SP_BLEND_MODE_SCREEN: + engineBlendMode = BLEND_SCREEN; + break; + default: + // unknown Spine blend mode, fall back to + // normal blend mode + engineBlendMode = BLEND_NORMAL; + } + + // Fill the vertices array depending on the type of attachment + Texture* texture = 0; + int vertexIndex = 0; + if (attachment->type == ATTACHMENT_REGION) { + // Cast to an spRegionAttachment so we can get the rendererObject + // and compute the world vertices + spRegionAttachment* regionAttachment = (spRegionAttachment*)attachment; + + // Calculate the tinting color based on the skeleton's color + // and the slot's color. Each color channel is given in the + // range [0-1], you may have to multiply by 255 and cast to + // and int if your engine uses integer ranges for color channels. + float tintR = skeleton->color.r * slot->color.r * regionAttachment.color.r; + float tintG = skeleton->color.g * slot->color.g * regionAttachment.color.g; + float tintB = skeleton->color.b * slot->color.b * regionAttachment.color.b; + float tintA = skeleton->color.a * slot->color.a * regionAttachment.color.a; + + // Computed the world vertices positions for the 4 vertices that make up + // the rectangular region attachment. This assumes the world transform of the + // bone to which the slot (and hence attachment) is attached has been calculated + // before rendering via spSkeleton_updateWorldTransform + spRegionAttachment_computeWorldVertices(regionAttachment, slot->bone, worldVerticesPositions, 0, 2); + + // Our engine specific Texture is stored in the spAtlasRegion which was + // assigned to the attachment on load. It represents the texture atlas + // page that contains the image the region attachment is mapped to + texture = (Texture*)((spAtlasRegion*)regionAttachment->rendererObject)->page->rendererObject; + + // Create 2 triangles, with 3 vertices each from the region's + // world vertex positions and its UV coordinates (in the range [0-1]). + addVertex(worldVerticesPositions[0], worldVerticesPositions[1], + regionAttachment->uvs[0], regionAttachment->uvs[1], + tintR, tintG, tintB, tintA, &vertexIndex); + + addVertex(worldVerticesPositions[2], worldVerticesPositions[3], + regionAttachment->uvs[2], regionAttachment->uvs[3], + tintR, tintG, tintB, tintA, &vertexIndex); + + addVertex(worldVerticesPositions[4], worldVerticesPositions[5], + regionAttachment->uvs[4], regionAttachment->uvs[5], + tintR, tintG, tintB, tintA, &vertexIndex); + + addVertex(worldVerticesPositions[4], worldVerticesPositions[5], + regionAttachment->uvs[4], regionAttachment->uvs[5], + tintR, tintG, tintB, tintA, &vertexIndex); + + addVertex(worldVerticesPositions[6], worldVerticesPositions[7], + regionAttachment->uvs[6], regionAttachment->uvs[7], + tintR, tintG, tintB, tintA, &vertexIndex); + + addVertex(worldVerticesPositions[0], worldVerticesPositions[1], + regionAttachment->uvs[0], regionAttachment->uvs[1], + tintR, tintG, tintB, tintA, &vertexIndex); + } else if (attachment->type == ATTACHMENT_MESH) { + // Cast to an spMeshAttachment so we can get the rendererObject + // and compute the world vertices + spMeshAttachment* mesh = (spMeshAttachment*)attachment; + + // Calculate the tinting color based on the skeleton's color + // and the slot's color. Each color channel is given in the + // range [0-1], you may have to multiply by 255 and cast to + // and int if your engine uses integer ranges for color channels. + float tintR = skeleton->color.r * slot->color.r * regionAttachment.color.r; + float tintG = skeleton->color.g * slot->color.g * regionAttachment.color.g; + float tintB = skeleton->color.b * slot->color.b * regionAttachment.color.b; + float tintA = skeleton->color.a * slot->color.a * regionAttachment.color.a; + + // Check the number of vertices in the mesh attachment. If it is bigger + // than our scratch buffer, we don't render the mesh. We do this here + // for simplicity, in production you want to reallocate the scratch buffer + // to fit the mesh. + if (mesh->super.worldVerticesLength > MAX_VERTICES_PER_ATTACHMENT) continue; + + // Computed the world vertices positions for the vertices that make up + // the mesh attachment. This assumes the world transform of the + // bone to which the slot (and hence attachment) is attached has been calculated + // before rendering via spSkeleton_updateWorldTransform + spVertexAttachment_computeWorldVertices(SUPER(mesh), slot, 0, mesh->super.worldVerticesLength, worldVerticesPositions, 0, 2); + + // Our engine specific Texture is stored in the spAtlasRegion which was + // assigned to the attachment on load. It represents the texture atlas + // page that contains the image the mesh attachment is mapped to + texture = (Texture*)((spAtlasRegion*)mesh->rendererObject)->page->rendererObject; + + // Mesh attachments use an array of vertices, and an array of indices to define which + // 3 vertices make up each triangle. We loop through all triangle indices + // and simply emit a vertex for each triangle's vertex. + for (int i = 0; i < mesh->trianglesCount; ++i) { + int index = mesh->triangles[i] << 1; + addVertex(worldVerticesPositions[index], worldVerticesPositions[index + 1], + mesh->uvs[index], mesh->uvs[index + 1], + tintR, tintG, tintB, tintA, &vertexIndex); + } + + } + + // Draw the mesh we created for the attachment + engine_drawMesh(vertices, 0, vertexIndex, texture, engineBlendMode); + } +} +``` + +This naive implementation will get you up and running quickly. However, there are a couple of low-hanging fruit in terms of optimization: + +* `engine_drawMesh` is assumed to submit the mesh for rendering immediately. This means we issue one draw call per attachment on the skeleton. A production grade implementation should batch all the meshes into a single mesh. Ideally, if all attachments use the same texture atlas page and blend mode, drawing a skeleton will only incur a single draw call. If all skeletons in a scene share the same texture atlas page and blend mode, you can even batch all skeletons into a single mesh, and hence a single draw call. +* The current setup does not use indexed meshes, but instead submits 3 vertices per triangle. +* The current setup does not support two color tinting. +* The current setup does not support clipping. See the [spine-sfml](https://github.com/EsotericSoftware/spine-runtimes/blob/4.0/spine-sfml/c/src/spine/spine-sfml.cpp#L293) runtime for an example on how to implement clipping. \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Animation.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Animation.h new file mode 100644 index 0000000..7fc48e4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Animation.h @@ -0,0 +1,184 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Animation_h +#define Spine_Animation_h + +#include +#include +#include +#include +#include +#include +#include + +namespace spine { + class Timeline; + class BoneTimeline; + + class Skeleton; + + class Event; + + class AnimationState; + + /// Stores a list of timelines to animate a skeleton's pose over time. + /// + /// See Applying Animations in the Spine + /// Runtimes Guide. + class SP_API Animation : public SpineObject { + friend class AnimationState; + + friend class TrackEntry; + + friend class AnimationStateData; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class RotateTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + friend class TwoColorTimeline; + + friend class Slider; + + public: + /// Creates a new animation. The timelines must be set before use. + Animation(const String &name); + + ~Animation(); + + /// If this list or the timelines it contains are modified, the timelines and bones must be set again to recompute the + /// animation's bone indices and timeline property IDs. + /// + /// See setTimelines(). + Array &getTimelines(); + + /// Sets the timelines and bone indices. + void setTimelines(Array &timelines, Array &bones); + + /// Returns true if this animation contains a timeline with any of the specified property IDs. + bool hasTimeline(Array &ids); + + /// The duration of the animation in seconds, which is usually the highest time of all frames in the timeline. The duration is + /// used to know when it has completed and when it should loop back to the start. + float getDuration(); + + void setDuration(float inValue); + + /// Applies the animation's timelines to the specified skeleton. + /// + /// See Timeline::apply() and + /// Applying Animations in the Spine + /// Runtimes Guide. + /// @param skeleton The skeleton the animation is applied to. This provides access to the bones, slots, and other skeleton + /// components the timelines may change. + /// @param lastTime The last time in seconds this animation was applied. Some timelines trigger only at discrete times, in + /// which case all keys are triggered between lastTime (exclusive) and time (inclusive). Pass -1 the first time an + /// animation is applied to ensure frame 0 is triggered. + /// @param time The time in seconds the skeleton is being posed for. Timelines find the frame before and after this time and + /// interpolate between the frame values. + /// @param loop True if time beyond the animation duration repeats the animation, else the last frame is used. + /// @param events If any events are fired, they are added to this list. Can be NULL to ignore fired events or if no timelines + /// fire events. + /// @param alpha 0 applies setup or current values (depending on from), 1 uses timeline values, and intermediate values + /// interpolate between them. Adjusting alpha over time can mix an animation in or out. + /// @param from If true, alpha transitions between setup and timeline values, setup values are used before the first + /// frame (current values are not used). If false, alpha transitions between current and timeline values, no change + /// is made before the first frame. + /// @param add If true, for timelines that support it, their values are added to the setup or current values (depending on + /// from). + /// @param out True when the animation is mixing out, else it is mixing in. Used by timelines that perform instant + /// transitions. + /// @param appliedPose True to modify getAppliedPose(), else the unconstrained pose is modified. + void apply(Skeleton &skeleton, float lastTime, float time, bool loop, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose); + + /// The animation's name, which is unique across all animations in the skeleton. + const String &getName(); + + /// The Skeleton::getBones() indices affected by this animation. + /// + /// See setTimelines() and BoneTimeline::getBoneIndex(). + const Array &getBones(); + + /// The color of the animation as it was in Spine, or a default color if nonessential data was not exported. + Color &getColor(); + + /// @param target After the first and before the last entry. + static int search(Array &values, float target); + + static int search(Array &values, float target, int step); + + protected: + Array _timelines; + Map _timelineIds; + Array _bones; + float _duration; + String _name; + Color _color; + }; +} + +#endif /* Spine_Animation_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AnimationState.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AnimationState.h new file mode 100644 index 0000000..9e26355 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AnimationState.h @@ -0,0 +1,619 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AnimationState_h +#define Spine_AnimationState_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Slot.h" + +#ifdef SPINE_USE_STD_FUNCTION +#include +#endif + +namespace spine { + enum EventType { + EventType_Start = 0, + EventType_Interrupt, + EventType_End, + EventType_Dispose, + EventType_Complete, + EventType_Event + }; + + class AnimationState; + + class TrackEntry; + + class Animation; + + class Event; + + class AnimationStateData; + + class Skeleton; + + class RotateTimeline; + + class AttachmentTimeline; + +#ifdef SPINE_USE_STD_FUNCTION + typedef std::function AnimationStateListener; +#else + + typedef void (*AnimationStateListener)(AnimationState *state, EventType type, TrackEntry *entry, Event *event, void *userData); + +#endif + + /// Abstract class to inherit from to create a callback object + class SP_API AnimationStateListenerObject { + public: + AnimationStateListenerObject() {}; + + virtual ~AnimationStateListenerObject() {}; + + public: + /// The callback function to be called + virtual void callback(AnimationState *state, EventType type, TrackEntry *entry, Event *event) = 0; + }; + + /// State for the playback of an animation + class SP_API TrackEntry : public SpineObject, public HasRendererObject { + friend class EventQueue; + + friend class AnimationState; + + public: + TrackEntry(); + + virtual ~TrackEntry(); + + /// The index of the track where this entry is either current or queued. + int getTrackIndex(); + + /// The animation to apply for this track entry. + Animation &getAnimation(); + + /// Sets the animation for this track entry. + void setAnimation(Animation &animation); + + TrackEntry *getPrevious(); + + /// If true, the animation will repeat. If false, it will not, instead its last frame is applied if played beyond its duration. + bool getLoop(); + + void setLoop(bool inValue); + + /// When true, timelines in this animation that support additive have their values added to the setup or current pose values + /// instead of replacing them. Additive can be set for a new track entry only before AnimationState::apply() is next called. + bool getAdditive(); + + void setAdditive(bool inValue); + + bool getReverse(); + + void setReverse(bool inValue); + + bool getShortestRotation(); + + void setShortestRotation(bool inValue); + + /// Seconds to postpone playing the animation. Must be >= 0. When this track entry is the current track entry, + /// delay postpones incrementing the track time. When this track entry is queued, delay is the time from the start of the + /// previous animation to when this track entry will become the current track entry (ie when the previous track entry's track + /// time >= this track entry's delay). + /// + /// Time scale affects the delay. + /// + /// When passing delay <= 0 to AnimationState::addAnimation(int, Animation, bool, float), this delay is set using a mix + /// duration from AnimationStateData. To change the mix duration afterward, use setMixDuration(float, float) so this delay is + /// adjusted. + float getDelay(); + + void setDelay(float inValue); + + /// The time in seconds this track entry has been the current track entry, starting at 0 and increasing forever. + /// Compare to getAnimationTime(), which is always between animationStart and animationEnd. + /// + /// The track time can be set to start the animation at a time other than 0, without affecting looping. When doing so, + /// animationLast can be set to the same value to avoid firing events from the start of the animation. + float getTrackTime(); + + void setTrackTime(float inValue); + + /// The track time in seconds when this animation will be removed from the track. Defaults to the highest possible float + /// value, meaning the animation will be applied until a new animation is set or the track is cleared. If the track end time + /// is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the + /// properties keyed by the animation are set to the setup pose and the track is cleared. + /// + /// It may be desired to use AnimationState::addEmptyAnimation(int, float, float) rather than have the animation + /// abruptly cease being applied, leaving the current pose. + float getTrackEnd(); + + void setTrackEnd(float inValue); + + /// The time in seconds for the first frame of this animation, both initially and after looping. Defaults to 0. + /// + /// When setting the animation start time, animationLast can be set to the same value to avoid firing events from the + /// start of the animation. + float getAnimationStart(); + + void setAnimationStart(float inValue); + + /// The time in seconds for the last frame of this animation. Past this time, non-looping animations hold the pose at this + /// time while looping animations will loop back to animationStart. Defaults to the animation duration. + float getAnimationEnd(); + + void setAnimationEnd(float inValue); + + /// The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this + /// animation is applied, event timelines will fire all events between the animation last time (exclusive) and animation time + /// (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation is applied. + float getAnimationLast(); + + void setAnimationLast(float inValue); + + /// Uses the track time to compute animationTime, which is always between animationStart and animationEnd. When trackTime is + /// 0, animationTime is equal to animationStart. + float getAnimationTime(); + + /// Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or + /// faster. Defaults to 1. + /// + /// Values < 0 are not supported. To play an animation in reverse, use reverse. + /// + /// mixTime is not affected by track entry time scale, so mixDuration may need to be adjusted to match the animation speed. + /// + /// When using AnimationState::addAnimation(int, Animation, bool, float) with a delay <= 0, delay is set using the mix + /// duration from AnimationStateData, assuming time scale to be 1. If the time scale is not 1, the delay may need to be + /// adjusted. + /// + /// See AnimationState::getTimeScale() for affecting all animations. + float getTimeScale(); + + void setTimeScale(float inValue); + + /// Values less than 1 mix this animation with the last skeleton pose. Defaults to 1, which overwrites the last skeleton pose with + /// this animation. + /// + /// Typically track 0 is used to completely pose the skeleton, then alpha can be used on higher tracks. It doesn't make sense + /// to use alpha on track 0 if the skeleton pose is from the last frame render. + float getAlpha(); + + void setAlpha(float inValue); + + /// + /// When the interpolated mix percentage is less than the event threshold, event timelines for the animation being mixed out + /// will be applied. Defaults to 0, so event timelines are not applied for an animation being mixed out. + float getEventThreshold(); + + void setEventThreshold(float inValue); + + /// When the interpolated mix percentage is less than the attachment threshold, attachment timelines for the animation being + /// mixed out will be applied. Defaults to 0, so attachment timelines are not applied for an animation being mixed out. + float getMixAttachmentThreshold(); + + void setMixAttachmentThreshold(float inValue); + + /// When the computed alpha is greater than alphaAttachmentThreshold, attachment timelines are applied. The computed alpha + /// includes alpha and the interpolated mix percentage. Defaults to 0, so attachment timelines are always applied. + float getAlphaAttachmentThreshold(); + + void setAlphaAttachmentThreshold(float inValue); + + /// When the interpolated mix percentage is less than the draw order threshold, draw order timelines for the animation being + /// mixed out will be applied. Defaults to 0, so draw order timelines are not applied for an animation being mixed out. + float getMixDrawOrderThreshold(); + + void setMixDrawOrderThreshold(float inValue); + + /// The animation queued to start after this animation, or NULL. + TrackEntry *getNext(); + + /// Returns true if at least one loop has been completed. + bool isComplete(); + + /// Seconds from 0 to the mix duration when mixing from the previous animation to this animation. May be slightly more than + /// mixDuration when the mix is complete. + float getMixTime(); + + void setMixTime(float inValue); + + /// Seconds for mixing from the previous animation to this animation. Defaults to the value provided by + /// AnimationStateData based on the animation before this animation (if any). + /// + /// The mix duration can be set manually rather than use the value from AnimationStateData.GetMix. + /// In that case, the mixDuration must be set before AnimationState.update(float) is next called. + /// + /// When using AnimationState::addAnimation(int, Animation, bool, float) with a delay + /// less than or equal to 0, note the Delay is set using the mix duration from the AnimationStateData + float getMixDuration(); + + void setMixDuration(float inValue); + + /// Sets both mixDuration and delay. + /// @param delay If > 0, sets delay. If <= 0, the delay set is the duration of the previous track + /// entry minus the specified mix duration plus the specified delay (ie the mix ends at + /// (delay = 0) or before (delay < 0) the previous track entry duration). If the previous + /// entry is looping, its next loop completion is used instead of its duration. + void setMixDuration(float mixDuration, float delay); + + /// The interpolation to apply to the mix percentage (mix time / mix duration) when mixing from the previous animation to + /// this animation. Defaults to linear. + Interpolation &getMixInterpolation(); + + void setMixInterpolation(Interpolation &mixInterpolation); + + /// The track entry for the previous animation when mixing to this animation, or NULL if no mixing is currently occurring. + /// When mixing from multiple animations, MixingFrom makes up a doubly linked list with MixingTo. + TrackEntry *getMixingFrom(); + + /// The track entry for the next animation when mixing from this animation, or NULL if no mixing is currently occurring. + /// When mixing to multiple animations, MixingTo makes up a doubly linked list with MixingFrom. + TrackEntry *getMixingTo(); + + /// Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the + /// long way around when using alpha and starting animations on other tracks. + /// + /// Mixing involves finding a rotation between two others, which has two possible solutions: the short way or the long way around. + /// The two rotations likely change over time, so which direction is the short or long way also changes. + /// If the short way was always chosen, bones would flip to the other side when that direction became the long way. + /// TrackEntry chooses the short way the first time it is applied and remembers that direction. + void resetRotationDirections(); + + float getTrackComplete(); + +#ifdef SPINE_USE_STD_FUNCTION + void setListener(AnimationStateListener listener); +#else + void setListener(AnimationStateListener listener, void *userData = NULL); +#endif + + void setListener(AnimationStateListenerObject *listener); + + /// Returns true if this entry is for the empty animation. + bool isEmptyAnimation(); + + /// Returns true if this track entry has been applied at least once. + /// + /// See AnimationState::apply(Skeleton). + bool wasApplied(); + + /// Returns true if there is a next track entry that is ready to become the current track entry during the + /// next AnimationState::update(float)} + bool isNextReady() { + return _next != NULL && _nextTrackLast - _next->_delay >= 0; + } + + // The AnimationState this track entry belongs to. May be NULL if TrackEntry is directly instantiated. + AnimationState *getAnimationState() { + return _state; + } + + void setAnimationState(AnimationState *state) { + _state = state; + } + + private: + Animation *_animation; + TrackEntry *_previous; + TrackEntry *_next; + TrackEntry *_mixingFrom; + TrackEntry *_mixingTo; + int _trackIndex; + + bool _loop, _additive, _reverse, _shortestRotation, _keepHold; + float _eventThreshold, _mixAttachmentThreshold, _alphaAttachmentThreshold, _mixDrawOrderThreshold; + float _animationStart, _animationEnd, _animationLast, _nextAnimationLast; + float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale; + float _alpha, _mixTime, _mixDuration, _totalAlpha; + Interpolation *_mixInterpolation; + Array _timelineMode; + Array _timelineHoldMix; + Array _timelinesRotation; + AnimationStateListener _listener; +#ifndef SPINE_USE_STD_FUNCTION + void *_listenerUserData; +#endif + AnimationStateListenerObject *_listenerObject; + AnimationState *_state; + + float mix(); + + void reset(); + }; + + class SP_API EventQueueEntry : public SpineObject { + friend class EventQueue; + + public: + EventType _type; + TrackEntry *_entry; + Event *_event; + + EventQueueEntry(EventType eventType, TrackEntry *trackEntry, Event *event = NULL); + }; + + class SP_API EventQueue : public SpineObject { + friend class AnimationState; + + private: + Array _eventQueueEntries; + AnimationState &_state; + bool _drainDisabled; + + static EventQueue *newEventQueue(AnimationState &state); + + static EventQueueEntry newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event = NULL); + + EventQueue(AnimationState &state); + + ~EventQueue(); + + void start(TrackEntry *entry); + + void interrupt(TrackEntry *entry); + + void end(TrackEntry *entry); + + void dispose(TrackEntry *entry); + + void complete(TrackEntry *entry); + + void event(TrackEntry *entry, Event *event); + + /// Raises all events in the queue and drains the queue. + void drain(); + }; + + /// Applies animations over time, queues animations for later playback, mixes (crossfading) between animations, and applies + /// multiple animations on top of each other (layering). + /// + /// See Applying Animations in the + /// Spine Runtimes Guide. + class SP_API AnimationState : public SpineObject, public HasRendererObject { + friend class TrackEntry; + + friend class EventQueue; + + public: + explicit AnimationState(AnimationStateData &data); + + ~AnimationState(); + + /// Increments each track entry's track time, setting queued animations as current if needed. + void update(float delta); + + /// Poses the skeleton using the track entry animations. The animation state is not changed, so can be applied to multiple + /// skeletons to pose them identically. + /// @return True if any animations were applied. + bool apply(Skeleton &skeleton); + + /// Removes all animations from all tracks, leaving skeletons in their current pose. + /// + /// It may be desired to use AnimationState::setEmptyAnimations(float) to mix the skeletons back to the setup pose, + /// rather than leaving them in their current pose. + void clearTracks(); + + /// Removes all animations from the track, leaving skeletons in their current pose. + /// + /// It may be desired to use AnimationState::setEmptyAnimation(int, float) to mix the skeletons back to the setup pose, + /// rather than leaving them in their current pose. + void clearTrack(size_t trackIndex); + + /// Sets an animation by name. + /// + /// See setAnimation(int, Animation, bool). + TrackEntry &setAnimation(size_t trackIndex, const String &animationName, bool loop); + + /// Sets the current animation for a track, discarding any queued animations. + /// + /// If the formerly current track entry is for the same animation and was never applied to a skeleton, it is replaced (not mixed + /// from). + /// @param loop If true, the animation will repeat. + /// If false, it will not, instead its last frame is applied if played beyond its duration. + /// In either case TrackEntry.TrackEnd determines when the track is cleared. + /// @return + /// A track entry to allow further customization of animation playback. References to the track entry must not be kept + /// after AnimationState.Dispose. + TrackEntry &setAnimation(size_t trackIndex, Animation &animation, bool loop); + + /// Queues an animation by name. + /// + /// See addAnimation(int, Animation, bool, float). + TrackEntry &addAnimation(size_t trackIndex, const String &animationName, bool loop, float delay); + + /// Adds an animation to be played delay seconds after the current or last queued animation + /// for a track. If the track has no entries, this is equivalent to calling setAnimation. + /// @param delay + /// Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation + /// duration of the previous track minus any mix duration plus the negative delay. + /// + /// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + /// after AnimationState.Dispose + TrackEntry &addAnimation(size_t trackIndex, Animation &animation, bool loop, float delay); + + /// Sets an empty animation for a track, discarding any queued animations, and sets the track entry's + /// TrackEntry::getMixDuration(). An empty animation has no timelines and serves as a placeholder for mixing in or out. + /// + /// Mixing out is done by setting an empty animation with a mix duration using either setEmptyAnimation(int, float), + /// setEmptyAnimations(float), or addEmptyAnimation(int, float, float). Mixing to an empty animation causes + /// the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation + /// transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of + /// 0 still mixes out over one frame. + /// + /// Mixing in is done by first setting an empty animation, then adding an animation using + /// addAnimation(int, Animation, bool, float) with the desired delay (an empty animation has a duration of 0) and on + /// the returned track entry set TrackEntry::setMixDuration(float). Mixing from an empty animation causes the new + /// animation to be applied more and more over the mix duration. Properties keyed in the new animation transition from the value + /// from lower tracks or from the setup pose value if no lower tracks key the property to the value keyed in the new animation. + /// + /// See Empty animations in the Spine + /// Runtimes Guide. + TrackEntry &setEmptyAnimation(size_t trackIndex, float mixDuration); + + /// Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's + /// TrackEntry::getMixDuration(). If the track has no entries, it is equivalent to calling + /// setEmptyAnimation(int, float). + /// + /// See setEmptyAnimation(int, float) and + /// Empty animations in the Spine + /// Runtimes Guide. + /// @param delay If > 0, sets TrackEntry::getDelay(). If <= 0, the delay set is the duration of the previous track entry + /// minus any mix duration plus the specified delay (ie the mix ends at (delay = 0) or before + /// (delay < 0) the previous track entry duration). If the previous entry is looping, its next loop completion + /// is used instead of its duration. + /// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + /// after the AnimationStateListener::dispose(TrackEntry) event occurs. + TrackEntry &addEmptyAnimation(size_t trackIndex, float mixDuration, float delay); + + /// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration. + /// + /// See Empty animations in the Spine + /// Runtimes Guide. + void setEmptyAnimations(float mixDuration); + + /// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing. + TrackEntry *getTrack(size_t trackIndex); + + /// The AnimationStateData to look up mix durations. + AnimationStateData &getData(); + + /// The list of tracks that have had animations, which may contain null entries for tracks that currently have no animation. + Array &getTracks(); + + /// Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower + /// or faster. Defaults to 1. + /// + /// See TrackEntry::getTimeScale() for affecting a single animation. + float getTimeScale(); + + void setTimeScale(float inValue); + + /// Adds a listener to receive events for all track entries. +#ifdef SPINE_USE_STD_FUNCTION + void setListener(AnimationStateListener listener); +#else + void setListener(AnimationStateListener listener, void *userData = NULL); +#endif + + /// Adds a listener to receive events for all track entries. + void setListener(AnimationStateListenerObject *listener); + + void disableQueue(); + + void enableQueue(); + + void setManualTrackEntryDisposal(bool inValue); + + bool getManualTrackEntryDisposal(); + + void disposeTrackEntry(TrackEntry *entry); + + private: + static const int Current = 0; + static const int Setup = 1; + static const int First = 2; + static const int Mode = 3; + static const int Hold = 4; + + static const int AttachSetup = 1; + static const int AttachRetain = 2; + + AnimationStateData *_data; + + Pool _trackEntryPool; + Array _tracks; + Array _events; + EventQueue *_queue; + + Map _propertyIDs; + bool _animationsChanged; + + AnimationStateListener _listener; +#ifndef SPINE_USE_STD_FUNCTION + void *_listenerUserData; +#endif + AnimationStateListenerObject *_listenerObject; + + int _unkeyedState; + + float _timeScale; + + bool _manualTrackEntryDisposal; + + static Animation *getEmptyAnimation(); + + /// Applies the rotate timeline, mixing with the current pose while keeping the same rotation direction chosen as the shortest + /// the first time the mixing was applied. + static void applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, MixFrom from, + Array &timelinesRotation, size_t i, bool firstFrame); + + /// Applies the attachment timeline and sets Slot::attachmentState. + /// @param retain True if the attachment remains after apply, false if temporary for deform timelines. + void applyAttachmentTimeline(AttachmentTimeline *attachmentTimeline, Skeleton &skeleton, float animationTime, MixFrom from, bool retain); + + /// Returns true when all mixing from entries are complete. + bool updateMixingFrom(TrackEntry *to, float delta); + + float applyMixingFrom(TrackEntry *to, Skeleton &skeleton); + + void queueEvents(TrackEntry *entry, float animationTime); + + void eventsReverse(TrackEntry *entry, float animationLast, float animationTime); + + /// Sets the active TrackEntry for a given track number. + void setTrack(size_t index, TrackEntry *current, bool interrupt); + + /// Removes the specified entry's next track entry and all entries after it. + void clearNext(TrackEntry *entry); + + TrackEntry *expandToIndex(size_t index); + + /// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values. + /// @param last May be NULL. + TrackEntry *newTrackEntry(size_t trackIndex, Animation *animation, bool loop, TrackEntry *last); + + void animationsChanged(); + + void computeHold(TrackEntry *entry, TrackEntry *track); + + int from(TrackEntry *track, Timeline *timeline, Array &ids); + }; +} + +#endif /* Spine_AnimationState_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AnimationStateData.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AnimationStateData.h new file mode 100644 index 0000000..8152489 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AnimationStateData.h @@ -0,0 +1,95 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AnimationStateData_h +#define Spine_AnimationStateData_h + +#include +#include +#include + +#include + +namespace spine { + class SkeletonData; + + class Animation; + + /// Stores mix (crossfade) durations to be applied when AnimationState animations are changed on the same track. + class SP_API AnimationStateData : public SpineObject { + friend class AnimationState; + + public: + explicit AnimationStateData(SkeletonData &skeletonData); + + /// The SkeletonData to look up animations when they are specified by name. + SkeletonData &getSkeletonData(); + + /// The mix duration to use when no mix duration has been specifically defined between two animations. + float getDefaultMix(); + + void setDefaultMix(float inValue); + + /// Sets a mix duration by animation names. + void setMix(const String &fromName, const String &toName, float duration); + + /// Sets a mix duration when changing from the specified animation to the other. + /// See TrackEntry.MixDuration. + void setMix(Animation &from, Animation &to, float duration); + + /// Returns the mix duration to use when changing from the specified animation to the other on the same track, + /// or the default mix if no mix duration has been set. + float getMix(Animation &from, Animation &to); + + /// Removes all mixes and sets the default mix to 0. + void clear(); + + private: + class AnimationPair : public SpineObject { + public: + Animation *_a1; + Animation *_a2; + + explicit AnimationPair(Animation *a1 = NULL, Animation *a2 = NULL); + + bool operator==(const AnimationPair &other) const; + }; + + class AnimationPairHash { + public: + size_t operator()(const AnimationPair &pair) const; + }; + + SkeletonData *_skeletonData; + float _defaultMix; + Map _animationToMixTime; + }; +} + +#endif /* Spine_AnimationStateData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Array.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Array.h new file mode 100644 index 0000000..4f01d34 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Array.h @@ -0,0 +1,249 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Array_h +#define Spine_Array_h + +#include +#include +#include +#include + +namespace spine { + template + class SP_API Array : public SpineObject { + public: + using size_type = size_t; + using value_type = T; + + Array() : _size(0), _capacity(0), _buffer(NULL) { + } + + Array(size_t capacity) : _size(0), _capacity(0), _buffer(NULL) { + ensureCapacity(capacity); + } + + Array(const Array &inArray) : _size(inArray._size), _capacity(inArray._capacity), _buffer(NULL) { + if (_capacity > 0) { + _buffer = allocate(_capacity); + for (size_t i = 0; i < _size; ++i) { + construct(_buffer + i, inArray._buffer[i]); + } + } + } + + ~Array() { + clear(); + deallocate(_buffer); + } + + inline void clear() { + for (size_t i = 0; i < _size; ++i) { + destroy(_buffer + (_size - 1 - i)); + } + + _size = 0; + } + + inline size_t getCapacity() const { + return _capacity; + } + + inline size_t size() const { + return _size; + } + + inline Array &setSize(size_t newSize, const T &defaultValue) { + size_t oldSize = _size; + _size = newSize; + if (_capacity < newSize) { + if (_capacity == 0) { + _capacity = _size; + } else { + _capacity = (int) (_size * 1.75f); + } + if (_capacity < 8) _capacity = 8; + _buffer = SpineExtension::realloc(_buffer, _capacity, __FILE__, __LINE__); + } + if (oldSize < _size) { + for (size_t i = oldSize; i < _size; i++) { + construct(_buffer + i, defaultValue); + } + } else { + for (size_t i = _size; i < oldSize; i++) { + destroy(_buffer + i); + } + } + return *this; + } + + inline void ensureCapacity(size_t newCapacity = 0) { + if (_capacity >= newCapacity) return; + _capacity = newCapacity; + _buffer = SpineExtension::realloc(_buffer, newCapacity, __FILE__, __LINE__); + } + + inline void add(const T &inValue) { + if (_size == _capacity) { + // inValue might reference an element in this buffer + // When we reallocate, the reference becomes invalid. + // We thus need to create a defensive copy before + // reallocating. + T valueCopy = inValue; + _capacity = (int) (_size * 1.75f); + if (_capacity < 8) _capacity = 8; + _buffer = SpineExtension::realloc(_buffer, _capacity, __FILE__, __LINE__); + construct(_buffer + _size++, valueCopy); + } else { + construct(_buffer + _size++, inValue); + } + } + + inline void addAll(const Array &inValue) { + ensureCapacity(this->size() + inValue.size()); + for (size_t i = 0; i < inValue.size(); i++) { + add(inValue[i]); + } + } + + inline void clearAndAddAll(const Array &inValue) { + ensureCapacity(inValue.size()); + for (size_t i = 0; i < inValue.size(); i++) _buffer[i] = inValue[i]; + _size = inValue.size(); + } + + inline void removeAt(size_t inIndex) { + assert(inIndex < _size); + + --_size; + + if (inIndex != _size) { + for (size_t i = inIndex; i < _size; ++i) { + T tmp(_buffer[i]); + _buffer[i] = _buffer[i + 1]; + _buffer[i + 1] = tmp; + } + } + + destroy(_buffer + _size); + } + + inline bool contains(const T &inValue) { + for (size_t i = 0; i < _size; ++i) { + if (_buffer[i] == inValue) { + return true; + } + } + + return false; + } + + inline int indexOf(const T &inValue) { + for (size_t i = 0; i < _size; ++i) { + if (_buffer[i] == inValue) { + return (int) i; + } + } + + return -1; + } + + inline T &operator[](size_t inIndex) { + assert(inIndex < _size); + + return _buffer[inIndex]; + } + + inline const T &operator[](size_t inIndex) const { + assert(inIndex < _size); + + return _buffer[inIndex]; + } + + inline friend bool operator==(Array &lhs, Array &rhs) { + if (lhs.size() != rhs.size()) { + return false; + } + + for (size_t i = 0, n = lhs.size(); i < n; ++i) { + if (lhs[i] != rhs[i]) { + return false; + } + } + + return true; + } + + inline friend bool operator!=(Array &lhs, Array &rhs) { + return !(lhs == rhs); + } + + Array &operator=(const Array &inArray) { + if (this != &inArray) { + clearAndAddAll(inArray); + } + return *this; + } + + inline T *buffer() { + return _buffer; + } + + private: + size_t _size; + size_t _capacity; + T *_buffer; + + inline T *allocate(size_t n) { + assert(n > 0); + + T *ptr = SpineExtension::calloc(n, __FILE__, __LINE__); + + assert(ptr); + + return ptr; + } + + inline void deallocate(T *buffer) { + if (_buffer) { + SpineExtension::free(buffer, __FILE__, __LINE__); + } + } + + inline void construct(T *buffer, const T &val) { + new (buffer) T(val); + } + + inline void destroy(T *buffer) { + buffer->~T(); + } + }; +} + +#endif /* Spine_Array_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ArrayUtils.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ArrayUtils.h new file mode 100644 index 0000000..62c66ee --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ArrayUtils.h @@ -0,0 +1,128 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ContainerUtil_h +#define Spine_ContainerUtil_h + +#include +#include +#include +#include + +#include + +namespace spine { + class SP_API ArrayUtils : public SpineObject { + public: + /// Finds an item by comparing each item's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + template + static T *findWithName(Array &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0; i < items.size(); ++i) { + T *item = items[i]; + if (item->getName() == name) { + return item; + } + } + + return NULL; + } + + /// @return -1 if the item was not found. + template + static int findIndexWithName(Array &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0, len = items.size(); i < len; ++i) { + T *item = items[i]; + if (item->getName() == name) { + return static_cast(i); + } + } + + return -1; + } + + /// Finds an item by comparing each item's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + template + static T *findWithDataName(Array &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0; i < items.size(); ++i) { + T *item = items[i]; + if (item->getData().getName() == name) { + return item; + } + } + + return NULL; + } + + /// @return -1 if the item was not found. + template + static int findIndexWithDataName(Array &items, const String &name) { + assert(name.length() > 0); + + for (size_t i = 0, len = items.size(); i < len; ++i) { + T *item = items[i]; + if (item->getData().getName() == name) { + return static_cast(i); + } + } + + return -1; + } + + template + static void deleteElements(Array &items) { + for (int i = (int) items.size() - 1; i >= 0; i--) { + T *item = items[i]; + + delete item; + + items.removeAt(i); + } + } + + private: + // ctor, copy ctor, and assignment should be private in a Singleton + ArrayUtils(); + + ArrayUtils(const ArrayUtils &); + + ArrayUtils &operator=(const ArrayUtils &); + }; +} + +#endif /* Spine_ContainerUtil_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Atlas.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Atlas.h new file mode 100644 index 0000000..a359b7b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Atlas.h @@ -0,0 +1,273 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Atlas_h +#define Spine_Atlas_h + +#include +#include +#include +#include +#include +#include "TextureRegion.h" +#include "spine/MeshAttachment.h" +#include "spine/RegionAttachment.h" + +namespace spine { + enum Format { + Format_Alpha, + Format_Intensity, + Format_LuminanceAlpha, + Format_RGB565, + Format_RGBA4444, + Format_RGB888, + Format_RGBA8888 + }; + + // Our TextureFilter collides with UE4's TextureFilter in unity builds. We rename + // TextureFilter to SpineTextureFilter in UE4. +#ifdef SPINE_UE4 + enum SpineTextureFilter { + TextureFilter_Unknown, + TextureFilter_Nearest, + TextureFilter_Linear, + TextureFilter_MipMap, + TextureFilter_MipMapNearestNearest, + TextureFilter_MipMapLinearNearest, + TextureFilter_MipMapNearestLinear, + TextureFilter_MipMapLinearLinear + }; +#else + enum TextureFilter { + TextureFilter_Unknown, + TextureFilter_Nearest, + TextureFilter_Linear, + TextureFilter_MipMap, + TextureFilter_MipMapNearestNearest, + TextureFilter_MipMapLinearNearest, + TextureFilter_MipMapNearestLinear, + TextureFilter_MipMapLinearLinear + }; +#endif + + enum TextureWrap { + TextureWrap_MirroredRepeat, + TextureWrap_ClampToEdge, + TextureWrap_Repeat + }; + + class SP_API AtlasPage : public SpineObject { + public: + String name; + String texturePath; + Format format; +#ifdef SPINE_UE4 + SpineTextureFilter minFilter; + SpineTextureFilter magFilter; +#else + TextureFilter minFilter; + TextureFilter magFilter; +#endif + TextureWrap uWrap; + TextureWrap vWrap; + int width, height; + bool pma; + int index; + void *texture; + + explicit AtlasPage(const String &inName) + : name(inName), format(Format_RGBA8888), minFilter(TextureFilter_Nearest), magFilter(TextureFilter_Nearest), + uWrap(TextureWrap_ClampToEdge), vWrap(TextureWrap_ClampToEdge), width(0), height(0), pma(false), index(0), texture(nullptr) { + } + }; + + class SP_API AtlasRegion : public TextureRegion { + friend class Atlas; + friend class RegionAttachment; + friend class MeshAttachment; + + RTTI_DECL + + public: + AtlasRegion() + : TextureRegion(), _page(nullptr), _name(""), _index(0), _x(0), _y(0), _offsetX(0), _offsetY(0), _packedWidth(0), _packedHeight(0), + _originalWidth(0), _originalHeight(0), _rotate(false), _degrees(0) { + } + ~AtlasRegion() { + } + AtlasPage *getPage() const { + return _page; + } + const String &getName() const { + return _name; + } + int getIndex() const { + return _index; + } + int getX() const { + return _x; + } + int getY() const { + return _y; + } + float getOffsetX() const { + return _offsetX; + } + float getOffsetY() const { + return _offsetY; + } + int getPackedWidth() const { + return _packedWidth; + } + int getPackedHeight() const { + return _packedHeight; + } + int getOriginalWidth() const { + return _originalWidth; + } + int getOriginalHeight() const { + return _originalHeight; + } + bool getRotate() const { + return _rotate; + } + int getDegrees() const { + return _degrees; + } + Array &getSplits() { + return _splits; + } + Array &getPads() { + return _pads; + } + Array &getNames() { + return _names; + } + Array &getValues() { + return _values; + } + void setPage(AtlasPage *value) { + _page = value; + } + void setName(const String &value) { + _name = value; + } + void setIndex(int value) { + _index = value; + } + void setX(int value) { + _x = value; + } + void setY(int value) { + _y = value; + } + void setOffsetX(float value) { + _offsetX = value; + } + void setOffsetY(float value) { + _offsetY = value; + } + void setPackedWidth(int value) { + _packedWidth = value; + } + void setPackedHeight(int value) { + _packedHeight = value; + } + void setOriginalWidth(int value) { + _originalWidth = value; + } + void setOriginalHeight(int value) { + _originalHeight = value; + } + void setRotate(bool value) { + _rotate = value; + } + void setDegrees(int value) { + _degrees = value; + } + void setSplits(const Array &value) { + _splits = value; + } + void setPads(const Array &value) { + _pads = value; + } + void setNames(const Array &value) { + _names = value; + } + void setValues(const Array &value) { + _values = value; + } + + private: + AtlasPage *_page; + String _name; + int _index; + int _x, _y; + float _offsetX, _offsetY; + int _packedWidth, _packedHeight; + int _originalWidth, _originalHeight; + bool _rotate; + int _degrees; + Array _splits; + Array _pads; + Array _names; + Array _values; + }; + + class TextureLoader; + + class SP_API Atlas : public SpineObject { + public: + Atlas(const String &path, TextureLoader *textureLoader, bool createTexture = true); + + Atlas(const char *data, int length, const char *dir, TextureLoader *textureLoader, bool createTexture = true); + + ~Atlas(); + + void flipV(); + + /// Returns the first region found with the specified name. This method uses String comparison to find the region, so the result + /// should be cached rather than calling this method multiple times. + /// @return The region, or nullptr. + AtlasRegion *findRegion(const String &name); + + Array &getPages(); + + Array &getRegions(); + + private: + Array _pages; + Array _regions; + TextureLoader *_textureLoader; + + void load(const char *begin, int length, const char *dir, bool createTexture); + }; +}// namespace spine + +#endif /* Spine_Atlas_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AtlasAttachmentLoader.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AtlasAttachmentLoader.h new file mode 100644 index 0000000..7646a21 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AtlasAttachmentLoader_h +#define Spine_AtlasAttachmentLoader_h + +#include +#include +#include + + +namespace spine { + class Atlas; + + class AtlasRegion; + + /// An AttachmentLoader that configures attachments using texture regions from an Atlas. + /// + /// See https://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data Loading skeleton data in the + /// Spine Runtimes Guide. + class SP_API AtlasAttachmentLoader : public AttachmentLoader { + public: + explicit AtlasAttachmentLoader(Atlas &atlas); + + virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &placeholder, const String &name, const String &path, + Sequence *sequence); + + virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &placeholder, const String &name, const String &path, Sequence *sequence); + + virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &skin, const String &placeholder, const String &name); + + virtual PathAttachment *newPathAttachment(Skin &skin, const String &placeholder, const String &name); + + virtual PointAttachment *newPointAttachment(Skin &skin, const String &placeholder, const String &name); + + virtual ClippingAttachment *newClippingAttachment(Skin &skin, const String &placeholder, const String &name); + + AtlasRegion *findRegion(const String &name); + + private: + Atlas *_atlas; + }; +} + +#endif /* Spine_AtlasAttachmentLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Attachment.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Attachment.h new file mode 100644 index 0000000..878bc01 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Attachment.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Attachment_h +#define Spine_Attachment_h + +#include +#include +#include +#include + +namespace spine { + class Slot; + + /// The base class for all attachments. Multiple Skeleton instances, slots, or skins can use the same attachments. + class SP_API Attachment : public SpineObject { + RTTI_DECL_NOPARENT + + public: + explicit Attachment(const String &name); + + virtual ~Attachment(); + + const String &getName() const; + + virtual Attachment ©() = 0; + + Attachment *getTimelineAttachment(); + + void setTimelineAttachment(Attachment *attachment); + + Array &getTimelineSlots(); + + void setTimelineSlots(Array &timelineSlots); + + /// Returns true if the slotIndex or any getTimelineSlots() have an attachment whose getTimelineAttachment() is this attachment. + /// @param slots The Skeleton::getSlots(). + /// @param slotIndex The timeline's primary slot index. + bool isTimelineActive(Array &slots, int slotIndex, bool appliedPose); + + int getRefCount(); + + void reference(); + + void dereference(); + + private: + const String _name; + Attachment *_timelineAttachment; + Array _timelineSlots; + int _refCount; + }; +} + +#endif /* Spine_Attachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AttachmentLoader.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AttachmentLoader.h new file mode 100644 index 0000000..cc3cade --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AttachmentLoader.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentLoader_h +#define Spine_AttachmentLoader_h + +#include +#include +#include + +namespace spine { + class Skin; + + class Attachment; + + class RegionAttachment; + + class MeshAttachment; + + class BoundingBoxAttachment; + + class PathAttachment; + + class PointAttachment; + + class ClippingAttachment; + + class Sequence; + + class SP_API AttachmentLoader : public SpineObject { + public: + AttachmentLoader(); + + virtual ~AttachmentLoader(); + + /// @return May be NULL to not load any attachment. + virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &placeholder, const String &name, const String &path, + Sequence *sequence) = 0; + + /// @return May be NULL to not load any attachment. + virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &placeholder, const String &name, const String &path, + Sequence *sequence) = 0; + + /// @return May be NULL to not load any attachment. + virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &skin, const String &placeholder, const String &name) = 0; + + /// @return May be NULL to not load any attachment + virtual PathAttachment *newPathAttachment(Skin &skin, const String &placeholder, const String &name) = 0; + + virtual PointAttachment *newPointAttachment(Skin &skin, const String &placeholder, const String &name) = 0; + + virtual ClippingAttachment *newClippingAttachment(Skin &skin, const String &placeholder, const String &name) = 0; + }; +} + +#endif /* Spine_AttachmentLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AttachmentTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AttachmentTimeline.h new file mode 100644 index 0000000..7db63ba --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AttachmentTimeline.h @@ -0,0 +1,88 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentTimeline_h +#define Spine_AttachmentTimeline_h + +#include +#include +#include +#include +#include + +namespace spine { + + class Skeleton; + + class Slot; + + class SlotPose; + + class Event; + + class SP_API AttachmentTimeline : public Timeline, public SlotTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit AttachmentTimeline(size_t frameCount, int slotIndex); + + virtual ~AttachmentTimeline(); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + /// Sets the time and attachment name for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + /// @param time The frame time in seconds. + void setFrame(int frame, float time, const String &attachmentName); + + /// The attachment name for each frame. May contain null values to clear the attachment. + Array &getAttachmentNames(); + + virtual int getSlotIndex() override { + return _slotIndex; + } + + virtual void setSlotIndex(int inValue) override { + _slotIndex = inValue; + } + + protected: + int _slotIndex; + Array _attachmentNames; + + void setAttachment(Skeleton &skeleton, SlotPose &pose, String *attachmentName); + }; +} + +#endif /* Spine_AttachmentTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AttachmentType.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AttachmentType.h new file mode 100644 index 0000000..e4b97da --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/AttachmentType.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentType_h +#define Spine_AttachmentType_h + +#include + +namespace spine { + enum AttachmentType { + AttachmentType_Region, + AttachmentType_Boundingbox, + AttachmentType_Mesh, + AttachmentType_Linkedmesh, + AttachmentType_Path, + AttachmentType_Point, + AttachmentType_Clipping + }; + + inline AttachmentType AttachmentType_valueOf(const char *value) { + if (strcmp(value, "region") == 0) + return AttachmentType_Region; + else if (strcmp(value, "mesh") == 0) + return AttachmentType_Mesh; + else if (strcmp(value, "linkedmesh") == 0) + return AttachmentType_Linkedmesh; + else if (strcmp(value, "boundingbox") == 0) + return AttachmentType_Boundingbox; + else if (strcmp(value, "path") == 0) + return AttachmentType_Path; + else if (strcmp(value, "clipping") == 0) + return AttachmentType_Clipping; + else if (strcmp(value, "point") == 0) + return AttachmentType_Point; + else + return AttachmentType_Region;// default + } +} + +#endif /* Spine_AttachmentType_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BlendMode.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BlendMode.h new file mode 100644 index 0000000..e89a4f3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BlendMode.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BlendMode_h +#define Spine_BlendMode_h + +#include + +namespace spine { + enum BlendMode { + BlendMode_Normal = 0, + BlendMode_Additive, + BlendMode_Multiply, + BlendMode_Screen + }; + + inline BlendMode BlendMode_valueOf(const char *value) { + if (strcmp(value, "normal") == 0) + return BlendMode_Normal; + else if (strcmp(value, "additive") == 0) + return BlendMode_Additive; + else if (strcmp(value, "multiply") == 0) + return BlendMode_Multiply; + else if (strcmp(value, "screen") == 0) + return BlendMode_Screen; + else + return BlendMode_Normal;// default + } +} + +#endif /* Spine_BlendMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BlockAllocator.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BlockAllocator.h new file mode 100644 index 0000000..d08b6ec --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BlockAllocator.h @@ -0,0 +1,114 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BlockAllocator_h +#define Spine_BlockAllocator_h + +#include +#include +#include +#include +#include + +namespace spine { + struct Block { + int size; + int allocated; + uint8_t *memory; + + int free() { + return size - allocated; + } + + bool canFit(int numBytes) { + return free() >= numBytes; + } + + uint8_t *allocate(int numBytes) { + uint8_t *ptr = memory + allocated; + allocated += numBytes; + return ptr; + } + }; + + class BlockAllocator : public SpineObject { + int initialBlockSize; + Array blocks; + + public: + BlockAllocator(int initialBlockSize) : initialBlockSize(initialBlockSize) { + blocks.add(newBlock(initialBlockSize)); + } + + ~BlockAllocator() { + for (int i = 0, n = (int) blocks.size(); i < n; i++) { + SpineExtension::free(blocks[i].memory, __FILE__, __LINE__); + } + } + + template + T *allocate(size_t num) { + return (T *) _allocate((int) (sizeof(T) * num)); + } + + void compress() { + if (blocks.size() == 1) { + blocks[0].allocated = 0; + return; + } + int totalSize = 0; + for (int i = 0, n = (int) blocks.size(); i < n; i++) { + totalSize += blocks[i].size; + SpineExtension::free(blocks[i].memory, __FILE__, __LINE__); + } + blocks.clear(); + blocks.add(newBlock(totalSize)); + } + + private: + void *_allocate(int numBytes) { + // 16-byte align allocations + int alignedNumBytes = numBytes + (numBytes % 16 != 0 ? 16 - (numBytes % 16) : 0); + Block *block = &blocks[blocks.size() - 1]; + if (!block->canFit(alignedNumBytes)) { + blocks.add(newBlock(MathUtil::max(initialBlockSize, alignedNumBytes))); + block = &blocks[blocks.size() - 1]; + } + return block->allocate(alignedNumBytes); + } + + Block newBlock(int numBytes) { + Block block = {MathUtil::max(initialBlockSize, numBytes), 0, nullptr}; + block.memory = SpineExtension::alloc(block.size, __FILE__, __LINE__); + return block; + } + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Bone.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Bone.h new file mode 100644 index 0000000..553924e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Bone.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Bone_h +#define Spine_Bone_h + +#include +#include +#include +#include +#include + +namespace spine { + /// A node in a skeleton's hierarchy with a transform that affects its children and their attachments. A bone has a number of + /// poses: + /// - getData(): The setup pose data. + /// - getPose(): The unconstrained local pose. Set by animations and application code. + /// - getAppliedPose(): The local pose to use for rendering. Possibly modified by constraints. + /// - World transform: the local pose combined with the parent world transform. Computed on a pose by + /// BonePose::updateWorldTransform(Skeleton) and Skeleton::updateWorldTransform(Physics). + class SP_API Bone : public PosedGeneric, public PosedActive, public Update { + friend class AnimationState; + friend class RotateTimeline; + friend class IkConstraint; + friend class TransformConstraint; + friend class VertexAttachment; + friend class PathConstraint; + friend class PhysicsConstraint; + friend class Skeleton; + friend class Slider; + friend class RegionAttachment; + friend class PointAttachment; + friend class AttachmentTimeline; + friend class RGBATimeline; + friend class RGBTimeline; + friend class AlphaTimeline; + friend class RGBA2Timeline; + friend class RGB2Timeline; + friend class ScaleTimeline; + friend class ScaleXTimeline; + friend class ScaleYTimeline; + friend class ShearTimeline; + friend class ShearXTimeline; + friend class ShearYTimeline; + friend class TranslateTimeline; + friend class TranslateXTimeline; + friend class TranslateYTimeline; + friend class InheritTimeline; + + RTTI_DECL + + public: + /// @param parent May be NULL. + Bone(BoneData &data, Bone *parent); + + /// Copy constructor. Does not copy the child bones. + Bone(Bone &bone, Bone *parent); + + /// The parent bone, or null if this is the root bone. + Bone *getParent(); + + /// The immediate children of this bone. + Array &getChildren(); + + static bool isYDown() { + return yDown; + } + static void setYDown(bool value) { + yDown = value; + } + + virtual void update(Skeleton &skeleton, Physics physics) override { + // No-op, need to extend Update so we can stuff Bone into Skeleton.updateCache temporarily. + // See Skeleton::updateCache(). + } + + private: + static bool yDown; + Bone *const _parent; + Array _children; + bool _sorted; + }; +} + +#endif /* Spine_Bone_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BoneData.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BoneData.h new file mode 100644 index 0000000..e279e36 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BoneData.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BoneData_h +#define Spine_BoneData_h + +#include +#include +#include +#include +#include + +namespace spine { + class SP_API BoneData : public PosedDataGeneric { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + + friend class RotateTimeline; + + friend class ScaleTimeline; + + friend class ScaleXTimeline; + + friend class ScaleYTimeline; + + friend class ShearTimeline; + + friend class ShearXTimeline; + + friend class ShearYTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + friend class Slot; + + public: + BoneData(int index, const String &name, BoneData *parent = NULL); + + /// The Skeleton::getBones() index for this bone. + int getIndex(); + + /// The parent bone, or NULL if this bone is the root. + BoneData *getParent(); + + float getLength(); + + void setLength(float inValue); + + Color &getColor(); + + /// The bone icon name as it was in Spine, or empty if nonessential data was not exported. + const String &getIcon(); + + void setIcon(const String &icon); + + /// The bone icon's display size scale, or 1 if nonessential data was not exported. + float getIconSize(); + + void setIconSize(float iconSize); + + /// The bone icon's display rotation in degrees, or 0 if nonessential data was not exported. + float getIconRotation(); + + void setIconRotation(float iconRotation); + + bool getVisible(); + + void setVisible(bool inValue); + + private: + const int _index; + BoneData *_parent; + float _length; + Color _color; + String _icon; + float _iconSize; + float _iconRotation; + bool _visible; + }; +} + +#endif /* Spine_BoneData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BoneLocal.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BoneLocal.h new file mode 100644 index 0000000..51ebd26 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BoneLocal.h @@ -0,0 +1,127 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_BONELOCAL_H_ +#define SPINE_BONELOCAL_H_ + +#include +#include +#include +#include + +namespace spine { + /// Stores a bone's local pose. + class SP_API BoneLocal : public Pose { + friend class IkConstraint; + friend class BoneTimeline1; + friend class BoneTimeline2; + friend class RotateTimeline; + friend class InheritTimeline; + friend class ScaleTimeline; + friend class ScaleXTimeline; + friend class ScaleYTimeline; + friend class ShearTimeline; + friend class ShearXTimeline; + friend class ShearYTimeline; + friend class TranslateTimeline; + friend class TranslateXTimeline; + friend class TranslateYTimeline; + friend class SkeletonJson; + friend class SkeletonBinary; + friend class Skeleton; + friend class FromProperty; + friend class ToProperty; + friend class FromRotate; + friend class ToRotate; + friend class FromX; + friend class ToX; + friend class FromY; + friend class ToY; + friend class FromScaleX; + friend class ToScaleX; + friend class FromScaleY; + friend class ToScaleY; + friend class FromShearY; + friend class ToShearY; + friend class AnimationState; + + protected: + float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; + Inherit _inherit; + + public: + BoneLocal(); + virtual ~BoneLocal(); + + virtual void set(BoneLocal &pose) override; + + /// The local x translation. + float getX(); + void setX(float x); + + /// The local y translation. + float getY(); + void setY(float y); + + /// Sets local x and y translation. + void setPosition(float x, float y); + + /// The local rotation in degrees, counter clockwise. + float getRotation(); + void setRotation(float rotation); + + /// The local scaleX. + float getScaleX(); + void setScaleX(float scaleX); + + /// The local scaleY. + float getScaleY(); + void setScaleY(float scaleY); + + /// Sets local scaleX and scaleY. + void setScale(float scaleX, float scaleY); + + /// Sets local scaleX and scaleY to the same value. + void setScale(float scale); + + /// The local shearX. + float getShearX(); + void setShearX(float shearX); + + /// The local shearY. + float getShearY(); + void setShearY(float shearY); + + /// Determines how parent world transforms affect this bone. + Inherit getInherit(); + void setInherit(Inherit inherit); + }; +} + +#endif /* SPINE_BONELOCAL_H_ */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BonePose.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BonePose.h new file mode 100644 index 0000000..ad68210 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BonePose.h @@ -0,0 +1,173 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_BONEPOSE_H_ +#define SPINE_BONEPOSE_H_ + +#include +#include +#include + +namespace spine { + class Bone; + class Skeleton; + + /// The applied local pose and world transform for a bone. This is the bone's unconstrained pose with constraints applied and + /// the world transform computed by Skeleton::updateWorldTransform(Physics) and updateWorldTransform(Skeleton). + /// + /// If the world transform is changed, call updateLocalTransform(Skeleton) before using the local transform. The local + /// transform may be needed by other code (eg to apply another constraint). + /// + /// After changing the world transform, call updateWorldTransform(Skeleton) on every descendant bone. It may be more + /// convenient to modify the local transform instead, then call Skeleton::updateWorldTransform(Physics) to update the world + /// transforms for all bones and apply constraints. + class SP_API BonePose : public BoneLocal, public Update { + friend class IkConstraint; + friend class PathConstraint; + friend class PhysicsConstraint; + friend class TransformConstraint; + friend class TransformConstraintData; + friend class FromRotate; + friend class ToRotate; + friend class FromX; + friend class ToX; + friend class FromY; + friend class ToY; + friend class FromScaleX; + friend class ToScaleX; + friend class FromScaleY; + friend class ToScaleY; + friend class FromShearX; + friend class ToShearX; + friend class FromShearY; + friend class ToShearY; + friend class Skeleton; + friend class Bone; + + RTTI_DECL + + public: + BonePose(); + virtual ~BonePose(); + + /// Called by Skeleton::updateCache() to compute the world transform, if needed. + virtual void update(Skeleton &skeleton, Physics physics) override; + + /// Computes the world transform using the parent bone's world transform and this applied local pose. Child bones are not + /// updated. + /// + /// See World transforms in the Spine + /// Runtimes Guide. + void updateWorldTransform(Skeleton &skeleton); + + /// Computes the local transform values from the world transform. + /// + /// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The local transform after + /// calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. + void updateLocalTransform(Skeleton &skeleton); + + /// If the world transform has been modified by constraints and the local transform no longer matches, + /// updateLocalTransform() is called. Call this after Skeleton::updateWorldTransform(Physics) before using the applied + /// local transform. + void validateLocalTransform(Skeleton &skeleton); + + void modifyLocal(Skeleton &skeleton); + void modifyWorld(Skeleton &skeleton); + + /// The world transform [a b][c d] x-axis x component. + float getA(); + void setA(float a); + + /// The world transform [a b][c d] y-axis x component. + float getB(); + void setB(float b); + + /// The world transform [a b][c d] x-axis y component. + float getC(); + void setC(float c); + + /// The world transform [a b][c d] y-axis y component. + float getD(); + void setD(float d); + + /// The world X position. + float getWorldX(); + void setWorldX(float worldX); + + /// The world Y position. + float getWorldY(); + void setWorldY(float worldY); + + /// The world rotation for the X axis, calculated using a and c. This is the direction the bone is pointing. + float getWorldRotationX(); + + /// The world rotation for the Y axis, calculated using b and d. + float getWorldRotationY(); + + /// The magnitude (always positive) of the world scale X, calculated using a and c. + float getWorldScaleX(); + + /// The magnitude (always positive) of the world scale Y, calculated using b and d. + float getWorldScaleY(); + + /// Transforms a point from world coordinates to the bone's local coordinates. + void worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY); + + /// Transforms a point from the bone's local coordinates to world coordinates. + void localToWorld(float localX, float localY, float &outWorldX, float &outWorldY); + + /// Transforms a point from world coordinates to the parent bone's local coordinates. + void worldToParent(float worldX, float worldY, float &outParentX, float &outParentY); + + /// Transforms a point from the parent bone's coordinates to world coordinates. + void parentToWorld(float parentX, float parentY, float &outWorldX, float &outWorldY); + + /// Transforms a world rotation to a local rotation. + float worldToLocalRotation(float worldRotation); + + /// Transforms a local rotation to a world rotation. + float localToWorldRotation(float localRotation); + + /// Rotates the world transform the specified amount. + void rotateWorld(float degrees); + + private: + void setLocal(float ra, float rb, float rc, float rd); + void setLocal(float ra, float rb, float rc, float rd, float ro); + void resetWorld(Skeleton &skeleton, int update); + + protected: + Bone *_bone; + float _a, _b, _worldX; + float _c, _d, _worldY; + int _world, _local; + }; +}// namespace spine + +#endif /* SPINE_BONEPOSE_H_ */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BoneTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BoneTimeline.h new file mode 100644 index 0000000..cf846fe --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BoneTimeline.h @@ -0,0 +1,123 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BoneTimeline_h +#define Spine_BoneTimeline_h + +#include +#include +#include + +namespace spine { + class Skeleton; + class Event; + class BonePose; + + /// An interface for timelines which change the property of a bone. + class SP_API BoneTimeline { + RTTI_DECL_NOPARENT + + public: + BoneTimeline(int boneIndex) { + } + virtual ~BoneTimeline() { + } + + /// The Skeleton::getBones() index of the bone that will be changed when this timeline is applied. + virtual int getBoneIndex() const = 0; + + virtual void setBoneIndex(int inValue) = 0; + }; + + /// Base class for timelines that animate a single bone property. + class SP_API BoneTimeline1 : public CurveTimeline1, public BoneTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class AnimationState; + + RTTI_DECL + + public: + BoneTimeline1(size_t frameCount, size_t bezierCount, int boneIndex, Property property); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + virtual int getBoneIndex() const override { + return _boneIndex; + } + + virtual void setBoneIndex(int inValue) override { + _boneIndex = inValue; + } + + protected: + /// Applies changes to the pose based on the timeline values. + virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) = 0; + + int _boneIndex; + }; + + /// Base class for timelines that animate two bone properties. + class SP_API BoneTimeline2 : public CurveTimeline, public BoneTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class AnimationState; + + RTTI_DECL + + public: + BoneTimeline2(size_t frameCount, size_t bezierCount, int boneIndex, Property property1, Property property2); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + virtual int getBoneIndex() const override { + return _boneIndex; + } + + virtual void setBoneIndex(int inValue) override { + _boneIndex = inValue; + } + + virtual void setFrame(size_t frame, float time, float value1, float value2); + + protected: + /// Applies changes to the pose based on the timeline values. + virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) = 0; + + int _boneIndex; + + static const int ENTRIES; + static const int VALUE1; + static const int VALUE2; + }; +} + +#endif \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BoundingBoxAttachment.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BoundingBoxAttachment.h new file mode 100644 index 0000000..3ec3284 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/BoundingBoxAttachment.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BoundingBoxAttachment_h +#define Spine_BoundingBoxAttachment_h + +#include +#include +#include + +namespace spine { + /// Attachment that has a polygon for bounds checking. + class SP_API BoundingBoxAttachment : public VertexAttachment { + RTTI_DECL + + public: + explicit BoundingBoxAttachment(const String &name); + + Color &getColor(); + + virtual Attachment ©() override; + + private: + Color _color; + }; +} + +#endif /* Spine_BoundingBoxAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ClippingAttachment.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ClippingAttachment.h new file mode 100644 index 0000000..048fe8b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ClippingAttachment.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ClippingAttachment_h +#define Spine_ClippingAttachment_h + +#include +#include + +namespace spine { + class SlotData; + + class SP_API ClippingAttachment : public VertexAttachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class SkeletonClipping; + + RTTI_DECL + + public: + explicit ClippingAttachment(const String &name); + + /// Clipping is performed between the clipping attachment's slot and the end slot. If NULL, clipping is done until + /// the end of the skeleton's rendering. + SlotData *getEndSlot(); + + void setEndSlot(SlotData *inValue); + + /// When true the clipping polygon is treated as convex for more efficient clipping. If the polygon deforms to concave then the + /// convex hull is used. When false the clipping polygon can be concave and if so has an additional CPU cost. Inverse clipping + /// always uses convex. + bool getConvex(); + + void setConvex(bool convex); + + /// When false, everything inside the clipping polygon is visible. When true, everything outside the clipping polygon is + /// visible and clipping is convex. + bool getInverse(); + + void setInverse(bool inverse); + + Color &getColor(); + + virtual Attachment ©() override; + + private: + SlotData *_endSlot; + bool _convex; + bool _inverse; + Color _color; + }; +} + +#endif /* Spine_ClippingAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Color.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Color.h new file mode 100644 index 0000000..0c670a8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Color.h @@ -0,0 +1,156 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_COLOR_H +#define SPINE_COLOR_H + +#include +#include +#include + +namespace spine { + class SP_API Color : public SpineObject { + public: + Color() : r(0), g(0), b(0), a(0) { + } + + Color(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) { + clamp(); + } + + inline Color &set(float _r, float _g, float _b, float _a) { + this->r = _r; + this->g = _g; + this->b = _b; + this->a = _a; + clamp(); + return *this; + } + + inline Color &set(float _r, float _g, float _b) { + this->r = _r; + this->g = _g; + this->b = _b; + clamp(); + return *this; + } + + inline Color &set(const Color &other) { + r = other.r; + g = other.g; + b = other.b; + a = other.a; + clamp(); + return *this; + } + + inline Color &add(float _r, float _g, float _b, float _a) { + this->r += _r; + this->g += _g; + this->b += _b; + this->a += _a; + clamp(); + return *this; + } + + inline Color &add(float _r, float _g, float _b) { + this->r += _r; + this->g += _g; + this->b += _b; + clamp(); + return *this; + } + + inline Color &add(const Color &other) { + r += other.r; + g += other.g; + b += other.b; + a += other.a; + clamp(); + return *this; + } + + inline Color &clamp() { + r = MathUtil::clamp(this->r, 0, 1); + g = MathUtil::clamp(this->g, 0, 1); + b = MathUtil::clamp(this->b, 0, 1); + a = MathUtil::clamp(this->a, 0, 1); + return *this; + } + + // Parse hex color string like "ff0000ff" (RRGGBBAA) or "ff0000" (RRGGBB) + static Color valueOf(const char *hexString) { + Color color; + valueOf(hexString, color); + return color; + } + + // Parse hex color string into existing Color object + static void valueOf(const char *hexString, Color &color) { + size_t len = strlen(hexString); + if (len >= 6) { + color.r = parseHex(hexString, 0); + color.g = parseHex(hexString, 1); + color.b = parseHex(hexString, 2); + color.a = len >= 8 ? parseHex(hexString, 3) : 1.0f; + } + } + + static float parseHex(const char *value, size_t index) { + char digits[3]; + digits[0] = value[index * 2]; + digits[1] = value[index * 2 + 1]; + digits[2] = '\0'; + return strtoul(digits, NULL, 16) / 255.0f; + } + + // Convert packed RGBA8888 integer to Color + static void rgba8888ToColor(Color &color, int value) { + unsigned int rgba = (unsigned int) value; + color.r = ((rgba & 0xff000000) >> 24) / 255.0f; + color.g = ((rgba & 0x00ff0000) >> 16) / 255.0f; + color.b = ((rgba & 0x0000ff00) >> 8) / 255.0f; + color.a = (rgba & 0x000000ff) / 255.0f; + } + + // Convert packed RGB888 integer to Color (no alpha) + static void rgb888ToColor(Color &color, int value) { + unsigned int rgb = (unsigned int) value; + color.r = ((rgb & 0xff0000) >> 16) / 255.0f; + color.g = ((rgb & 0x00ff00) >> 8) / 255.0f; + color.b = (rgb & 0x0000ff) / 255.0f; + color.a = 1.0f; + } + + float r, g, b, a; + }; +} + + +#endif//SPINE_COLOR_H diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ColorTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ColorTimeline.h new file mode 100644 index 0000000..65d84e5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ColorTimeline.h @@ -0,0 +1,177 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ColorTimeline_h +#define Spine_ColorTimeline_h + +#include +#include + +namespace spine { + /// Changes a slot's color. + class SP_API RGBATimeline : public SlotCurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGBATimeline(); + + /// Sets the time and color for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + /// @param time The frame time in seconds. + void setFrame(int frame, float time, float r, float g, float b, float a); + + protected: + virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) override; + + static const int ENTRIES = 5; + static const int R = 1; + static const int G = 2; + static const int B = 3; + static const int A = 4; + }; + + /// Changes RGB for a slot's color. + class SP_API RGBTimeline : public SlotCurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGBTimeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGBTimeline(); + + /// Sets the time and color for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + /// @param time The frame time in seconds. + void setFrame(int frame, float time, float r, float g, float b); + + protected: + virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) override; + + static const int ENTRIES = 4; + static const int R = 1; + static const int G = 2; + static const int B = 3; + }; + + class SP_API AlphaTimeline : public CurveTimeline1, public SlotTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit AlphaTimeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~AlphaTimeline(); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + virtual int getSlotIndex() override; + + virtual void setSlotIndex(int inValue) override; + + protected: + int _slotIndex; + }; + + /// Changes a slot's light and dark colors for two color tinting. + class SP_API RGBA2Timeline : public SlotCurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGBA2Timeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGBA2Timeline(); + + /// Sets the time, light color, and dark color for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + /// @param time The frame time in seconds. + void setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2); + + protected: + virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) override; + + static const int ENTRIES = 8; + static const int R = 1; + static const int G = 2; + static const int B = 3; + static const int A = 4; + static const int R2 = 5; + static const int G2 = 6; + static const int B2 = 7; + }; + + /// Changes RGB for a slot's light and dark colors for two color tinting. + class SP_API RGB2Timeline : public SlotCurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit RGB2Timeline(size_t frameCount, size_t bezierCount, int slotIndex); + + virtual ~RGB2Timeline(); + + /// Sets the time, light color, and dark color for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + /// @param time The frame time in seconds. + void setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2); + + protected: + virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) override; + + static const int ENTRIES = 7; + static const int R = 1; + static const int G = 2; + static const int B = 3; + static const int R2 = 4; + static const int G2 = 5; + static const int B2 = 6; + }; +} + +#endif /* Spine_ColorTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Constraint.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Constraint.h new file mode 100644 index 0000000..5a66f86 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Constraint.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Constraint_h +#define Spine_Constraint_h + +#include +#include +#include +#include +#include + +namespace spine { + class Skeleton; + + class SP_API Constraint : public Update { + friend class Skeleton; + + public: + RTTI_DECL + + Constraint(); + virtual ~Constraint(); + + virtual ConstraintData &getData() = 0; + + virtual void sort(Skeleton &skeleton) = 0; + + virtual bool isSourceActive() = 0; + + // Inherited from Update + virtual void update(Skeleton &skeleton, Physics physics) override = 0; + + protected: + virtual void unconstrained() = 0; + + virtual void setupPose() = 0; + + bool _active; + }; + + template + class ConstraintGeneric : public PosedGeneric, public PosedActive, public Constraint { + public: + ConstraintGeneric(D &data) : PosedGeneric(data), PosedActive(), Constraint() { + } + + virtual ~ConstraintGeneric() { + } + + virtual D &getData() override { + return PosedGeneric::getData(); + } + + protected: + virtual void unconstrained() override { + PosedGeneric::unconstrained(); + } + + virtual void setupPose() override { + PosedGeneric::setupPose(); + } + }; +}// namespace spine + +#endif /* Spine_Constraint_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ConstraintData.h new file mode 100644 index 0000000..18311fc --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ConstraintData.h @@ -0,0 +1,108 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ConstraintData_h +#define Spine_ConstraintData_h + +#include +#include +#include +#include +#include + +namespace spine { + class Skeleton; + class Constraint; + + enum ScaleYMode { + ScaleYMode_None = 0, + ScaleYMode_Uniform, + ScaleYMode_Volume + }; + + inline ScaleYMode ScaleYMode_valueOf(const char *value) { + if (strcmp(value, "uniform") == 0) + return ScaleYMode_Uniform; + else if (strcmp(value, "volume") == 0) + return ScaleYMode_Volume; + else + return ScaleYMode_None; + } + + inline const char *ScaleYMode_toString(ScaleYMode scaleYMode) { + switch (scaleYMode) { + case ScaleYMode_Uniform: + return "uniform"; + case ScaleYMode_Volume: + return "volume"; + default: + return "none"; + } + } + + class SP_API ConstraintData : public SpineObject { + RTTI_DECL_NOPARENT + friend class Skeleton; + friend class Constraint; + + public: + ConstraintData(const String &name) : SpineObject(name) { + } + virtual ~ConstraintData() { + } + + virtual Constraint &create(Skeleton &skeleton) = 0; + + virtual const String &getName() const = 0; + + virtual bool getSkinRequired() const = 0; + }; + + /// Base class for all constraint data types. + template + class ConstraintDataGeneric : public PosedDataGeneric

, public ConstraintData { + public: + ConstraintDataGeneric(const String &name) : PosedDataGeneric

(name), ConstraintData(name) { + } + virtual ~ConstraintDataGeneric() { + } + + virtual Constraint &create(Skeleton &skeleton) override = 0; + + // Resolve ambiguity by forwarding to PosedData's implementation + virtual const String &getName() const override { + return PosedDataGeneric

::getName(); + } + virtual bool getSkinRequired() const override { + return PosedDataGeneric

::getSkinRequired(); + } + }; +} + +#endif /* Spine_ConstraintData_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ConstraintTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ConstraintTimeline.h new file mode 100644 index 0000000..16c2a5d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ConstraintTimeline.h @@ -0,0 +1,52 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ConstraintTimeline_h +#define Spine_ConstraintTimeline_h + +#include +#include + +namespace spine { + /// An interface for timelines which change the property of a constraint. + class SP_API ConstraintTimeline { + RTTI_DECL_NOPARENT + + public: + ConstraintTimeline(); + virtual ~ConstraintTimeline(); + + /// The Skeleton::getConstraints() index of the constraint that will be changed when this timeline is applied. + virtual int getConstraintIndex() const = 0; + + virtual void setConstraintIndex(int inValue) = 0; + }; +} + +#endif \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ConstraintTimeline1.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ConstraintTimeline1.h new file mode 100644 index 0000000..b7b7315 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ConstraintTimeline1.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ConstraintTimeline1_h +#define Spine_ConstraintTimeline1_h + +#include +#include +#include + +namespace spine { + /// The base class for timelines that change 1 constraint property with a curve. + class SP_API ConstraintTimeline1 : public CurveTimeline1, public ConstraintTimeline { + RTTI_DECL + + public: + ConstraintTimeline1(size_t frameCount, size_t bezierCount, int constraintIndex, Property property); + virtual ~ConstraintTimeline1(); + + virtual int getConstraintIndex() const override { + return _constraintIndex; + } + + virtual void setConstraintIndex(int inValue) override { + _constraintIndex = inValue; + } + + protected: + int _constraintIndex; + }; +}// namespace spine + +#endif /* Spine_ConstraintTimeline1_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/CurveTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/CurveTimeline.h new file mode 100644 index 0000000..fe30d25 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/CurveTimeline.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_CurveTimeline_h +#define Spine_CurveTimeline_h + +#include +#include + +namespace spine { + /// Base class for frames that use an interpolation bezier curve. + class SP_API CurveTimeline : public Timeline { + RTTI_DECL + + public: + explicit CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount); + + virtual ~CurveTimeline(); + + void setLinear(size_t frame); + + void setStepped(size_t frame); + + virtual void setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, float cy2, + float time2, float value2); + + float getBezierValue(float time, size_t frame, size_t valueOffset, size_t i); + + Array &getCurves(); + + protected: + static const int LINEAR = 0; + static const int STEPPED = 1; + static const int BEZIER = 2; + static const int BEZIER_SIZE = 18; + + Array _curves;// type, x, y, ... + }; + + /// The base class for a CurveTimeline that sets one property. + class SP_API CurveTimeline1 : public CurveTimeline { + RTTI_DECL + + public: + /// @param frameCount The number of frames for this timeline. + /// @param bezierCount The maximum number of Bezier curves. + explicit CurveTimeline1(size_t frameCount, size_t bezierCount); + + virtual ~CurveTimeline1(); + + /// Sets the time and value for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + /// @param time The frame time in seconds. + void setFrame(size_t frame, float time, float value); + + /// Returns the interpolated value for the specified time. + float getCurveValue(float time); + + float getRelativeValue(float time, float alpha, MixFrom from, bool add, float current, float setup); + + float getAbsoluteValue(float time, float alpha, MixFrom from, bool add, float current, float setup); + + float getAbsoluteValue(float time, float alpha, MixFrom from, bool add, float current, float setup, float value); + + float getScaleValue(float time, float alpha, MixFrom from, bool add, bool out, float current, float setup); + + static float beforeFirstKey(MixFrom from, float alpha, float current, float setup); + + protected: + static const int ENTRIES = 2; + static const int VALUE = 1; + }; +} + +#endif /* Spine_CurveTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Debug.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Debug.h new file mode 100644 index 0000000..b3a3227 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Debug.h @@ -0,0 +1,368 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_LOG_H +#define SPINE_LOG_H + +#include +#include + +#ifndef SPINE_NO_CPP_RT +#include +#endif + +namespace spine { + +#ifdef SPINE_NO_CPP_RT + // Need a copy as HashMap extends SpineObject, which would trigger + // infinite recursion when used in DebugExtension + template + class DebugHashMap { + private: + class DebugEntry; + + public: + class SP_API DebugPair { + public: + explicit DebugPair(K &k, V &v) : key(k), value(v) { + } + + K &key; + V &value; + }; + + class SP_API DebugEntries { + public: + friend class DebugHashMap; + + explicit DebugEntries(DebugEntry *entry) : _hasChecked(false) { + _start.next = entry; + _entry = &_start; + } + + DebugPair next() { + assert(_entry); + assert(_hasChecked); + _entry = _entry->next; + DebugPair pair(_entry->_key, _entry->_value); + _hasChecked = false; + return pair; + } + + bool hasNext() { + _hasChecked = true; + return _entry->next; + } + + private: + bool _hasChecked; + DebugEntry _start; + DebugEntry *_entry; + }; + + DebugHashMap() : _head(NULL), _size(0) { + } + + ~DebugHashMap() { + clear(); + } + + void clear() { + for (DebugEntry *entry = _head; entry != NULL;) { + DebugEntry *next = entry->next; + delete entry; + entry = next; + } + _head = NULL; + _size = 0; + } + + size_t size() { + return _size; + } + + void put(const K &key, const V &value) { + DebugEntry *entry = find(key); + if (entry) { + entry->_key = key; + entry->_value = value; + } else { + entry = new DebugEntry(); + entry->_key = key; + entry->_value = value; + + DebugEntry *oldHead = _head; + + if (oldHead) { + _head = entry; + oldHead->prev = entry; + entry->next = oldHead; + } else { + _head = entry; + } + _size++; + } + } + + bool addAll(Array &keys, const V &value) { + size_t oldSize = _size; + for (size_t i = 0; i < keys.size(); i++) { + put(keys[i], value); + } + return _size != oldSize; + } + + bool containsKey(const K &key) { + return find(key) != NULL; + } + + bool remove(const K &key) { + DebugEntry *entry = find(key); + if (!entry) return false; + + DebugEntry *prev = entry->prev; + DebugEntry *next = entry->next; + + if (prev) + prev->next = next; + else + _head = next; + if (next) next->prev = entry->prev; + + delete entry; + _size--; + + return true; + } + + V operator[](const K &key) { + DebugEntry *entry = find(key); + if (entry) + return entry->_value; + else { + assert(false); + return 0; + } + } + + DebugEntries getEntries() const { + return DebugEntries(_head); + } + + private: + DebugEntry *find(const K &key) { + for (DebugEntry *entry = _head; entry != NULL; entry = entry->next) { + if (entry->_key == key) return entry; + } + return NULL; + } + + class SP_API DebugEntry { + public: + K _key; + V _value; + DebugEntry *next; + DebugEntry *prev; + + DebugEntry() : next(NULL), prev(NULL) { + } + }; + + DebugEntry *_head; + size_t _size; + }; +#endif// SPINE_NO_CPP_RT + + class SP_API DebugExtension : public SpineExtension { + struct Allocation { + void *address; + size_t size; + const char *fileName; + int line; + + Allocation() : address(NULL), size(0), fileName(NULL), line(0) { + } + + Allocation(void *a, size_t s, const char *f, int l) : address(a), size(s), fileName(f), line(l) { + } + }; + + public: + DebugExtension(SpineExtension *extension) : _extension(extension), _allocations(0), _reallocations(0), _frees(0) { + } + + void reportLeaks() { +#ifdef SPINE_NO_CPP_RT + DebugHashMap::DebugEntries entries = _allocated.getEntries(); + while (entries.hasNext()) { + DebugHashMap::DebugPair pair = entries.next(); + printf("\"%s:%i (%zu bytes at %p)\n", pair.value.fileName, pair.value.line, pair.value.size, pair.value.address); + } +#else + for (const auto &pair : _allocated) { + printf("\"%s:%i (%zu bytes at %p)\n", pair.second.fileName, pair.second.line, pair.second.size, pair.second.address); + } +#endif + printf("allocations: %zu, reallocations: %zu, frees: %zu\n", _allocations, _reallocations, _frees); + if (_allocated.size() == 0) printf("No leaks detected\n"); + } + + void clearAllocations() { + _allocated.clear(); + _usedMemory = 0; + } + + virtual void *_alloc(size_t size, const char *file, int line) { + void *result = _extension->_alloc(size, file, line); +#ifdef SPINE_NO_CPP_RT + _allocated.put(result, Allocation(result, size, file, line)); +#else + _allocated[result] = Allocation(result, size, file, line); +#endif + _allocations++; + _usedMemory += size; + return result; + } + + virtual void *_calloc(size_t size, const char *file, int line) { + void *result = _extension->_calloc(size, file, line); +#ifdef SPINE_NO_CPP_RT + _allocated.put(result, Allocation(result, size, file, line)); +#else + _allocated[result] = Allocation(result, size, file, line); +#endif + _allocations++; + _usedMemory += size; + return result; + } + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) { +#ifdef SPINE_NO_CPP_RT + if (_allocated.containsKey(ptr)) { + // Find and store the size before removing + DebugHashMap::DebugEntries entries = _allocated.getEntries(); + while (entries.hasNext()) { + DebugHashMap::DebugPair pair = entries.next(); + if (pair.key == ptr) { + _usedMemory -= pair.value.size; + break; + } + } + _allocated.remove(ptr); + } +#else + auto it = _allocated.find(ptr); + if (it != _allocated.end()) { + _usedMemory -= it->second.size; + _allocated.erase(it); + } +#endif + void *result = _extension->_realloc(ptr, size, file, line); + _reallocations++; +#ifdef SPINE_NO_CPP_RT + _allocated.put(result, Allocation(result, size, file, line)); +#else + _allocated[result] = Allocation(result, size, file, line); +#endif + _usedMemory += size; + return result; + } + + virtual void _free(void *mem, const char *file, int line) { +#ifdef SPINE_NO_CPP_RT + if (_allocated.containsKey(mem)) { + _extension->_free(mem, file, line); + _frees++; + // Find and store the size before removing + DebugHashMap::DebugEntries entries = _allocated.getEntries(); + while (entries.hasNext()) { + DebugHashMap::DebugPair pair = entries.next(); + if (pair.key == mem) { + _usedMemory -= pair.value.size; + break; + } + } + _allocated.remove(mem); + return; + } +#else + auto it = _allocated.find(mem); + if (it != _allocated.end()) { + _extension->_free(mem, file, line); + _frees++; + _usedMemory -= it->second.size; + _allocated.erase(it); + return; + } +#endif + + printf("%s:%i (address %p): Double free or not allocated through SpineExtension\n", file, line, mem); + _extension->_free(mem, file, line); + } + + virtual char *_readFile(const String &path, int *length) { + auto data = _extension->_readFile(path, length); + +#ifdef SPINE_NO_CPP_RT + if (!_allocated.containsKey(data)) { + _allocated.put(data, Allocation(data, sizeof(char) * (*length), nullptr, 0)); + _allocations++; + _usedMemory += sizeof(char) * (*length); + } +#else + if (_allocated.find(data) == _allocated.end()) { + _allocated[data] = Allocation(data, sizeof(char) * (*length), nullptr, 0); + _allocations++; + _usedMemory += sizeof(char) * (*length); + } +#endif + + return data; + } + + size_t getUsedMemory() { + return _usedMemory; + } + + private: + SpineExtension *_extension; +#ifdef SPINE_NO_CPP_RT + DebugHashMap _allocated; +#else + std::unordered_map _allocated; +#endif + size_t _allocations; + size_t _reallocations; + size_t _frees; + size_t _usedMemory; + }; +} + + +#endif//SPINE_LOG_H diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/DeformTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/DeformTimeline.h new file mode 100644 index 0000000..ed5c3f9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/DeformTimeline.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DeformTimeline_h +#define Spine_DeformTimeline_h + +#include + +namespace spine { + class VertexAttachment; + + /// Changes a slot's deform to deform a VertexAttachment. + class SP_API DeformTimeline : public SlotCurveTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit DeformTimeline(size_t frameCount, size_t bezierCount, int slotIndex, VertexAttachment &attachment); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + /// Sets the time and vertices for the specified frame. + void setFrame(int frameIndex, float time, Array &vertices); + + /// The vertices for each frame. + Array> &getVertices(); + + /// The attachment whose vertices will be deformed. + VertexAttachment &getAttachment(); + + void setAttachment(VertexAttachment &inValue); + + virtual void setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, float cy2, + float time2, float value2) override; + + float getCurvePercent(float time, int frame); + + size_t getFrameCount() { + return _frames.size(); + } + + protected: + void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) override; + + private: + void applyBeforeFirst(Slot &slot, bool appliedPose, float alpha, MixFrom from); + void applyToPose(SlotPose &pose, Array &v1, Array *v2, float percent, size_t vertexCount, float alpha, MixFrom from, bool add); + void applyToSlot(Slot &slot, bool appliedPose, Array &v1, Array *v2, float percent, size_t vertexCount, float alpha, + MixFrom from, bool add); + + Array> _vertices; + + VertexAttachment *_attachment; + }; +} + +#endif /* Spine_DeformTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/DrawOrder.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/DrawOrder.h new file mode 100644 index 0000000..918084f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/DrawOrder.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DrawOrder_h +#define Spine_DrawOrder_h + +#include +#include + +namespace spine { + class Slot; + + /// Stores the skeleton's draw order, which is the order that each slot's attachment is rendered. + class SP_API DrawOrder : public SpineObject { + friend class Skeleton; + + friend class DrawOrderTimeline; + + friend class DrawOrderFolderTimeline; + + friend class Slider; + + public: + explicit DrawOrder(Array &setupPose); + + /// Sets the unconstrained draw order to the setup pose order. + void setupPose(); + + /// The unconstrained draw order, set by animations and application code. + Array &getPose(); + + /// The constrained draw order for rendering. If no constraints modify the draw order, this is the same as getPose(). + /// Otherwise it is a copy of getPose() modified by constraints. + Array &getAppliedPose(); + + private: + /// Sets the applied pose to the unconstrained pose, for when no constraints will modify the draw order. + void unconstrained(); + + /// Sets the applied pose to the constrained pose, in anticipation of the applied pose being modified by constraints. + void constrained(); + + /// Copies the unconstrained pose to the constrained pose, as a starting point for constraints to be applied. + void reset(); + + Array &_setupPose; + Array _pose; + Array _constrainedPose; + Array *_appliedPose; + }; +} + +#endif /* Spine_DrawOrder_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/DrawOrderFolderTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/DrawOrderFolderTimeline.h new file mode 100644 index 0000000..6bd2507 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/DrawOrderFolderTimeline.h @@ -0,0 +1,76 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DrawOrderFolderTimeline_h +#define Spine_DrawOrderFolderTimeline_h + +#include + +namespace spine { + class Slot; + + /// Changes a subset of the Skeleton::getDrawOrder() draw order. + class SP_API DrawOrderFolderTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + DrawOrderFolderTimeline(size_t frameCount, Array &slots, size_t slotCount); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + size_t getFrameCount(); + + /// The Skeleton::getSlots() indices that this timeline affects, in setup order. + Array &getSlots(); + + /// The draw order for each frame. See setFrame(). + Array> &getDrawOrders(); + + /// Sets the time and draw order for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + /// @param time The frame time in seconds. + /// @param drawOrder Ordered getSlots() indices, or null to use setup pose order. + void setFrame(size_t frame, float time, Array *drawOrder); + + private: + Array _slots; + Array _inFolder; + Array> _drawOrders; + + void setup(Array &pose, Array &setupPose); + void apply(Array &pose, Array &setupPose, Array &drawOrder); + }; +} + +#endif /* Spine_DrawOrderFolderTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/DrawOrderTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/DrawOrderTimeline.h new file mode 100644 index 0000000..9f8bc7a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/DrawOrderTimeline.h @@ -0,0 +1,69 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DrawOrderTimeline_h +#define Spine_DrawOrderTimeline_h + +#include + +namespace spine { + /// Changes the Skeleton::getDrawOrder(). + class SP_API DrawOrderTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + static PropertyId getPropertyId(); + + explicit DrawOrderTimeline(size_t frameCount); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + size_t getFrameCount(); + + /// The draw order for each frame. See setFrame(). + Array> &getDrawOrders(); + + /// Sets the time and draw order for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + /// @param time The frame time in seconds. + /// @param drawOrder For each slot in Skeleton::getSlots(), the index of the slot in the new draw order. May be null to use + /// setup pose draw order. + void setFrame(size_t frame, float time, Array *drawOrder); + + private: + Array> _drawOrders; + }; +} + +#endif /* Spine_DrawOrderTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Event.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Event.h new file mode 100644 index 0000000..43e8efb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Event.h @@ -0,0 +1,95 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Event_h +#define Spine_Event_h + +#include +#include + +namespace spine { + class EventData; + + /// Fired by EventTimeline when specific animation times are reached. + /// + /// See Timeline::apply(), AnimationStateListener::event(), and + /// https://esotericsoftware.com/spine-events Events in the Spine User Guide. + class SP_API Event : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + + public: + Event(float time, const EventData &data); + + /// The event's setup pose data. + const EventData &getData(); + + /// The animation time this event was keyed, or -1 for the setup pose. + float getTime(); + + /// The integer payload for this event. + int getInt(); + + void setInt(int inValue); + + /// The float payload for this event. + float getFloat(); + + void setFloat(float inValue); + + /// The string payload for this event. + const String &getString(); + + void setString(const String &inValue); + + /// If an audio path is set, the volume for the audio. + float getVolume(); + + void setVolume(float inValue); + + /// If an audio path is set, the left/right balance for the audio. + float getBalance(); + + void setBalance(float inValue); + + private: + const EventData &_data; + const float _time; + int _intValue; + float _floatValue; + String _stringValue; + float _volume; + float _balance; + }; +} + +#endif /* Spine_Event_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/EventData.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/EventData.h new file mode 100644 index 0000000..cf9f7f1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/EventData.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_EventData_h +#define Spine_EventData_h + +#include +#include +#include + +namespace spine { + /// Stores the setup pose values for an Event. + class SP_API EventData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class Event; + + public: + explicit EventData(const String &name); + + /// The name of the event, unique across all events in the skeleton. + const String &getName() const; + + /// The setup values that are shared by all events with this data. + Event &getSetupPose(); + const Event &getSetupPose() const; + + /// Path to an audio file relative to the audio folder as defined in Spine. + const String &getAudioPath() const; + + void setAudioPath(const String &inValue); + + private: + const String _name; + String _audioPath; + Event _setupPose; + }; +} + +#endif /* Spine_EventData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/EventTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/EventTimeline.h new file mode 100644 index 0000000..ba371b8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/EventTimeline.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_EventTimeline_h +#define Spine_EventTimeline_h + +#include + +namespace spine { + /// Fires an Event when specific animation times are reached. + class SP_API EventTimeline : public Timeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit EventTimeline(size_t frameCount); + + ~EventTimeline(); + + /// Fires events for frames > lastTime and <= time. + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + size_t getFrameCount(); + + /// The event for each frame. + Array &getEvents(); + + /// Sets the time and event for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + void setFrame(size_t frame, Event &event); + + private: + Array _events; + }; +} + +#endif /* Spine_EventTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Extension.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Extension.h new file mode 100644 index 0000000..e3d0d6f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Extension.h @@ -0,0 +1,136 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Extension_h +#define Spine_Extension_h + + +#include +#include +#include + +#define SP_UNUSED(x) (void) (x) + +namespace spine { + class String; + + class SP_API SpineExtension { + public: + template + static T *alloc(size_t num, const char *file, int line) { + return (T *) getInstance()->_alloc(sizeof(T) * num, file, line); + } + + template + static T *calloc(size_t num, const char *file, int line) { + return (T *) getInstance()->_calloc(sizeof(T) * num, file, line); + } + + template + static T *realloc(T *ptr, size_t num, const char *file, int line) { + return (T *) getInstance()->_realloc(ptr, sizeof(T) * num, file, line); + } + + template + static void free(T *ptr, const char *file, int line) { + getInstance()->_free((void *) ptr, file, line); + } + + template + static void beforeFree(T *ptr) { + getInstance()->_beforeFree((void *) ptr); + } + + static char *readFile(const String &path, int *length) { + return getInstance()->_readFile(path, length); + } + + static char *strdup(const char *str, const char *file, int line) { + if (!str) return nullptr; + size_t len = strlen(str) + 1; + char *copy = (char *) getInstance()->_alloc(len, file, line); + memcpy(copy, str, len); + return copy; + } + + static void setInstance(SpineExtension *inSpineExtension); + + static SpineExtension *getInstance(); + + virtual ~SpineExtension(); + + /// Implement this function to use your own memory allocator + virtual void *_alloc(size_t size, const char *file, int line) = 0; + + virtual void *_calloc(size_t size, const char *file, int line) = 0; + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) = 0; + + /// If you provide a spineAllocFunc, you should also provide a spineFreeFunc + virtual void _free(void *mem, const char *file, int line) = 0; + + virtual char *_readFile(const String &path, int *length) = 0; + + virtual void _beforeFree(void *ptr) { + SP_UNUSED(ptr); + } + + protected: + SpineExtension(); + + private: + static SpineExtension *_instance; + }; + + class SP_API DefaultSpineExtension : public SpineExtension { + public: + DefaultSpineExtension(); + + virtual ~DefaultSpineExtension(); + + protected: + virtual void *_alloc(size_t size, const char *file, int line) override; + + virtual void *_calloc(size_t size, const char *file, int line) override; + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) override; + + virtual void _free(void *mem, const char *file, int line) override; + + virtual char *_readFile(const String &path, int *length) override; + }; + + // This function is to be implemented by engine specific runtimes to provide + // the default extension for that engine. It is called the first time + // SpineExtension::getInstance() is called, when no instance has been set + // yet. + extern SpineExtension *getDefaultExtension(); +} + +#endif /* Spine_Extension_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/HasRendererObject.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/HasRendererObject.h new file mode 100644 index 0000000..55e038c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/HasRendererObject.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_HasRendererObject_h +#define Spine_HasRendererObject_h + +#include + +namespace spine { + + typedef void (*DisposeRendererObject)(void *rendererObject); + + class SP_API HasRendererObject { + public: + explicit HasRendererObject() : _rendererObject(0), _dispose(0) {}; + + virtual ~HasRendererObject() { + if (_dispose && _rendererObject) _dispose(_rendererObject); + } + + void *getRendererObject() { + return _rendererObject; + } + + void setRendererObject(void *rendererObject, DisposeRendererObject dispose = 0) { + if (_dispose && _rendererObject && _rendererObject != rendererObject) _dispose(_rendererObject); + + _rendererObject = rendererObject; + _dispose = dispose; + } + + private: + void *_rendererObject; + DisposeRendererObject _dispose; + }; + +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/HashMap.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/HashMap.h new file mode 100644 index 0000000..6bcbe49 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/HashMap.h @@ -0,0 +1,202 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_HashMap_h +#define Spine_HashMap_h + +#include +#include + +// Required for new with line number and file name in MSVC +#ifdef _MSC_VER +#pragma warning(disable : 4291) + +#pragma warning(disable : 4251) + +#endif + +namespace spine { + template + class HashMap : public SpineObject { + private: + class Entry; + + public: + class Pair { + public: + explicit Pair(K &k, V &v) : key(k), value(v) { + } + + K &key; + V &value; + }; + + class Entries { + public: + friend class HashMap; + + explicit Entries(Entry *entry) : _hasChecked(false) { + _start.next = entry; + _entry = &_start; + } + + Pair next() { + assert(_entry); + assert(_hasChecked); + _entry = _entry->next; + Pair pair(_entry->_key, _entry->_value); + _hasChecked = false; + return pair; + } + + bool hasNext() { + _hasChecked = true; + return _entry->next; + } + + private: + bool _hasChecked; + Entry _start; + Entry *_entry; + }; + + HashMap() : _head(NULL), _size(0) { + } + + ~HashMap() { + clear(); + } + + void clear() { + for (Entry *entry = _head; entry != NULL;) { + Entry *next = entry->next; + delete entry; + entry = next; + } + _head = NULL; + _size = 0; + } + + size_t size() { + return _size; + } + + void put(const K &key, const V &value) { + Entry *entry = find(key); + if (entry) { + entry->_key = key; + entry->_value = value; + } else { + entry = new (__FILE__, __LINE__) Entry(); + entry->_key = key; + entry->_value = value; + + Entry *oldHead = _head; + + if (oldHead) { + _head = entry; + oldHead->prev = entry; + entry->next = oldHead; + } else { + _head = entry; + } + _size++; + } + } + + bool addAll(Array &keys, const V &value) { + size_t oldSize = _size; + for (size_t i = 0; i < keys.size(); i++) { + put(keys[i], value); + } + return _size != oldSize; + } + + bool containsKey(const K &key) { + return find(key) != NULL; + } + + bool remove(const K &key) { + Entry *entry = find(key); + if (!entry) return false; + + Entry *prev = entry->prev; + Entry *next = entry->next; + + if (prev) + prev->next = next; + else + _head = next; + if (next) next->prev = entry->prev; + + delete entry; + _size--; + + return true; + } + + V operator[](const K &key) { + Entry *entry = find(key); + if (entry) + return entry->_value; + else { + assert(false); + return 0; + } + } + + Entries getEntries() const { + return Entries(_head); + } + + private: + Entry *find(const K &key) { + for (Entry *entry = _head; entry != NULL; entry = entry->next) { + if (entry->_key == key) return entry; + } + return NULL; + } + + class SP_API Entry : public SpineObject { + public: + K _key; + V _value; + Entry *next; + Entry *prev; + + Entry() : next(NULL), prev(NULL) { + } + }; + + Entry *_head; + size_t _size; + }; +} + +#endif /* Spine_HashMap_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/IkConstraint.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/IkConstraint.h new file mode 100644 index 0000000..8f41130 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/IkConstraint.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraint_h +#define Spine_IkConstraint_h + +#include +#include +#include +#include +#include + +namespace spine { + class Skeleton; + class Bone; + class BonePose; + + // Non-exported base class that inherits from the template + class IkConstraintBase : public ConstraintGeneric { + public: + IkConstraintBase(IkConstraintData &data) : ConstraintGeneric(data) { + } + }; + + class SP_API IkConstraint : public IkConstraintBase { + friend class Skeleton; + + friend class IkConstraintTimeline; + + RTTI_DECL + + public: + IkConstraint(IkConstraintData &data, Skeleton &skeleton); + + virtual IkConstraint ©(Skeleton &skeleton); + + virtual void update(Skeleton &skeleton, Physics physics) override; + + virtual void sort(Skeleton &skeleton) override; + + virtual bool isSourceActive() override; + + Array &getBones(); + + Bone &getTarget(); + + void setTarget(Bone &inValue); + + /// Adjusts the local rotation of the bone so the world position of the tip is as close to the target position as + /// possible. The target is specified in the world coordinate system. + static void apply(Skeleton &skeleton, BonePose &bone, float targetX, float targetY, bool compress, bool stretch, ScaleYMode scaleYMode, + float mix); + + /// Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as + /// possible. The target is specified in the world coordinate system. + /// @param child A direct descendant of the parent bone. + static void apply(Skeleton &skeleton, BonePose &parent, BonePose &child, float targetX, float targetY, int bendDirection, bool stretch, + ScaleYMode scaleYMode, float softness, float mix); + + private: + Array _bones; + Bone *_target; + }; +} + +#endif /* Spine_IkConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/IkConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/IkConstraintData.h new file mode 100644 index 0000000..be5b629 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/IkConstraintData.h @@ -0,0 +1,83 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraintData_h +#define Spine_IkConstraintData_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + class BoneData; + class IkConstraint; + + class SP_API IkConstraintData : public ConstraintDataGeneric { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class IkConstraint; + + friend class Skeleton; + + friend class IkConstraintTimeline; + + RTTI_DECL + + public: + explicit IkConstraintData(const String &name); + + virtual Constraint &create(Skeleton &skeleton) override; + + /// The bones that are constrained by this IK Constraint. + Array &getBones(); + + /// The bone that is the IK target. + BoneData &getTarget(); + + void setTarget(BoneData &inValue); + + /// Determines how BonePose::getScaleY() changes when IkConstraintPose::getCompress() or IkConstraintPose::getStretch() + /// sets BonePose::getScaleX(). + ScaleYMode getScaleYMode(); + + void setScaleYMode(ScaleYMode scaleYMode); + + private: + Array _bones; + BoneData *_target; + ScaleYMode _scaleYMode; + }; +} + +#endif /* Spine_IkConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/IkConstraintPose.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/IkConstraintPose.h new file mode 100644 index 0000000..2f86ae5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/IkConstraintPose.h @@ -0,0 +1,84 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraintPose_h +#define Spine_IkConstraintPose_h + +#include +#include + +namespace spine { + + /// Stores a pose for an IK constraint. + class SP_API IkConstraintPose : public Pose { + friend class IkConstraint; + friend class IkConstraintTimeline; + friend class SkeletonJson; + friend class SkeletonBinary; + + public: + IkConstraintPose(); + virtual ~IkConstraintPose(); + + virtual void set(IkConstraintPose &pose) override; + + /// A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. + /// + /// For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0. + float getMix(); + void setMix(float mix); + + /// For two bone IK, the target bone's distance from the maximum reach of the bones where rotation begins to slow. The bones + /// will not straighten completely until the target is this far out of range. + float getSoftness(); + void setSoftness(float softness); + + /// For two bone IK, controls the bend direction of the IK bones, either 1 or -1. + int getBendDirection(); + void setBendDirection(int bendDirection); + + /// For one bone IK, when true and the target is too close, the bone is scaled to reach it. + bool getCompress(); + void setCompress(bool compress); + + /// When true and the target is out of range, the parent bone is scaled to reach it. + /// + /// For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if softness is + /// > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied. + bool getStretch(); + void setStretch(bool stretch); + + private: + int _bendDirection; + bool _compress, _stretch; + float _mix, _softness; + }; +} + +#endif /* Spine_IkConstraintPose_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/IkConstraintTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/IkConstraintTimeline.h new file mode 100644 index 0000000..38e12eb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/IkConstraintTimeline.h @@ -0,0 +1,80 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraintTimeline_h +#define Spine_IkConstraintTimeline_h + +#include +#include + +namespace spine { + + /// Changes an IK constraint's mix, softness, bend direction, stretch, and compress values. + class SP_API IkConstraintTimeline : public CurveTimeline, public ConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit IkConstraintTimeline(size_t frameCount, size_t bezierCount, int constraintIndex); + + virtual ~IkConstraintTimeline(); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + /// Sets the time, mix, softness, bend direction, compress, and stretch for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + /// @param time The frame time in seconds. + /// @param bendDirection 1 or -1. + void setFrame(int frame, float time, float mix, float softness, int bendDirection, bool compress, bool stretch); + + virtual int getConstraintIndex() const override { + return _constraintIndex; + } + + virtual void setConstraintIndex(int inValue) override { + _constraintIndex = inValue; + } + + private: + int _constraintIndex; + + static const int ENTRIES = 6; + static const int MIX = 1; + static const int SOFTNESS = 2; + static const int BEND_DIRECTION = 3; + static const int COMPRESS = 4; + static const int STRETCH = 5; + }; +} + +#endif /* Spine_IkConstraintTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Inherit.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Inherit.h new file mode 100644 index 0000000..ec520cc --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Inherit.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformMode_h +#define Spine_TransformMode_h + +#include + +namespace spine { + /// Determines how a bone inherits world transforms from parent bones. + enum Inherit { + Inherit_Normal = 0, + Inherit_OnlyTranslation, + Inherit_NoRotationOrReflection, + Inherit_NoScale, + Inherit_NoScaleOrReflection + }; + + inline Inherit Inherit_valueOf(const char *value) { + if (strcmp(value, "normal") == 0) + return Inherit_Normal; + else if (strcmp(value, "onlyTranslation") == 0) + return Inherit_OnlyTranslation; + else if (strcmp(value, "noRotationOrReflection") == 0) + return Inherit_NoRotationOrReflection; + else if (strcmp(value, "noScale") == 0) + return Inherit_NoScale; + else if (strcmp(value, "noScaleOrReflection") == 0) + return Inherit_NoScaleOrReflection; + else + return Inherit_Normal;// default + } +} + +#endif /* Spine_TransformMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/InheritTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/InheritTimeline.h new file mode 100644 index 0000000..c768ef5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/InheritTimeline.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_InheritTimeline_h +#define Spine_InheritTimeline_h + +#include +#include +#include +#include +#include + +namespace spine { + + /// Changes a bone's inherit mode. + class SP_API InheritTimeline : public Timeline, public BoneTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit InheritTimeline(size_t frameCount, int boneIndex); + + virtual ~InheritTimeline(); + + /// Sets the inherit transform mode for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + /// @param time The frame time in seconds. + void setFrame(int frame, float time, Inherit inherit); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + + virtual int getBoneIndex() const override { + return _boneIndex; + } + + void setBoneIndex(int inValue) override { + _boneIndex = inValue; + } + + private: + int _boneIndex; + + static const int ENTRIES = 2; + static const int INHERIT = 1; + }; +} + +#endif /* Spine_InheritTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Interpolation.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Interpolation.h new file mode 100644 index 0000000..4b06de5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Interpolation.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Interpolation_h +#define Spine_Interpolation_h + +#include + +namespace spine { + /// Takes a linear value in the range 0-1 and outputs a usually non-linear, interpolated value. + class SP_API Interpolation : public SpineObject { + public: + virtual ~Interpolation(); + + /// @param a Alpha value between 0 and 1. + virtual float apply(float a); + + float apply(float start, float end, float a); + + static Interpolation &linear(); + + /// Aka "smoothstep". + static Interpolation &smooth(); + + /// Slow, then fast. + static Interpolation &slowFast(); + + /// Fast, then slow. + static Interpolation &fastSlow(); + + static Interpolation &circle(); + }; +} + +#endif /* Spine_Interpolation_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Json.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Json.h new file mode 100644 index 0000000..b7683f1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Json.h @@ -0,0 +1,141 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Json_h +#define Spine_Json_h + +#include +#include + +#ifndef SPINE_JSON_HAVE_PREV +/* spine doesn't use the "prev" link in the Json sibling lists. */ +#define SPINE_JSON_HAVE_PREV 0 +#endif + +namespace spine { + class SP_API Json : public SpineObject { + friend class SkeletonJson; + + public: + /* Json Types: */ + static const int JSON_FALSE; + static const int JSON_TRUE; + static const int JSON_NULL; + static const int JSON_NUMBER; + static const int JSON_STRING; + static const int JSON_ARRAY; + static const int JSON_OBJECT; + + static bool asFloatArray(Json *value, Array &array) { + if (value == NULL) return false; + array.setSize(value->_size, 0); + Json *vertex = value->_child; + for (int i = 0; vertex; vertex = vertex->_next, i++) array[i] = vertex->_valueFloat; + return true; + } + + static bool asIntArray(Json *value, Array &array) { + if (value == NULL) return false; + array.setSize(value->_size, 0); + Json *vertex = value->_child; + for (int i = 0; vertex; vertex = vertex->_next, i++) array[i] = vertex->_valueInt; + return true; + } + + static bool asUnsignedShortArray(Json *value, Array &array) { + if (value == NULL) return false; + array.setSize(value->_size, 0); + Json *vertex = value->_child; + for (int i = 0; vertex; vertex = vertex->_next, i++) array[i] = (unsigned short) vertex->_valueInt; + return true; + } + + /* Get item "string" from object. Case insensitive. */ + static Json *getItem(Json *object, const char *string); + + static Json *getItem(Json *object, int childIndex); + + static const char *getString(Json *object, const char *name, const char *defaultValue); + + static float getFloat(Json *object, const char *name, float defaultValue); + + static int getInt(Json *object, const char *name, int defaultValue); + + static bool getBoolean(Json *object, const char *name, bool defaultValue); + + /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when Json_create() returns 0. 0 when Json_create() succeeds. */ + static const char *getError(); + + /* Supply a block of JSON, and this returns a Json object you can interrogate. Call Json_dispose when finished. */ + explicit Json(const char *value); + + ~Json(); + + + private: + static const char *_error; + + Json *_next; +#if SPINE_JSON_HAVE_PREV + Json *_prev; /* next/prev allow you to walk array/object chains. Alternatively, use getSize/getItem */ +#endif + Json *_child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int _type; /* The type of the item, as above. */ + int _size; /* The number of children. */ + + const char *_valueString; /* The item's string, if type==JSON_STRING */ + int _valueInt; /* The item's number, if type==JSON_NUMBER */ + float _valueFloat; /* The item's number, if type==JSON_NUMBER */ + + const char *_name; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + + /* Utility to jump whitespace and cr/lf */ + static const char *skip(const char *inValue); + + /* Parser core - when encountering text, process appropriately. */ + static const char *parseValue(Json *item, const char *value); + + /* Parse the input text into an unescaped cstring, and populate item. */ + static const char *parseString(Json *item, const char *str); + + /* Parse the input text to generate a number, and populate the result into item. */ + static const char *parseNumber(Json *item, const char *num); + + /* Build an array from input text. */ + static const char *parseArray(Json *item, const char *value); + + /* Build an object from the text. */ + static const char *parseObject(Json *item, const char *value); + + static int json_strcasecmp(const char *s1, const char *s2); + }; +} + +#endif /* Spine_Json_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/LinkedMesh.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/LinkedMesh.h new file mode 100644 index 0000000..527aa31 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/LinkedMesh.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_LinkedMesh_h +#define Spine_LinkedMesh_h + +#include +#include + +namespace spine { + class MeshAttachment; + + class SP_API LinkedMesh : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + public: + LinkedMesh(MeshAttachment &mesh, const int skinIndex, size_t slotIndex, size_t sourceIndex, const String &source, bool inheritTimelines); + + LinkedMesh(MeshAttachment &mesh, const String &skin, size_t slotIndex, size_t sourceIndex, const String &source, bool inheritTimelines); + + private: + MeshAttachment *_mesh; + int _skinIndex; + String _skin; + size_t _slotIndex; + size_t _sourceIndex; + String _source; + bool _inheritTimelines; + }; +} + +#endif /* Spine_LinkedMesh_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Map.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Map.h new file mode 100644 index 0000000..3e51091 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Map.h @@ -0,0 +1,400 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Map_h +#define Spine_Map_h + +#include +#include +#include +#include + +#include +#include +#include + +namespace spine { + template + class MapHash { + public: + size_t operator()(const K &key) const { + return (size_t) key; + } + }; + + template + class MapHash { + public: + size_t operator()(T *const &key) const { + uintptr_t value = (uintptr_t) key; + return (size_t) (value >> 4); + } + }; + + template<> + class MapHash { + public: + size_t operator()(const long long &key) const { + unsigned long long value = (unsigned long long) key; + return (size_t) (value ^ (value >> 32)); + } + }; + + template<> + class MapHash { + public: + size_t operator()(const unsigned long long &key) const { + return (size_t) (key ^ (key >> 32)); + } + }; + + template<> + class MapHash { + public: + size_t operator()(const String &key) const { + const unsigned char *buffer = (const unsigned char *) key.buffer(); + size_t length = key.length(); + uint64_t hash = 14695981039346656037ULL; + for (size_t i = 0; i < length; i++) { + hash ^= buffer[i]; + hash *= 1099511628211ULL; + } + return (size_t) (hash ^ (hash >> 32)); + } + }; + + template + class MapEquals { + public: + bool operator()(const K &a, const K &b) const { + return a == b; + } + }; + + /// A compact open-addressed hash map. Unlike HashMap, this implementation does not allocate per entry. + /// Iteration order is unspecified and may change when the map grows or entries are removed. + template, typename Equals = MapEquals> + class Map : public SpineObject { + private: + enum State { + Empty = 0, + Occupied = 1, + Deleted = 2 + }; + + struct Entry { + K key; + V value; + }; + + public: + class Pair { + public: + explicit Pair(K &k, V &v) : key(k), value(v) { + } + + K &key; + V &value; + }; + + class Entries { + public: + friend class Map; + + bool hasNext() { + while (_index < _map->_capacity) { + if (_map->_states[_index] == Occupied) return true; + _index++; + } + return false; + } + + Pair next() { + assert(_index < _map->_capacity); + assert(_map->_states[_index] == Occupied); + Entry &entry = _map->_entries[_index++]; + return Pair(entry.key, entry.value); + } + + private: + explicit Entries(Map &map) : _map(&map), _index(0) { + } + + Map *_map; + size_t _index; + }; + + Map() : _entries(NULL), _states(NULL), _capacity(0), _size(0), _deleted(0), _hash(), _equals() { + } + + explicit Map(size_t capacity) : _entries(NULL), _states(NULL), _capacity(0), _size(0), _deleted(0), _hash(), _equals() { + ensureCapacity(capacity); + } + + Map(const Map &other) : _entries(NULL), _states(NULL), _capacity(0), _size(0), _deleted(0), _hash(other._hash), _equals(other._equals) { + ensureCapacity(other._size); + for (size_t i = 0; i < other._capacity; i++) { + if (other._states[i] == Occupied) put(other._entries[i].key, other._entries[i].value); + } + } + + Map &operator=(const Map &other) { + if (this == &other) return *this; + clear(); + _hash = other._hash; + _equals = other._equals; + ensureCapacity(other._size); + for (size_t i = 0; i < other._capacity; i++) { + if (other._states[i] == Occupied) put(other._entries[i].key, other._entries[i].value); + } + return *this; + } + + ~Map() { + release(); + } + + size_t size() const { + return _size; + } + + size_t getCapacity() const { + return _capacity; + } + + bool isEmpty() const { + return _size == 0; + } + + void ensureCapacity(size_t expectedSize) { + size_t needed = capacityFor(expectedSize); + if (_capacity < needed) rehash(needed); + } + + void clear() { + for (size_t i = 0; i < _capacity; i++) { + if (_states[i] == Occupied) resetEntry(i); + _states[i] = Empty; + } + _size = 0; + _deleted = 0; + } + + void release() { + if (!_entries) return; + clear(); + for (size_t i = 0; i < _capacity; i++) _entries[i].~Entry(); + SpineExtension::free(_entries, __FILE__, __LINE__); + SpineExtension::free(_states, __FILE__, __LINE__); + _entries = NULL; + _states = NULL; + _capacity = 0; + } + + bool containsKey(const K &key) const { + return findIndex(key) >= 0; + } + + V *get(const K &key) { + int index = findIndex(key); + return index >= 0 ? &_entries[index].value : NULL; + } + + const V *get(const K &key) const { + int index = findIndex(key); + return index >= 0 ? &_entries[index].value : NULL; + } + + V operator[](const K &key) const { + const V *value = get(key); + assert(value); + return *value; + } + + void put(const K &key, const V &value) { + ensureLoadForOneMore(); + bool found = false; + size_t index = findSlot(key, found); + if (found) { + _entries[index].value = value; + return; + } + if (_states[index] == Deleted) _deleted--; + _states[index] = Occupied; + _entries[index].key = key; + _entries[index].value = value; + _size++; + } + + /// Adds the key and value only if the key is not already present. + /// @return The existing value, or V() if the key was not present and the new value was added. + V putMissing(const K &key, const V &value) { + ensureLoadForOneMore(); + bool found = false; + size_t index = findSlot(key, found); + if (found) return _entries[index].value; + if (_states[index] == Deleted) _deleted--; + _states[index] = Occupied; + _entries[index].key = key; + _entries[index].value = value; + _size++; + return V(); + } + + bool addAll(Array &keys, const V &value) { + size_t oldSize = _size; + ensureCapacity(_size + keys.size()); + for (size_t i = 0; i < keys.size(); i++) put(keys[i], value); + return _size != oldSize; + } + + bool remove(const K &key) { + int index = findIndex(key); + if (index < 0) return false; + resetEntry((size_t) index); + _states[index] = Deleted; + _size--; + _deleted++; + if (_size == 0) { + memset(_states, Empty, _capacity); + _deleted = 0; + } + return true; + } + + Entries getEntries() { + return Entries(*this); + } + + private: + Entry *_entries; + unsigned char *_states; + size_t _capacity; + size_t _size; + size_t _deleted; + Hash _hash; + Equals _equals; + + static size_t mix(size_t h) { + h ^= h >> 16; + h *= (size_t) 0x7feb352d; + h ^= h >> 15; + h *= (size_t) 0x846ca68b; + h ^= h >> 16; + return h; + } + + static size_t nextPowerOfTwo(size_t value) { + size_t result = 8; + while (result < value) result <<= 1; + return result; + } + + static size_t capacityFor(size_t expectedSize) { + if (expectedSize < 6) return 8; + return nextPowerOfTwo((expectedSize * 4 + 2) / 3); + } + + void ensureLoadForOneMore() { + if (_capacity == 0) { + rehash(8); + return; + } + if ((_size + _deleted + 1) * 4 > _capacity * 3) { + size_t newCapacity = _deleted > _size ? _capacity : _capacity << 1; + rehash(newCapacity); + } + } + + int findIndex(const K &key) const { + if (_capacity == 0) return -1; + size_t mask = _capacity - 1; + size_t index = mix(_hash(key)) & mask; + while (true) { + unsigned char state = _states[index]; + if (state == Empty) return -1; + if (state == Occupied && _equals(_entries[index].key, key)) return (int) index; + index = (index + 1) & mask; + } + } + + /// Returns an index containing key, an empty slot, or the first deleted slot encountered. + size_t findSlot(const K &key, bool &found) const { + size_t mask = _capacity - 1; + size_t index = mix(_hash(key)) & mask; + size_t firstDeleted = (size_t) -1; + while (true) { + unsigned char state = _states[index]; + if (state == Empty) { + found = false; + return firstDeleted != (size_t) -1 ? firstDeleted : index; + } + if (state == Deleted) { + if (firstDeleted == (size_t) -1) firstDeleted = index; + } else if (_equals(_entries[index].key, key)) { + found = true; + return index; + } + index = (index + 1) & mask; + } + } + + void rehash(size_t newCapacity) { + newCapacity = nextPowerOfTwo(newCapacity); + Entry *oldEntries = _entries; + unsigned char *oldStates = _states; + size_t oldCapacity = _capacity; + + _entries = SpineExtension::alloc(newCapacity, __FILE__, __LINE__); + _states = SpineExtension::calloc(newCapacity, __FILE__, __LINE__); + assert(_entries); + assert(_states); + _capacity = newCapacity; + _size = 0; + _deleted = 0; + for (size_t i = 0; i < _capacity; i++) new (_entries + i) Entry(); + + if (oldEntries) { + for (size_t i = 0; i < oldCapacity; i++) { + if (oldStates[i] == Occupied) put(oldEntries[i].key, oldEntries[i].value); + oldEntries[i].~Entry(); + } + SpineExtension::free(oldEntries, __FILE__, __LINE__); + SpineExtension::free(oldStates, __FILE__, __LINE__); + } + } + + void resetEntry(size_t index) { + _entries[index].key = K(); + _entries[index].value = V(); + } + }; +} + +#endif /* Spine_Map_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/MathUtil.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/MathUtil.h new file mode 100644 index 0000000..7b1da26 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/MathUtil.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MathUtil_h +#define Spine_MathUtil_h + +#include + +#include +// Needed for older MSVC versions +#undef min +#undef max + +namespace spine { + + class SP_API MathUtil : public SpineObject { + private: + MathUtil(); + + public: + static const float Epsilon; + static const float EpsilonSq; + static const float Pi; + static const float Pi_2; + static const float InvPi_2; + static const float Deg_Rad; + static const float Rad_Deg; + + template + static inline T min(T a, T b) { + return a < b ? a : b; + } + + template + static inline T max(T a, T b) { + return a > b ? a : b; + } + + static float sign(float val); + + static float clamp(float x, float lower, float upper); + + static float abs(float v); + + /// Returns the sine in radians from a lookup table. + static float sin(float radians); + + /// Returns the cosine in radians from a lookup table. + static float cos(float radians); + + /// Returns the sine in radians from a lookup table. + static float sinDeg(float degrees); + + /// Returns the cosine in radians from a lookup table. + static float cosDeg(float degrees); + + /// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 + /// degrees), largest error of 0.00488 radians (0.2796 degrees). + static float atan2(float y, float x); + + static float atan2Deg(float x, float y); + + static float acos(float v); + + static float sqrt(float v); + + static float fmod(float a, float b); + + static bool isNan(float v); + + static float quietNan(); + + static float random(); + + static float randomTriangular(float min, float max); + + static float randomTriangular(float min, float max, float mode); + + static float pow(float a, float b); + + static float ceil(float v); + }; +} + +#endif /* Spine_MathUtil_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/MeshAttachment.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/MeshAttachment.h new file mode 100644 index 0000000..466982f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/MeshAttachment.h @@ -0,0 +1,116 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MeshAttachment_h +#define Spine_MeshAttachment_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + /// Attachment that displays a texture region using a mesh. + class SP_API MeshAttachment : public VertexAttachment { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class AtlasAttachmentLoader; + + RTTI_DECL + + public: + explicit MeshAttachment(const String &name, Sequence *sequence); + + virtual ~MeshAttachment(); + + using VertexAttachment::computeWorldVertices; + + virtual void computeWorldVertices(Skeleton &skeleton, Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride = 2) override; + + Array &getRegionUVs(); + void setRegionUVs(Array &inValue); + + Array &getTriangles(); + void setTriangles(Array &inValue); + + int getHullLength(); + void setHullLength(int inValue); + + Sequence &getSequence(); + + void updateSequence(); + + const String &getPath(); + void setPath(const String &inValue); + + Color &getColor(); + + /// The source mesh if this is a linked mesh, else NULL. A linked mesh shares the bones, vertices, regionUVs, + /// triangles, hullLength, edges, width, and height with the source mesh, but may have a different name or path, + /// and therefore a different texture region. + MeshAttachment *getSourceMesh(); + void setSourceMesh(MeshAttachment *inValue); + + /// Vertex index pairs describing edges for controlling triangulation, or empty if nonessential data was not + /// exported. Mesh triangles do not cross edges. Triangulation is not performed at runtime. + Array &getEdges(); + void setEdges(Array &inValue); + + float getWidth(); + void setWidth(float inValue); + + float getHeight(); + void setHeight(float inValue); + + virtual Attachment ©() override; + + MeshAttachment &newLinkedMesh(); + + /// Computes UVs for a mesh attachment. + /// @param uvs Output array for the computed UVs, same length as regionUVs. + static void computeUVs(TextureRegion *region, Array ®ionUVs, Array &uvs); + + private: + Sequence *_sequence; + Array _regionUVs; + Array _triangles; + int _hullLength; + String _path; + Color _color; + MeshAttachment *_sourceMesh; + + Array _edges; + float _width, _height; + }; +} + +#endif /* Spine_MeshAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathAttachment.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathAttachment.h new file mode 100644 index 0000000..f70f82e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathAttachment.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathAttachment_h +#define Spine_PathAttachment_h + +#include +#include + +namespace spine { + class SP_API PathAttachment : public VertexAttachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathAttachment(const String &name); + + /// The length in the setup pose from the start of the path to the end of each curve. + Array &getLengths(); + + void setLengths(Array &inValue); + + bool getClosed(); + + void setClosed(bool inValue); + + /// If true, additional calculations are performed to make computing positions along the path more accurate so + /// movement along the path has a constant speed. + bool getConstantSpeed(); + + void setConstantSpeed(bool inValue); + + Color &getColor(); + + virtual Attachment ©() override; + + private: + Array _lengths; + bool _closed; + bool _constantSpeed; + Color _color; + }; +} + +#endif /* Spine_PathAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraint.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraint.h new file mode 100644 index 0000000..73281d4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraint.h @@ -0,0 +1,118 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraint_h +#define Spine_PathConstraint_h + +#include +#include +#include +#include +#include + +namespace spine { + class Skeleton; + class PathAttachment; + class BonePose; + class Slot; + class Bone; + class Skin; + class Attachment; + + /// Adjusts the rotation, translation, and scale of the constrained bones so they follow a PathAttachment. + /// + /// See https://esotericsoftware.com/spine-path-constraints Path constraints in the Spine User Guide. + // Non-exported base class that inherits from the template + class PathConstraintBase : public ConstraintGeneric { + public: + PathConstraintBase(PathConstraintData &data) : ConstraintGeneric(data) { + } + }; + + class SP_API PathConstraint : public PathConstraintBase { + friend class Skeleton; + friend class PathConstraintMixTimeline; + friend class PathConstraintPositionTimeline; + friend class PathConstraintPositionTimeline; + friend class PathConstraintSpacingTimeline; + + RTTI_DECL + + public: + static const float epsilon; + static const int NONE; + static const int BEFORE; + static const int AFTER; + + PathConstraint(PathConstraintData &data, Skeleton &skeleton); + + PathConstraint ©(Skeleton &skeleton); + + /// Applies the constraint to the constrained bones. + virtual void update(Skeleton &skeleton, Physics physics) override; + + virtual void sort(Skeleton &skeleton) override; + + virtual bool isSourceActive() override; + + /// The bones that will be modified by this path constraint. + Array &getBones(); + + /// The slot whose path attachment will be used to constrained the bones. + Slot &getSlot(); + + void setSlot(Slot &slot); + + private: + Array _bones; + Slot *_slot; + + Array _spaces; + Array _positions; + Array _world; + Array _curves; + Array _lengths; + Array _segments; + + Array &computeWorldPositions(Skeleton &skeleton, PathAttachment &path, int spacesCount, bool tangents); + + void addBeforePosition(float p, Array &temp, int i, Array &output, int o); + + void addAfterPosition(float p, Array &temp, int i, Array &output, int o); + + void addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, Array &output, + int o, bool tangents); + + void sortPathSlot(Skeleton &skeleton, Skin &skin, int slotIndex, Bone &slotBone); + + void sortPath(Skeleton &skeleton, Attachment *attachment, Bone &slotBone); + }; +} + +#endif /* Spine_PathConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintData.h new file mode 100644 index 0000000..008c4bf --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintData.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintData_h +#define Spine_PathConstraintData_h + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spine { + class BoneData; + class SlotData; + class PathConstraint; + class Skeleton; + + /// Stores the setup pose for a PathConstraint. + /// + /// See https://esotericsoftware.com/spine-path-constraints Path constraints in the Spine User Guide. + class SP_API PathConstraintData : public ConstraintDataGeneric { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class PathConstraint; + + friend class Skeleton; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + RTTI_DECL + public: + explicit PathConstraintData(const String &name); + + virtual Constraint &create(Skeleton &skeleton) override; + + + /// The bones that will be modified by this path constraint. + Array &getBones(); + + /// The slot whose path attachment will be used to constrained the bones. + SlotData &getSlot(); + + void setSlot(SlotData &slot); + + /// The mode for positioning the first bone on the path. + PositionMode getPositionMode(); + + void setPositionMode(PositionMode positionMode); + + /// The mode for positioning the bones after the first bone on the path. + SpacingMode getSpacingMode(); + + void setSpacingMode(SpacingMode spacingMode); + + /// The mode for adjusting the rotation of the bones. + RotateMode getRotateMode(); + + void setRotateMode(RotateMode rotateMode); + + /// An offset added to the constrained bone rotation. + float getOffsetRotation(); + + void setOffsetRotation(float offsetRotation); + + private: + Array _bones; + SlotData *_slot; + PositionMode _positionMode; + SpacingMode _spacingMode; + RotateMode _rotateMode; + float _offsetRotation; + }; +} + +#endif /* Spine_PathConstraintData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintMixTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintMixTimeline.h new file mode 100644 index 0000000..65eca77 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -0,0 +1,77 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintMixTimeline_h +#define Spine_PathConstraintMixTimeline_h + +#include +#include + +namespace spine { + + /// Changes a path constraint's rotate, x, and y mix values. + class SP_API PathConstraintMixTimeline : public CurveTimeline, public ConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathConstraintMixTimeline(size_t frameCount, size_t bezierCount, int constraintIndex); + + virtual ~PathConstraintMixTimeline(); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + /// Sets the time and color for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + /// @param time The frame time in seconds. + void setFrame(int frame, float time, float mixRotate, float mixX, float mixY); + + virtual int getConstraintIndex() const override { + return _constraintIndex; + } + + virtual void setConstraintIndex(int inValue) override { + _constraintIndex = inValue; + } + + private: + int _constraintIndex; + + static const int ENTRIES = 4; + static const int ROTATE = 1; + static const int X = 2; + static const int Y = 3; + }; +} + +#endif /* Spine_PathConstraintMixTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintPose.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintPose.h new file mode 100644 index 0000000..7ced819 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintPose.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintPose_h +#define Spine_PathConstraintPose_h + +#include +#include + +namespace spine { + /// Stores a pose for a path constraint. + class SP_API PathConstraintPose : public Pose { + friend class PathConstraint; + friend class PathConstraintPositionTimeline; + friend class PathConstraintSpacingTimeline; + friend class PathConstraintMixTimeline; + friend class SkeletonJson; + friend class SkeletonBinary; + + private: + float _position; + float _spacing; + float _mixRotate; + float _mixX; + float _mixY; + + public: + PathConstraintPose(); + virtual ~PathConstraintPose(); + + virtual void set(PathConstraintPose &pose) override; + + /// The position along the path. + float getPosition(); + void setPosition(float position); + + /// The spacing between bones. + float getSpacing(); + void setSpacing(float spacing); + + /// A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. + float getMixRotate(); + void setMixRotate(float mixRotate); + + /// A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. + float getMixX(); + void setMixX(float mixX); + + /// A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. + float getMixY(); + void setMixY(float mixY); + }; +} + +#endif \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintPositionTimeline.h new file mode 100644 index 0000000..303380f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintPositionTimeline_h +#define Spine_PathConstraintPositionTimeline_h + +#include + +namespace spine { + + /// Changes a path constraint's position. + class SP_API PathConstraintPositionTimeline : public ConstraintTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + static const int ENTRIES; + + explicit PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, int constraintIndex); + + virtual ~PathConstraintPositionTimeline(); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + }; +}// namespace spine + +#endif /* Spine_PathConstraintPositionTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintSpacingTimeline.h new file mode 100644 index 0000000..c38229b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintSpacingTimeline_h +#define Spine_PathConstraintSpacingTimeline_h + +#include + +namespace spine { + /// Changes a path constraint's spacing. + class SP_API PathConstraintSpacingTimeline : public ConstraintTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PathConstraintSpacingTimeline(size_t frameCount, size_t bezierCount, int constraintIndex); + + virtual ~PathConstraintSpacingTimeline(); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + }; +} + +#endif /* Spine_PathConstraintSpacingTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Physics.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Physics.h new file mode 100644 index 0000000..ccfb04c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Physics.h @@ -0,0 +1,50 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Physics_h +#define Spine_Physics_h + +namespace spine { + /// Determines how physics and other non-deterministic updates are applied. + enum Physics { + /// Physics are not updated or applied. + Physics_None, + + /// Physics are reset via PhysicsConstraint::reset(). + Physics_Reset, + + /// Physics are updated and the pose from physics is applied. + Physics_Update, + + /// Physics are not updated but the pose from physics is applied. + Physics_Pose + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PhysicsConstraint.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PhysicsConstraint.h new file mode 100644 index 0000000..2767c32 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PhysicsConstraint.h @@ -0,0 +1,104 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PhysicsConstraint_h +#define Spine_PhysicsConstraint_h + +#include +#include +#include +#include +#include + +namespace spine { + class Skeleton; + class BonePose; + class PhysicsConstraintPose; + + /// Applies physics to a bone. + /// + /// See https://esotericsoftware.com/spine-physics-constraints Physics constraints in the Spine User Guide. + // Non-exported base class that inherits from the template + class PhysicsConstraintBase : public ConstraintGeneric { + public: + PhysicsConstraintBase(PhysicsConstraintData &data) + : ConstraintGeneric(data) { + } + }; + + class SP_API PhysicsConstraint : public PhysicsConstraintBase { + friend class Skeleton; + friend class PhysicsConstraintTimeline; + friend class PhysicsConstraintInertiaTimeline; + friend class PhysicsConstraintStrengthTimeline; + friend class PhysicsConstraintDampingTimeline; + friend class PhysicsConstraintMassTimeline; + friend class PhysicsConstraintWindTimeline; + friend class PhysicsConstraintGravityTimeline; + friend class PhysicsConstraintMixTimeline; + friend class PhysicsConstraintResetTimeline; + + public: + RTTI_DECL + + PhysicsConstraint(PhysicsConstraintData &data, Skeleton &skeleton); + + void update(Skeleton &skeleton, Physics physics) override; + void sort(Skeleton &skeleton) override; + bool isSourceActive() override; + PhysicsConstraint ©(Skeleton &skeleton); + + /// Resets all physics state that was the result of previous movement. Use this after moving a bone to prevent physics + /// from reacting to the movement. + void reset(Skeleton &skeleton); + + /// Translates the physics constraint so the next update() forces are applied as if the bone moved an additional amount in world space. + void translate(float x, float y); + + /// Rotates the physics constraint so the next update() forces are applied as if the bone rotated around the specified point in world space. + void rotate(float x, float y, float degrees); + + /// The bone constrained by this physics constraint. + BonePose &getBone(); + void setBone(BonePose &bone); + + private: + BonePose *_bone; + + bool _reset; + float _ux, _uy, _cx, _cy, _tx, _ty; + float _xOffset, _xLag, _xVelocity; + float _yOffset, _yLag, _yVelocity; + float _rotateOffset, _rotateLag, _rotateVelocity; + float _scaleOffset, _scaleLag, _scaleVelocity; + float _remaining, _lastTime; + }; +} + +#endif /* Spine_PhysicsConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PhysicsConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PhysicsConstraintData.h new file mode 100644 index 0000000..298965f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PhysicsConstraintData.h @@ -0,0 +1,128 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PhysicsConstraintData_h +#define Spine_PhysicsConstraintData_h + +#include +#include +#include + +namespace spine { + class BoneData; + class PhysicsConstraint; + + /// Stores the setup pose for a PhysicsConstraint. + /// + /// See https://esotericsoftware.com/spine-physics-constraints Physics constraints in the Spine User Guide. + class SP_API PhysicsConstraintData : public ConstraintDataGeneric { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class PhysicsConstraint; + friend class Skeleton; + + RTTI_DECL + public: + explicit PhysicsConstraintData(const String &name); + + virtual Constraint &create(Skeleton &skeleton) override; + + /// The bone constrained by this physics constraint. + BoneData &getBone(); + void setBone(BoneData &bone); + + /// The time in milliseconds required to advanced the physics simulation one step. + float getStep(); + void setStep(float step); + + /// Physics influence on x translation, 0-1. + float getX(); + void setX(float x); + + /// Physics influence on y translation, 0-1. + float getY(); + void setY(float y); + + /// Physics influence on rotation, 0-1. + float getRotate(); + void setRotate(float rotate); + + /// Physics influence on scaleX, 0-1. + float getScaleX(); + void setScaleX(float scaleX); + + /// Physics influence on shearX, 0-1. + float getShearX(); + void setShearX(float shearX); + + /// Movement greater than the limit will not have a greater affect on physics. + float getLimit(); + void setLimit(float limit); + + /// Determines how BonePose::getScaleY() changes when getScaleX() sets BonePose::getScaleX(). + ScaleYMode getScaleYMode(); + void setScaleYMode(ScaleYMode scaleYMode); + + /// True when this constraint's inertia is controlled by global slider timelines. + bool getInertiaGlobal(); + void setInertiaGlobal(bool inertiaGlobal); + + /// True when this constraint's strength is controlled by global slider timelines. + bool getStrengthGlobal(); + void setStrengthGlobal(bool strengthGlobal); + + /// True when this constraint's damping is controlled by global slider timelines. + bool getDampingGlobal(); + void setDampingGlobal(bool dampingGlobal); + + /// True when this constraint's mass is controlled by global slider timelines. + bool getMassGlobal(); + void setMassGlobal(bool massGlobal); + + /// True when this constraint's wind is controlled by global slider timelines. + bool getWindGlobal(); + void setWindGlobal(bool windGlobal); + + /// True when this constraint's gravity is controlled by global slider timelines. + bool getGravityGlobal(); + void setGravityGlobal(bool gravityGlobal); + + /// True when this constraint's mix is controlled by global slider timelines. + bool getMixGlobal(); + void setMixGlobal(bool mixGlobal); + + private: + BoneData *_bone; + float _x, _y, _rotate, _scaleX, _shearX, _limit, _step; + ScaleYMode _scaleYMode; + bool _inertiaGlobal, _strengthGlobal, _dampingGlobal, _massGlobal, _windGlobal, _gravityGlobal, _mixGlobal; + }; +} + +#endif /* Spine_PhysicsConstraintData_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PhysicsConstraintPose.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PhysicsConstraintPose.h new file mode 100644 index 0000000..d2814d2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PhysicsConstraintPose.h @@ -0,0 +1,89 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PhysicsConstraintPose_h +#define Spine_PhysicsConstraintPose_h + +#include +#include + +namespace spine { + /// Stores a pose for a physics constraint. + class SP_API PhysicsConstraintPose : public Pose { + friend class PhysicsConstraint; + friend class PhysicsConstraintTimeline; + friend class SkeletonJson; + friend class SkeletonBinary; + + private: + float _inertia; + float _strength; + float _damping; + float _massInverse; + float _wind; + float _gravity; + float _mix; + + public: + PhysicsConstraintPose(); + virtual ~PhysicsConstraintPose(); + + virtual void set(PhysicsConstraintPose &pose) override; + + /// Controls how much bone movement is converted into physics movement. + float getInertia(); + void setInertia(float inertia); + + /// The amount of force used to return properties to the unconstrained value. + float getStrength(); + void setStrength(float strength); + + /// Reduces the speed of physics movements, with more of a reduction at higher speeds. + float getDamping(); + void setDamping(float damping); + + /// Determines susceptibility to acceleration. + float getMassInverse(); + void setMassInverse(float massInverse); + + /// Applies a constant force along the Skeleton::getWindX(), Skeleton::getWindY() vector. + float getWind(); + void setWind(float wind); + + /// Applies a constant force along the Skeleton::getGravityX(), Skeleton::getGravityY() vector. + float getGravity(); + void setGravity(float gravity); + + /// A percentage (0+) that controls the mix between the constrained and unconstrained poses. + float getMix(); + void setMix(float mix); + }; +} + +#endif \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PhysicsConstraintTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PhysicsConstraintTimeline.h new file mode 100644 index 0000000..b699bb6 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PhysicsConstraintTimeline.h @@ -0,0 +1,300 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PhysicsConstraintTimeline_h +#define Spine_PhysicsConstraintTimeline_h + +#include +#include +#include +#include +#include + +namespace spine { + + /// The base class for most PhysicsConstraint timelines. + class SP_API PhysicsConstraintTimeline : public CurveTimeline1, public ConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + /// @param constraintIndex -1 for all physics constraints in the skeleton. + explicit PhysicsConstraintTimeline(size_t frameCount, size_t bezierCount, int constraintIndex, Property property); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + virtual int getConstraintIndex() const override { + return _constraintIndex; + } + + virtual void setConstraintIndex(int inValue) override { + _constraintIndex = inValue; + } + + protected: + virtual float get(PhysicsConstraintPose &pose) = 0; + virtual void set(PhysicsConstraintPose &pose, float value) = 0; + virtual bool global(PhysicsConstraintData &constraintData) = 0; + + int _constraintIndex; + }; + + /// Changes a physics constraint's inertia. + class SP_API PhysicsConstraintInertiaTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintInertiaTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex) + : PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintInertia) {}; + + protected: + float get(PhysicsConstraintPose &pose) override { + return pose.getInertia(); + } + + void set(PhysicsConstraintPose &pose, float value) override { + pose.setInertia(value); + } + + bool global(PhysicsConstraintData &constraintData) override { + return constraintData.getInertiaGlobal(); + } + }; + + /// Changes a physics constraint's strength. + class SP_API PhysicsConstraintStrengthTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintStrengthTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex) + : PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintStrength) {}; + + protected: + float get(PhysicsConstraintPose &pose) override { + return pose.getStrength(); + } + + void set(PhysicsConstraintPose &pose, float value) override { + pose.setStrength(value); + } + + bool global(PhysicsConstraintData &constraintData) override { + return constraintData.getStrengthGlobal(); + } + }; + + /// Changes a physics constraint's damping. + class SP_API PhysicsConstraintDampingTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintDampingTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex) + : PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintDamping) {}; + + protected: + float get(PhysicsConstraintPose &pose) override { + return pose.getDamping(); + } + + void set(PhysicsConstraintPose &pose, float value) override { + pose.setDamping(value); + } + + bool global(PhysicsConstraintData &constraintData) override { + return constraintData.getDampingGlobal(); + } + }; + + /// Changes a physics constraint's mass inverse. The timeline values are not inverted. + class SP_API PhysicsConstraintMassTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintMassTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex) + : PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintMass) {}; + + protected: + float get(PhysicsConstraintPose &pose) override { + return 1 / pose.getMassInverse(); + } + + void set(PhysicsConstraintPose &pose, float value) override { + pose.setMassInverse(1 / value); + } + + bool global(PhysicsConstraintData &constraintData) override { + return constraintData.getMassGlobal(); + } + }; + + /// Changes a physics constraint's wind. + class SP_API PhysicsConstraintWindTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintWindTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex) + : PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintWind) { + _additive = true; + }; + + protected: + float get(PhysicsConstraintPose &pose) override { + return pose.getWind(); + } + + void set(PhysicsConstraintPose &pose, float value) override { + pose.setWind(value); + } + + bool global(PhysicsConstraintData &constraintData) override { + return constraintData.getWindGlobal(); + } + }; + + /// Changes a physics constraint's gravity. + class SP_API PhysicsConstraintGravityTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintGravityTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex) + : PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintGravity) { + _additive = true; + }; + + protected: + float get(PhysicsConstraintPose &pose) override { + return pose.getGravity(); + } + + void set(PhysicsConstraintPose &pose, float value) override { + pose.setGravity(value); + } + + bool global(PhysicsConstraintData &constraintData) override { + return constraintData.getGravityGlobal(); + } + }; + + /// Changes a physics constraint's mix. + class SP_API PhysicsConstraintMixTimeline : public PhysicsConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PhysicsConstraintMixTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex) + : PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintMix) {}; + + protected: + float get(PhysicsConstraintPose &pose) override { + return pose.getMix(); + } + + void set(PhysicsConstraintPose &pose, float value) override { + pose.setMix(value); + } + + bool global(PhysicsConstraintData &constraintData) override { + return constraintData.getMixGlobal(); + } + }; + + /// Resets a physics constraint when specific animation times are reached. + class SP_API PhysicsConstraintResetTimeline : public Timeline, public ConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + /// @param constraintIndex -1 for all physics constraints in the skeleton. + explicit PhysicsConstraintResetTimeline(size_t frameCount, int constraintIndex) + : Timeline(frameCount, 1), ConstraintTimeline(), _constraintIndex(constraintIndex) { + PropertyId ids[] = {((PropertyId) Property_PhysicsConstraintReset) << 32}; + setPropertyIds(ids, 1); + _instant = true; + } + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + int getFrameCount() { + return (int) _frames.size(); + } + + virtual int getConstraintIndex() const override { + return _constraintIndex; + } + + virtual void setConstraintIndex(int inValue) override { + _constraintIndex = inValue; + } + + /// Sets the time for the specified frame. + void setFrame(int frame, float time) { + _frames[frame] = time; + } + + private: + int _constraintIndex; + }; +}// namespace spine + +#endif /* Spine_PhysicsConstraintTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PointAttachment.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PointAttachment.h new file mode 100644 index 0000000..41eb112 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PointAttachment.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PointAttachment_h +#define Spine_PointAttachment_h + +#include +#include + +namespace spine { + class Bone; + class BonePose; + + /// An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be + /// used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a + /// skin. + /// + /// See https://esotericsoftware.com/spine-points for Point Attachments in the Spine User Guide. + /// + class SP_API PointAttachment : public Attachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit PointAttachment(const String &name); + + /// The local x position. + float getX(); + + void setX(float inValue); + + /// The local y position. + float getY(); + + void setY(float inValue); + + /// The local rotation in degrees, counter clockwise. + float getRotation(); + + void setRotation(float inValue); + + Color &getColor(); + + /// Computes the world position from the local position. + void computeWorldPosition(BonePose &bone, float &ox, float &oy); + + /// Computes the world rotation from the local rotation. + float computeWorldRotation(BonePose &bone); + + virtual Attachment ©() override; + + private: + float _x, _y, _rotation; + Color _color; + }; +} + +#endif /* Spine_PointAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Pool.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Pool.h new file mode 100644 index 0000000..53d0951 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Pool.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Pool_h +#define Spine_Pool_h + +#include +#include +#include +#include + +namespace spine { + template + class SP_API Pool : public SpineObject { + public: + Pool() { + } + + ~Pool() { + ArrayUtils::deleteElements(_objects); + } + + T *obtain() { + if (_objects.size() > 0) { + T **object = &_objects[_objects.size() - 1]; + T *ret = *object; + _objects.removeAt(_objects.size() - 1); + + return ret; + } else { + T *ret = new (__FILE__, __LINE__) T(); + + return ret; + } + } + + void free(T *object) { + if (!_objects.contains(object)) { + _objects.add(object); + } + } + + private: + Array _objects; + }; +} + +#endif /* Spine_Pool_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Pose.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Pose.h new file mode 100644 index 0000000..35938c8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Pose.h @@ -0,0 +1,48 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Pose_h +#define Spine_Pose_h + +#include + +namespace spine { + /// An interface for an object representing a pose. + template + class SP_API Pose : public SpineObject { + public: + Pose() {}; + virtual ~Pose() {}; + + /// Sets this pose to the specified pose. + virtual void set(P &pose) = 0; + }; +} + +#endif \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Posed.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Posed.h new file mode 100644 index 0000000..919914d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Posed.h @@ -0,0 +1,148 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Posed_h +#define Spine_Posed_h + +#include + +namespace spine { + /// Base interface for posed objects. + class SP_API Posed { + public: + Posed() { + } + virtual ~Posed() { + } + + virtual void constrained() = 0; + + virtual void resetConstrained() = 0; + + virtual bool isPoseEqualToApplied() = 0; + + protected: + virtual void setupPose() = 0; + + virtual void unconstrained() = 0; + }; + + /// The base class for an object with a number of poses: + /// - getData(): The setup pose data. + /// - getPose(): The unconstrained pose. Set by animations and application code. + /// - getAppliedPose(): The pose to use for rendering. Possibly modified by constraints. + template + class PosedGeneric : public Posed, public SpineObject { + friend class AnimationState; + friend class BoneTimeline1; + friend class BoneTimeline2; + friend class RotateTimeline; + friend class IkConstraint; + friend class TransformConstraint; + friend class VertexAttachment; + friend class PathConstraint; + friend class PhysicsConstraint; + friend class Skeleton; + friend class RegionAttachment; + friend class PointAttachment; + friend class AttachmentTimeline; + friend class RGBATimeline; + friend class RGBTimeline; + friend class AlphaTimeline; + friend class RGBA2Timeline; + friend class RGB2Timeline; + friend class ScaleTimeline; + friend class ScaleXTimeline; + friend class ScaleYTimeline; + friend class ShearTimeline; + friend class ShearXTimeline; + friend class ShearYTimeline; + friend class TranslateTimeline; + friend class TranslateXTimeline; + friend class TranslateYTimeline; + friend class InheritTimeline; + friend class Skeleton; + + public: + PosedGeneric(D &data) : _data(data), _pose(), _constrainedPose(), _appliedPose(&_pose) { + setupPose(); + } + + virtual ~PosedGeneric() { + } + + /// The setup pose data. May be shared with multiple instances. + D &getData() { + return _data; + } + + /// The unconstrained pose for this object, set by animations and application code. + P &getPose() { + return _pose; + } + + /// The pose to use for rendering. If no constraints modify this pose, this is the same as getPose(). Otherwise it is a + /// copy of getPose() modified by constraints. + A &getAppliedPose() { + return *_appliedPose; + } + + /// Sets the constrained pose to the unconstrained pose, as a starting point for constraints to be applied. + virtual void resetConstrained() override { + _constrainedPose.set(_pose); + } + + /// Sets the applied pose to the constrained pose, in anticipation of the applied pose being modified by constraints. + virtual void constrained() override { + _appliedPose = &_constrainedPose; + } + + virtual bool isPoseEqualToApplied() override { + return _appliedPose == &_pose; + } + + protected: + /// Sets the applied pose to the unconstrained pose, for when no constraints will modify the pose. + virtual void unconstrained() override { + _appliedPose = &_pose; + } + /// Sets the unconstrained pose to the setup pose. + virtual void setupPose() override { + _pose.set(_data.getSetupPose()); + } + + protected: + D &_data; + A _pose; ///< Stored as A type (concrete pose type) to match Java behavior + A _constrainedPose;///< Stored as A type (concrete pose type) to match Java behavior + A *_appliedPose; ///< Points to either _pose or _constrainedPose, reassignable like Java + }; +}// namespace spine + +#endif /* Spine_Posed_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PosedActive.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PosedActive.h new file mode 100644 index 0000000..6ccefaf --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PosedActive.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PosedActive_h +#define Spine_PosedActive_h + +#include + +namespace spine { + /// A posed object that may be active or inactive. + class SP_API PosedActive { + protected: + bool _active; + + public: + PosedActive() : _active(true) { + } + virtual ~PosedActive() { + } + + /// Returns false when this won't be updated by Skeleton::updateWorldTransform(Physics) because a skin is + /// required and the active skin does not contain this item. See Skin::getBones(), Skin::getConstraints(), + /// PosedData::getSkinRequired(), and Skeleton::updateCache(). + bool isActive() const { + return _active; + } + void setActive(bool active) { + _active = active; + } + }; +} + +#endif /* Spine_PosedActive_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PosedData.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PosedData.h new file mode 100644 index 0000000..97bdc7f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PosedData.h @@ -0,0 +1,146 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PosedData_h +#define Spine_PosedData_h + +#include +#include + +namespace spine { + template + class Pose; + + class SP_API PosedData : public SpineObject { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class BoneTimeline1; + friend class BoneTimeline2; + friend class RotateTimeline; + friend class AttachmentTimeline; + friend class RGBATimeline; + friend class RGBTimeline; + friend class AlphaTimeline; + friend class RGBA2Timeline; + friend class RGB2Timeline; + friend class ScaleTimeline; + friend class ScaleXTimeline; + friend class ScaleYTimeline; + friend class ShearTimeline; + friend class ShearXTimeline; + friend class ShearYTimeline; + friend class TranslateTimeline; + friend class TranslateXTimeline; + friend class TranslateYTimeline; + friend class InheritTimeline; + friend class Skeleton; + friend class Slot; + + public: + PosedData(const String &name); + virtual ~PosedData(); + + const String &getName() const { + return _name; + }; + + /// When true, Skeleton::updateWorldTransform(Physics) only updates this constraint if the Skeleton::getSkin() + /// contains this constraint. + /// + /// See Skin::getConstraints(). + bool getSkinRequired() const { + return _skinRequired; + }; + void setSkinRequired(bool skinRequired) { + _skinRequired = skinRequired; + }; + + protected: + String _name; + bool _skinRequired; + }; + + inline PosedData::PosedData(const String &name) : _name(name), _skinRequired(false) { + } + + inline PosedData::~PosedData() { + } + + /// The base class for storing setup data for a posed object. May be shared with multiple instances. + template + class PosedDataGeneric : public PosedData { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class BoneTimeline1; + friend class BoneTimeline2; + friend class RotateTimeline; + friend class AttachmentTimeline; + friend class RGBATimeline; + friend class RGBTimeline; + friend class AlphaTimeline; + friend class RGBA2Timeline; + friend class RGB2Timeline; + friend class ScaleTimeline; + friend class ScaleXTimeline; + friend class ScaleYTimeline; + friend class ShearTimeline; + friend class ShearXTimeline; + friend class ShearYTimeline; + friend class TranslateTimeline; + friend class TranslateXTimeline; + friend class TranslateYTimeline; + friend class InheritTimeline; + friend class PhysicsConstraintTimeline; + friend class PhysicsConstraintInertiaTimeline; + friend class PhysicsConstraintStrengthTimeline; + friend class PhysicsConstraintDampingTimeline; + friend class PhysicsConstraintMassTimeline; + friend class PhysicsConstraintWindTimeline; + friend class PhysicsConstraintGravityTimeline; + friend class Slot; + + protected: + P _setupPose; + + public: + PosedDataGeneric(const String &name) : PosedData(name), _setupPose() { + } + virtual ~PosedDataGeneric() {}; + + /// The setup pose that most animations are relative to. + P &getSetupPose() { + return _setupPose; + }; + const P &getSetupPose() const { + return _setupPose; + }; + }; +} + +#endif \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PositionMode.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PositionMode.h new file mode 100644 index 0000000..5736607 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/PositionMode.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PositionMode_h +#define Spine_PositionMode_h + +#include + +namespace spine { + /// Controls how the first bone is positioned along the path. + /// + /// @see https://esotericsoftware.com/spine-path-constraints#Position-mode Position mode in the Spine User Guide. + enum PositionMode { + PositionMode_Fixed = 0, + PositionMode_Percent + }; + + inline PositionMode PositionMode_valueOf(const char *value) { + if (strcmp(value, "fixed") == 0) + return PositionMode_Fixed; + else if (strcmp(value, "percent") == 0) + return PositionMode_Percent; + else + return PositionMode_Percent;// default + } +} + +#endif /* Spine_PositionMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Property.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Property.h new file mode 100644 index 0000000..030e27e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Property.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Property_h +#define Spine_Property_h + +namespace spine { + typedef long long PropertyId; + enum Property { + Property_Rotate = 0, + Property_X, + Property_Y, + Property_ScaleX, + Property_ScaleY, + Property_ShearX, + Property_ShearY, + Property_Inherit, + Property_Rgb, + Property_Alpha, + Property_Rgb2, + Property_Attachment, + Property_Deform, + Property_Event, + Property_DrawOrder, + Property_IkConstraint, + Property_TransformConstraint, + Property_PathConstraintPosition, + Property_PathConstraintSpacing, + Property_PathConstraintMix, + Property_PhysicsConstraintInertia, + Property_PhysicsConstraintStrength, + Property_PhysicsConstraintDamping, + Property_PhysicsConstraintMass, + Property_PhysicsConstraintWind, + Property_PhysicsConstraintGravity, + Property_PhysicsConstraintMix, + Property_PhysicsConstraintReset, + Property_Sequence, + Property_SliderTime, + Property_SliderMix, + Property_DrawOrderFolder + }; +} + +#endif /* Spine_Property_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/RTTI.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/RTTI.h new file mode 100644 index 0000000..43cdbe5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/RTTI.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RTTI_h +#define Spine_RTTI_h + +#include + +namespace spine { + class SP_API RTTI { + public: + explicit RTTI(const char *className); + + RTTI(const char *className, const RTTI &baseRTTI); + + // New constructor for multiple interfaces (up to 3) + RTTI(const char *className, const RTTI &baseRTTI, const RTTI *interface1, const RTTI *interface2 = 0, const RTTI *interface3 = 0); + + const char *getClassName() const; + + bool isExactly(const RTTI &rtti) const; + + bool instanceOf(const RTTI &rtti) const; + + private: + // Prevent copying + RTTI(const RTTI &obj); + + RTTI &operator=(const RTTI &obj); + + const char *_className; + const RTTI *_pBaseRTTI; + const RTTI *_interfaces[3];// Support up to 3 interfaces + int _interfaceCount; + }; +} + +#define RTTI_DECL_NOPARENT \ +public: \ + static const RTTI rtti; \ + virtual const RTTI &getRTTI() const; + +#define RTTI_DECL \ +public: \ + static const RTTI rtti; \ + virtual const RTTI &getRTTI() const override; + +#define RTTI_IMPL_NOPARENT(name) \ + const RTTI name::rtti(#name); \ + const RTTI &name::getRTTI() const { \ + return rtti; \ + } + +#define RTTI_IMPL(name, parent) \ + const RTTI name::rtti(#name, parent::rtti); \ + const RTTI &name::getRTTI() const { \ + return rtti; \ + } + +#define RTTI_IMPL_MULTI(name, parent, ...) \ + const RTTI name::rtti(#name, parent::rtti, &__VA_ARGS__::rtti); \ + const RTTI &name::getRTTI() const { \ + return rtti; \ + } + +#endif /* Spine_RTTI_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/RegionAttachment.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/RegionAttachment.h new file mode 100644 index 0000000..3069f46 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/RegionAttachment.h @@ -0,0 +1,126 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RegionAttachment_h +#define Spine_RegionAttachment_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + class Slot; + class SlotPose; + + /// Attachment that displays a texture region. + class SP_API RegionAttachment : public Attachment { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class AtlasAttachmentLoader; + + RTTI_DECL + + public: + explicit RegionAttachment(const String &name, Sequence *sequence); + + virtual ~RegionAttachment(); + + /// Transforms the attachment's four vertices to world coordinates. + /// @param slot The parent slot. + /// @param vertexOffsets The vertex offsets. + /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8. + /// @param offset The worldVertices index to begin writing values. + /// @param stride The number of worldVertices entries between the value pairs written. + void computeWorldVertices(Slot &slot, float *vertexOffsets, float *worldVertices, size_t offset, size_t stride = 2); + + void computeWorldVertices(Slot &slot, Array &vertexOffsets, Array &worldVertices, size_t offset, size_t stride = 2); + + /// Returns the vertex offsets for the specified slot pose. + Array &getOffsets(SlotPose &pose); + + float getX(); + void setX(float inValue); + + float getY(); + void setY(float inValue); + + float getScaleX(); + void setScaleX(float inValue); + + float getScaleY(); + void setScaleY(float inValue); + + /// The local rotation in degrees, counter clockwise. + float getRotation(); + void setRotation(float inValue); + + float getWidth(); + void setWidth(float inValue); + + float getHeight(); + void setHeight(float inValue); + + Sequence &getSequence(); + + void updateSequence(); + + const String &getPath(); + void setPath(const String &inValue); + + Color &getColor(); + + virtual Attachment ©() override; + + /// Computes UVs and offsets for a region attachment. + /// @param uvs Output array for the computed UVs, length of 8. + /// @param offset Output array for the computed vertex offsets, length of 8. + static void computeUVs(TextureRegion *region, float x, float y, float scaleX, float scaleY, float rotation, float width, float height, + Array &offset, Array &uvs); + + private: + static const int BLX; + static const int BLY; + static const int ULX; + static const int ULY; + static const int URX; + static const int URY; + static const int BRX; + static const int BRY; + + Sequence *_sequence; + float _x, _y, _scaleX, _scaleY, _rotation, _width, _height; + String _path; + Color _color; + }; +} + +#endif /* Spine_RegionAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/RotateMode.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/RotateMode.h new file mode 100644 index 0000000..7f9a717 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/RotateMode.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RotateMode_h +#define Spine_RotateMode_h + +#include + +namespace spine { + /// Controls how bones are rotated, translated, and scaled to match the path. + /// + /// @see https://esotericsoftware.com/spine-path-constraints#Rotate-Mix Rotate mode in the Spine User Guide. + enum RotateMode { + RotateMode_Tangent = 0, + RotateMode_Chain, + /// When chain scale, constrained bones should all have the same parent. That way when the path constraint scales a bone, it + /// doesn't affect other constrained bones. + RotateMode_ChainScale + }; + + inline RotateMode RotateMode_valueOf(const char *value) { + if (strcmp(value, "tangent") == 0) + return RotateMode_Tangent; + else if (strcmp(value, "chain") == 0) + return RotateMode_Chain; + else if (strcmp(value, "chainScale") == 0) + return RotateMode_ChainScale; + else + return RotateMode_Tangent;// default + } +} + +#endif /* Spine_RotateMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/RotateTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/RotateTimeline.h new file mode 100644 index 0000000..872130c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/RotateTimeline.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RotateTimeline_h +#define Spine_RotateTimeline_h + +#include + +namespace spine { + /// Changes a bone's local rotation. + class SP_API RotateTimeline : public BoneTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class AnimationState; + + RTTI_DECL + + public: + explicit RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + protected: + virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override; + }; +} + +#endif /* Spine_RotateTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ScaleTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ScaleTimeline.h new file mode 100644 index 0000000..00b962a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ScaleTimeline.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ScaleTimeline_h +#define Spine_ScaleTimeline_h + +#include + +namespace spine { + /// Changes a bone's local scaleX and scaleY. + class SP_API ScaleTimeline : public BoneTimeline2 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + protected: + virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override; + }; + + /// Changes a bone's local scaleX. + class SP_API ScaleXTimeline : public BoneTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + protected: + virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override; + }; + + /// Changes a bone's local scaleY. + class SP_API ScaleYTimeline : public BoneTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + protected: + virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override; + }; +} + +#endif /* Spine_ScaleTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Sequence.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Sequence.h new file mode 100644 index 0000000..adabe3c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Sequence.h @@ -0,0 +1,163 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Sequence_h +#define Spine_Sequence_h + +#include +#include +#include +#include + +namespace spine { + class SlotPose; + class RegionAttachment; + class MeshAttachment; + + class SkeletonBinary; + class SkeletonJson; + + /// Holds texture regions, UVs, and vertex offsets for rendering a region or mesh attachment. + /// Regions must be populated and update() called before use. + class SP_API Sequence : public SpineObject { + friend class SkeletonBinary; + friend class SkeletonJson; + + public: + /// @param count The number of texture regions this sequence will display. + /// @param pathSuffix If true, getPath(String, int) has a numeric suffix. If false, all regions will use the same path, + /// so count should be 1. + Sequence(int count, bool pathSuffix); + + /// Copy constructor. + Sequence(const Sequence &other); + + ~Sequence(); + + /// Computes UVs and offsets for the specified attachment. Must be called if the regions + /// or attachment properties are changed. + void update(RegionAttachment &attachment); + void update(MeshAttachment &attachment); + + /// The list of texture regions this sequence will display. + Array &getRegions() { + return _regions; + } + + /// Returns the getRegions() index for SlotPose::getSequenceIndex(). + int resolveIndex(SlotPose &pose); + + /// Returns the texture region from getRegions() for the specified index. + TextureRegion *getRegion(int index); + + /// Returns the UVs for the specified index. getRegions() must be populated and update() called before calling this method. + Array &getUVs(int index); + + /// Returns vertex offsets from the center of a RegionAttachment. Invalid to call for a MeshAttachment. + Array &getOffsets(int index); + + /// The starting number for the numeric getPath(String, int) suffix. + int getStart() { + return _start; + } + + void setStart(int start) { + _start = start; + } + + /// The minimum number of digits in the numeric getPath(String, int) suffix, for zero padding. 0 for no zero padding. + int getDigits() { + return _digits; + } + + void setDigits(int digits) { + _digits = digits; + } + + /// The index of the region to show for the setup pose. + int getSetupIndex() { + return _setupIndex; + } + + void setSetupIndex(int setupIndex) { + _setupIndex = setupIndex; + } + + /// Returns true if getPath(String, int) has a numeric suffix. + bool hasPathSuffix() { + return _pathSuffix; + } + + /// Returns the specified base path with an optional numeric suffix for the specified index. + String &getPath(const String &basePath, int index); + + /// Returns a unique ID for this sequence. + int getId() { + return _id; + } + + private: + static int _nextID; + int _id; + Array _regions; + bool _pathSuffix; + Array> _uvs; + Array> _offsets; + int _start; + int _digits; + int _setupIndex; + String _tmpPath; + + static int nextID(); + }; + + /// Controls how getRegions() are displayed over time. + enum SequenceMode { + SequenceMode_hold = 0, + SequenceMode_once = 1, + SequenceMode_loop = 2, + SequenceMode_pingpong = 3, + SequenceMode_onceReverse = 4, + SequenceMode_loopReverse = 5, + SequenceMode_pingpongReverse = 6 + }; + + inline SequenceMode SequenceMode_valueOf(const String &value) { + if (value == "hold") return SequenceMode_hold; + if (value == "once") return SequenceMode_once; + if (value == "loop") return SequenceMode_loop; + if (value == "pingpong") return SequenceMode_pingpong; + if (value == "onceReverse") return SequenceMode_onceReverse; + if (value == "loopReverse") return SequenceMode_loopReverse; + if (value == "pingpongReverse") return SequenceMode_pingpongReverse; + return SequenceMode_hold; + } +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SequenceTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SequenceTimeline.h new file mode 100644 index 0000000..6ccf220 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SequenceTimeline.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SequenceTimeline_h +#define Spine_SequenceTimeline_h + +#include +#include +#include + +namespace spine { + class Attachment; + class HasTextureRegion; + class Slot; + + /// Changes the sequence index for an attachment's Sequence. + class SP_API SequenceTimeline : public Timeline, public SlotTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit SequenceTimeline(size_t frameCount, int slotIndex, Attachment &attachment); + + virtual ~SequenceTimeline(); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + /// Sets the time, mode, index, and frame time for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + /// @param delay Seconds between frames. + void setFrame(int frame, float time, SequenceMode mode, int index, float delay); + + /// The attachment for which the sequence index will be set. + /// + /// See Attachment::getTimelineAttachment(). + Attachment &getAttachment() { + return *(Attachment *) _attachment; + } + + virtual int getSlotIndex() override; + + virtual void setSlotIndex(int inValue) override; + + protected: + int _slotIndex; + Attachment *_attachment; + + void setupPose(Slot &slot, bool appliedPose); + void applyToSlot(Slot &slot, bool appliedPose, Sequence &sequence, float time, float before, int modeAndIndex, float delay); + + static const int ENTRIES = 3; + static const int MODE = 1; + static const int DELAY = 2; + }; +} + +#endif /* Spine_SequenceTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ShearTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ShearTimeline.h new file mode 100644 index 0000000..d312efa --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/ShearTimeline.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ShearTimeline_h +#define Spine_ShearTimeline_h + +#include + +namespace spine { + /// Changes a bone's local shearX and shearY. + class SP_API ShearTimeline : public BoneTimeline2 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + protected: + virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override; + }; + + /// Changes a bone's local shearX. + class SP_API ShearXTimeline : public BoneTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + protected: + virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override; + }; + + /// Changes a bone's local shearY. + class SP_API ShearYTimeline : public BoneTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + protected: + virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override; + }; +} + +#endif /* Spine_ShearTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Skeleton.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Skeleton.h new file mode 100644 index 0000000..a3d5aa5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Skeleton.h @@ -0,0 +1,368 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Skeleton_h +#define Spine_Skeleton_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spine { + class SkeletonData; + + class Bone; + + class BonePose; + + class Updatable; + + class Slot; + + class DrawOrder; + + class IkConstraint; + + class PathConstraint; + + class PhysicsConstraint; + + class TransformConstraint; + + class Skin; + + class Attachment; + + class SkeletonClipping; + + /// Stores bones and slots to be posed by animations and application code. Multiple skeleton instances can share the same + /// SkeletonData, including animations, attachments, and skins. + /// + /// After posing, call updateWorldTransform(Physics) to apply constraints and compute world transforms for rendering. + class SP_API Skeleton : public SpineObject { + friend class AnimationState; + + friend class SkeletonBounds; + + friend class SkeletonClipping; + + friend class SlotCurveTimeline; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderFolderTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class InheritTimeline; + + friend class PathConstraint; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class SliderTimeline; + + friend class SliderMixTimeline; + + friend class ScaleTimeline; + + friend class ScaleXTimeline; + + friend class ScaleYTimeline; + + friend class ShearTimeline; + + friend class ShearXTimeline; + + friend class ShearYTimeline; + + friend class TransformConstraintTimeline; + + friend class BoneTimeline1; + + friend class BoneTimeline2; + + friend class RotateTimeline; + + friend class TranslateTimeline; + + friend class TranslateXTimeline; + + friend class TranslateYTimeline; + + friend class TwoColorTimeline; + + friend class PhysicsConstraint; + + friend class BonePose; + + friend class IkConstraint; + + friend class PathConstraint; + + friend class PhysicsConstraint; + + friend class TransformConstraint; + + friend class Slider; + + public: + explicit Skeleton(SkeletonData &skeletonData); + + ~Skeleton(); + + /// Caches information about bones and constraints. Must be called if the active skin is modified or if bones, constraints, or + /// weighted path attachments are added or removed. + void updateCache(); + + void printUpdateCache(); + + void constrained(Posed &object); + + void sortBone(Bone *bone); + + static void sortReset(Array &bones); + + /// Updates the world transform for each bone and applies all constraints. + /// + /// See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + /// Runtimes Guide. + void updateWorldTransform(Physics physics); + + + /// Sets the bones, constraints, and slots to their setup pose values. + void setupPose(); + + /// Sets the bones and constraints to their setup pose values. + void setupPoseBones(); + + void setupPoseSlots(); + + SkeletonData &getData(); + + Array &getBones(); + + Array &getUpdateCache(); + + Bone *getRootBone(); + + /// @return May be NULL. + Bone *findBone(const String &boneName); + + /// The skeleton's slots in setup pose order. To change the order use DrawOrder::getPose(). For rendering use + /// DrawOrder::getAppliedPose(). + Array &getSlots(); + + /// @return May be NULL. + Slot *findSlot(const String &slotName); + + /// The skeleton's draw order. Use DrawOrder::getAppliedPose() for rendering and DrawOrder::getPose() for changing the + /// draw order. + DrawOrder &getDrawOrder(); + + Skin *getSkin(); + + /// Sets a skin by name (see setSkin). + void setSkin(const String &skinName); + + /// Sets the skin used to look up attachments before looking in SkeletonData::getDefaultSkin(). If the skin is changed, + /// updateCache() is called. + /// + /// Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was + /// no old skin, each slot's setup pose placeholder attachment is attached from the new skin. + /// + /// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling + /// setupPoseSlots(). Also, AnimationState::apply(Skeleton&) is often called before the next time the skeleton is rendered + /// so attachment keys in the current animation(s) can hide or show attachments from the new skin. + /// @param newSkin May be NULL. + void setSkin(Skin *newSkin); + + /// Finds an attachment by looking in getSkin() and SkeletonData::getDefaultSkin() using the slot name and skin + /// placeholder name. First the skin is checked and if the attachment was not found, the default skin is checked. + /// @return May be NULL. + Attachment *getAttachment(const String &slotName, const String &placeholder); + + /// Finds an attachment by looking in getSkin() and SkeletonData::getDefaultSkin() using the slot index and skin + /// placeholder name. First the skin is checked and if the attachment was not found, the default skin is checked. + /// @return May be NULL. + Attachment *getAttachment(int slotIndex, const String &placeholder); + + /// A convenience method to set an attachment by finding the slot with findSlot(String), finding the attachment with + /// getAttachment(int, String), then setting the slot's SlotPose::getAttachment(). + /// @param placeholder May be empty. + void setAttachment(const String &slotName, const String &placeholder); + + Array &getConstraints(); + + /// The skeleton's physics constraints. + Array &getPhysicsConstraints(); + + /// Finds a constraint of the specified type by comparing each constraint's name. It is more efficient to cache the results of + /// this method than to call it multiple times. + template + T *findConstraint(const String &constraintName) { + if (constraintName.isEmpty()) return NULL; + for (size_t i = 0; i < _constraints.size(); i++) { + Constraint *constraint = _constraints[i]; + if (constraint->getRTTI().isExactly(T::rtti)) { + if (constraint->getData().getName() == constraintName) { + return (T *) constraint; + } + } + } + return NULL; + } + + /// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the applied pose. + /// @param outX The horizontal distance between the skeleton origin and the left side of the AABB. + /// @param outY The vertical distance between the skeleton origin and the bottom side of the AABB. + /// @param outWidth The width of the AABB + /// @param outHeight The height of the AABB. + void getBounds(float &outX, float &outY, float &outWidth, float &outHeight); + + /// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the applied pose. + /// @param outX The horizontal distance between the skeleton origin and the left side of the AABB. + /// @param outY The vertical distance between the skeleton origin and the bottom side of the AABB. + /// @param outWidth The width of the AABB + /// @param outHeight The height of the AABB. + /// @param outVertexBuffer Reference to hold an array of floats. This method will assign it with new floats as needed. + /// @param clipping Pointer to a SkeletonClipping instance or NULL. If a clipper is given, clipping attachments will be taken into account. + void getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Array &outVertexBuffer, SkeletonClipping *clipping); + + Color &getColor(); + + void setColor(Color &color); + + void setColor(float r, float g, float b, float a); + + float getScaleX(); + + void setScaleX(float inValue); + + float getScaleY(); + + void setScaleY(float inValue); + + void setScale(float scaleX, float scaleY); + + float getX(); + + void setX(float inValue); + + float getY(); + + void setY(float inValue); + + void setPosition(float x, float y); + + void getPosition(float &x, float &y); + + /// The x component of a vector that defines the direction PhysicsConstraintPose::getWind() is applied. + float getWindX(); + + void setWindX(float windX); + + /// The y component of a vector that defines the direction PhysicsConstraintPose::getWind() is applied. + float getWindY(); + + void setWindY(float windY); + + /// The x component of a vector that defines the direction PhysicsConstraintPose::getGravity() is applied. + float getGravityX(); + + void setGravityX(float gravityX); + + /// The y component of a vector that defines the direction PhysicsConstraintPose::getGravity() is applied. + float getGravityY(); + + void setGravityY(float gravityY); + + /// Rotates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone rotated around the + /// specified point in world space. + void physicsTranslate(float x, float y); + + /// Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */ + void physicsRotate(float x, float y, float degrees); + + /// Returns the skeleton's time, used for time-based manipulations, such as PhysicsConstraint. + /// + /// See update(). + float getTime(); + + void setTime(float time); + + void update(float delta); + + protected: + SkeletonData &_data; + Array _bones; + Array _slots; + DrawOrder _drawOrder; + Array _constraints; + Array _physics; + Array _updateCache; + Array _resetCache; + Skin *_skin; + Color _color; + float _x, _y; + float _scaleX, _scaleY; + float _windX, _windY, _gravityX, _gravityY; + float _time; + int _update; + }; +}// namespace spine + +#endif /* Spine_Skeleton_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonBinary.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonBinary.h new file mode 100644 index 0000000..e680453 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonBinary.h @@ -0,0 +1,267 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonBinary_h +#define Spine_SkeletonBinary_h + +#include +#include +#include +#include +#include +#include +#include + +namespace spine { + class SkeletonData; + + class Atlas; + + class AttachmentLoader; + + class LinkedMesh; + + class Skin; + + class Attachment; + + class VertexAttachment; + + class Animation; + + class Timeline; + + class CurveTimeline; + + class CurveTimeline1; + + class BoneTimeline2; + + class Sequence; + + class SP_API SkeletonBinary : public SpineObject { + public: + static const int BONE_ROTATE = 0; + static const int BONE_TRANSLATE = 1; + static const int BONE_TRANSLATEX = 2; + static const int BONE_TRANSLATEY = 3; + static const int BONE_SCALE = 4; + static const int BONE_SCALEX = 5; + static const int BONE_SCALEY = 6; + static const int BONE_SHEAR = 7; + static const int BONE_SHEARX = 8; + static const int BONE_SHEARY = 9; + static const int BONE_INHERIT = 10; + + static const int SLOT_ATTACHMENT = 0; + static const int SLOT_RGBA = 1; + static const int SLOT_RGB = 2; + static const int SLOT_RGBA2 = 3; + static const int SLOT_RGB2 = 4; + static const int SLOT_ALPHA = 5; + + static const int CONSTRAINT_IK = 0; + static const int CONSTRAINT_PATH = 1; + static const int CONSTRAINT_TRANSFORM = 2; + static const int CONSTRAINT_PHYSICS = 3; + static const int CONSTRAINT_SLIDER = 4; + + static const int ATTACHMENT_DEFORM = 0; + static const int ATTACHMENT_SEQUENCE = 1; + + static const int PATH_POSITION = 0; + static const int PATH_SPACING = 1; + static const int PATH_MIX = 2; + + static const int PHYSICS_INERTIA = 0; + static const int PHYSICS_STRENGTH = 1; + static const int PHYSICS_DAMPING = 2; + static const int PHYSICS_MASS = 4; + static const int PHYSICS_WIND = 5; + static const int PHYSICS_GRAVITY = 6; + static const int PHYSICS_MIX = 7; + static const int PHYSICS_RESET = 8; + + static const int SLIDER_TIME = 0; + static const int SLIDER_MIX = 1; + + static const int CURVE_LINEAR = 0; + static const int CURVE_STEPPED = 1; + static const int CURVE_BEZIER = 2; + + explicit SkeletonBinary(Atlas &atlas); + + explicit SkeletonBinary(AttachmentLoader &attachmentLoader, bool ownsLoader = false); + + ~SkeletonBinary(); + + SkeletonData *readSkeletonData(const unsigned char *binary, int length); + + SkeletonData *readSkeletonDataFile(const String &path); + + void setScale(float scale) { + _scale = scale; + } + + const String &getError() const { + return _error; + } + + private: + struct DataInput : public SpineObject { + const unsigned char *cursor; + const unsigned char *end; + SkeletonData *skeletonData; + + DataInput(SkeletonData *skeletonData, const unsigned char *data, size_t length) + : cursor(data), end(data + length), skeletonData(skeletonData) { + } + + inline int read() { + return readUnsignedByte(); + } + + inline signed char readByte() { + return (signed char) *cursor++; + } + + inline unsigned char readUnsignedByte() { + return (unsigned char) *cursor++; + } + + inline bool readBoolean() { + return readByte() != 0; + } + + inline int readInt() { + int result = readUnsignedByte(); + result <<= 8; + result |= readUnsignedByte(); + result <<= 8; + result |= readUnsignedByte(); + result <<= 8; + result |= readUnsignedByte(); + return result; + } + + inline long long readLong() { + unsigned long long result = (unsigned int) readInt(); + result <<= 32; + result |= (unsigned int) readInt(); + return (long long) result; + } + + inline float readFloat() { + union { + int intValue; + float floatValue; + } intToFloat; + intToFloat.intValue = readInt(); + return intToFloat.floatValue; + } + + inline void readColor(Color &color) { + color.r = readUnsignedByte() / 255.0f; + color.g = readUnsignedByte() / 255.0f; + color.b = readUnsignedByte() / 255.0f; + color.a = readUnsignedByte() / 255.0f; + } + + inline int readInt(bool optimizePositive) { + unsigned char b = readUnsignedByte(); + int value = b & 0x7F; + if (b & 0x80) { + b = readUnsignedByte(); + value |= (b & 0x7F) << 7; + if (b & 0x80) { + b = readUnsignedByte(); + value |= (b & 0x7F) << 14; + if (b & 0x80) { + b = readUnsignedByte(); + value |= (b & 0x7F) << 21; + if (b & 0x80) value |= (readUnsignedByte() & 0x7F) << 28; + } + } + } + if (!optimizePositive) value = (((unsigned int) value >> 1) ^ -(value & 1)); + return value; + } + + char *readString() { + int length = readInt(true); + char *string; + if (length == 0) return NULL; + string = SpineExtension::alloc(length, __FILE__, __LINE__); + memcpy(string, cursor, length - 1); + cursor += length - 1; + string[length - 1] = '\0'; + return string; + } + + char *readStringRef() { + int index = readInt(true); + return index == 0 ? NULL : skeletonData->_strings[index - 1]; + } + }; + + AttachmentLoader *_attachmentLoader; + Array _linkedMeshes; + String _error; + float _scale; + const bool _ownsLoader; + + void setError(const char *value1, const char *value2); + + Skin *readSkin(DataInput &input, SkeletonData &skeletonData, bool defaultSkin, bool nonessential); + + Attachment *readAttachment(DataInput &input, Skin &skin, int slotIndex, const String &placeholder, SkeletonData &skeletonData, + bool nonessential); + + Sequence *readSequence(DataInput &input, bool hasPathSuffix); + + int readVertices(DataInput &input, Array &vertices, Array &bones, bool weighted); + + void readFloatArray(DataInput &input, int n, float scale, Array &array); + + void readUnsignedShortArray(DataInput &input, Array &array, int n); + + Animation *readAnimation(DataInput &input, const String &name, SkeletonData &skeletonData, bool nonessential); + + void readTimeline(DataInput &input, Array &timelines, CurveTimeline1 &timeline, float scale); + + void readTimeline(DataInput &input, Array &timelines, BoneTimeline2 &timeline, float scale); + + void readDrawOrder(DataInput &input, size_t slotCount, Array &drawOrder); + + void setBezier(DataInput &input, CurveTimeline &timeline, int bezier, int frame, int value, float time1, float time2, float value1, + float value2, float scale); + }; +}// namespace spine + +#endif /* Spine_SkeletonBinary_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonBounds.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonBounds.h new file mode 100644 index 0000000..2593410 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonBounds.h @@ -0,0 +1,135 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonBounds_h +#define Spine_SkeletonBounds_h + +#include +#include +#include + +namespace spine { + class Skeleton; + + class BoundingBoxAttachment; + + class Polygon; + + /// Collects each BoundingBoxAttachment that is visible and computes the world vertices for its polygon. + /// The polygon vertices are provided along with convenience methods for doing hit detection. + class SP_API SkeletonBounds : public SpineObject { + public: + SkeletonBounds(); + + ~SkeletonBounds(); + + /// Clears any previous polygons, finds all visible bounding box attachments, + /// and computes the world vertices for each bounding box's polygon. + /// @param skeleton The skeleton. + /// @param updateAabb + /// If true, the axis aligned bounding box containing all the polygons is computed. + /// If false, the SkeletonBounds AABB methods will always return true. + /// + void update(Skeleton &skeleton, bool updateAabb); + + /// Returns true if the axis aligned bounding box contains the point. + bool aabbContainsPoint(float x, float y); + + /// Returns true if the axis aligned bounding box intersects the line segment. + bool aabbIntersectsSegment(float x1, float y1, float x2, float y2); + + /// Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. + bool aabbIntersectsSkeleton(SkeletonBounds &bounds); + + /// Returns true if the polygon contains the point. + bool containsPoint(Polygon &polygon, float x, float y); + + /// Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more + /// efficient to only call this method if aabbContainsPoint(float, float) returns true. + BoundingBoxAttachment *containsPoint(float x, float y); + + /// Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it + /// is usually more efficient to only call this method if aabbIntersectsSegment(float, float, float, float) returns true. + BoundingBoxAttachment *intersectsSegment(float x1, float y1, float x2, float y2); + + /// Returns true if the polygon contains any part of the line segment. + bool intersectsSegment(Polygon &polygon, float x1, float y1, float x2, float y2); + + /// Returns the polygon for the given bounding box attachment or null if no + /// polygon can be found for the attachment. Requires a call to update() first. + Polygon *getPolygon(BoundingBoxAttachment *attachment); + + /// Returns the bounding box for the given polygon or null. Requires a call to update() first. + BoundingBoxAttachment *getBoundingBox(Polygon *polygon); + + /// Returns all polygons or an empty array. Requires a call to update() first. + Array &getPolygons(); + + /// Returns all bounding boxes. Requires a call to update() first. + Array &getBoundingBoxes(); + + /// The left edge of the axis aligned bounding box. + float getMinX(); + + /// The bottom edge of the axis aligned bounding box. + float getMinY(); + + /// The right edge of the axis aligned bounding box. + float getMaxX(); + + /// The top edge of the axis aligned bounding box. + float getMaxY(); + + /// The width of the axis aligned bounding box. + float getWidth(); + + /// The height of the axis aligned bounding box. + float getHeight(); + + private: + Pool _polygonPool; + Array _boundingBoxes; + Array _polygons; + float _minX, _minY, _maxX, _maxY; + + void aabbCompute(); + }; + + class Polygon : public SpineObject { + public: + Array _vertices; + int _count; + + Polygon() : _count(0) { + _vertices.ensureCapacity(16); + } + }; +} + +#endif /* Spine_SkeletonBounds_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonClipping.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonClipping.h new file mode 100644 index 0000000..386aefb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonClipping.h @@ -0,0 +1,90 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonClipping_h +#define Spine_SkeletonClipping_h + +#include +#include + +namespace spine { + class Slot; + class Skeleton; + class ClippingAttachment; + + class SP_API SkeletonClipping : public SpineObject { + public: + SkeletonClipping(); + + size_t clipStart(Skeleton &skeleton, Slot &slot, ClippingAttachment *clip); + + void clipEnd(Slot &slot); + + void clipEnd(); + + bool clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength); + + bool clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength, float *uvs, size_t stride); + + bool clipTriangles(Array &vertices, Array &triangles, Array &uvs, size_t stride); + + bool isClipping(); + + Array &getClippedVertices(); + + Array &getClippedTriangles(); + + Array &getClippedUVs(); + + private: + Triangulator _triangulator; + Array _clippingPolygon; + Array *> _clippingPolygons; + Array _clipOutput; + Array _clippedVertices; + Array _clippedTriangles; + Array _clippedUVs; + Array _inverseVertices; + Array _scratch; + ClippingAttachment *_clipAttachment; + bool _inverse; + + /** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping + * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */ + bool clip(float x1, float y1, float x2, float y2, float x3, float y3, Array *polygon); + + void clipInverse(float x1, float y1, float x2, float y2, float x3, float y3, Array *polygon); + + static bool makeClockwise(Array &polygon); + + void makeConvex(Array &polygon); + }; +} + +#endif /* Spine_SkeletonClipping_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonData.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonData.h new file mode 100644 index 0000000..7028d28 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonData.h @@ -0,0 +1,213 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonData_h +#define Spine_SkeletonData_h + +#include +#include +#include + +namespace spine { + class BoneData; + + class SlotData; + + class Skin; + + class EventData; + + class Animation; + + class IkConstraintData; + + class TransformConstraintData; + + class PathConstraintData; + + class PhysicsConstraintData; + + class ConstraintData; + + /// Stores the setup pose and all of the stateless data for a skeleton. + /// + /// See Data objects in the Spine Runtimes + /// Guide. + class SP_API SkeletonData : public SpineObject { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class Skeleton; + + public: + SkeletonData(); + + ~SkeletonData(); + + /// Finds a bone by comparing each bone's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + BoneData *findBone(const String &boneName); + + /// @return May be NULL. + SlotData *findSlot(const String &slotName); + + /// @return May be NULL. + Skin *findSkin(const String &skinName); + + /// @return May be NULL. + EventData *findEvent(const String &eventDataName); + + /// @return May be NULL. + Animation *findAnimation(const String &animationName); + + /// Collects animations used by slider constraints. + Array &findSliderAnimations(Array &animations); + + /// The skeleton's name, which by default is the name of the skeleton data file when possible, or null when a name hasn't been + /// set. + const String &getName(); + + void setName(const String &inValue); + + /// The skeleton's bones, sorted parent first. The root bone is always the first bone. + Array &getBones(); + + /// The skeleton's slots in the setup pose draw order. + Array &getSlots(); + + /// All skins, including the default skin. + Array &getSkins(); + + /// The skeleton's default skin. + /// By default this skin contains all attachments that were not in a skin in Spine. + /// @return May be NULL. + Skin *getDefaultSkin(); + + void setDefaultSkin(Skin *inValue); + + /// The skeleton's events. + Array &getEvents(); + + /// The skeleton's animations. + Array &getAnimations(); + + /// The skeleton's constraints. + Array &getConstraints(); + + /// Finds a constraint of the specified type by comparing each constraint's name. It is more efficient to cache the results of + /// this method than to call it multiple times. + /// @return May be NULL. + template + T *findConstraint(const String &constraintName) { + getConstraints();// Ensure constraints array is populated + for (size_t i = 0, n = _constraints.size(); i < n; i++) { + ConstraintData *constraint = _constraints[i]; + if (constraint->getName() == constraintName && constraint->getRTTI().instanceOf(T::rtti)) { + return static_cast(constraint); + } + } + return NULL; + } + + /// The X coordinate of the skeleton's axis aligned bounding box in the setup pose. + float getX(); + + void setX(float inValue); + + /// The Y coordinate of the skeleton's axis aligned bounding box in the setup pose. + float getY(); + + void setY(float inValue); + + /// The width of the skeleton's axis aligned bounding box in the setup pose. + float getWidth(); + + void setWidth(float inValue); + + /// The height of the skeleton's axis aligned bounding box in the setup pose. + float getHeight(); + + void setHeight(float inValue); + + /// Baseline scale factor for applying physics and other effects based on distance to non-scalable properties, such as angle or + /// scale. Default is 100. + float getReferenceScale(); + + void setReferenceScale(float inValue); + + /// The Spine version used to export this data, or NULL. + const String &getVersion(); + + void setVersion(const String &inValue); + + /// The skeleton data hash. This value will change if any of the skeleton data has changed. + const String &getHash(); + + void setHash(const String &inValue); + + /// The path to the images folder as defined in Spine, or null if nonessential data was not exported. + const String &getImagesPath(); + + void setImagesPath(const String &inValue); + + /// The path to the audio folder as defined in Spine, or null if nonessential data was not exported. + const String &getAudioPath(); + + void setAudioPath(const String &inValue); + + /// The dopesheet FPS in Spine. Available only when nonessential data was exported. + float getFps(); + + void setFps(float inValue); + + private: + String _name; + Array _bones;// Ordered parents first + Array _slots;// Setup pose draw order. + Array _skins; + Skin *_defaultSkin; + Array _events; + Array _animations; + Array _constraints; + float _x, _y, _width, _height; + float _referenceScale; + String _version; + String _hash; + Array _strings; + + // Nonessential. + float _fps; + String _imagesPath; + String _audioPath; + }; +} + +#endif /* Spine_SkeletonData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonJson.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonJson.h new file mode 100644 index 0000000..39838f1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonJson.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonJson_h +#define Spine_SkeletonJson_h + +#include +#include +#include + +namespace spine { + class Timeline; + + class CurveTimeline; + + class CurveTimeline1; + + class BoneTimeline2; + + class VertexAttachment; + + class Animation; + + class Json; + + class SkeletonData; + + class Atlas; + + class AttachmentLoader; + + class LinkedMesh; + + class String; + + class Sequence; + + class Skin; + + class Attachment; + + class SP_API SkeletonJson : public SpineObject { + public: + explicit SkeletonJson(Atlas &atlas); + + explicit SkeletonJson(AttachmentLoader &attachmentLoader, bool ownsLoader = false); + + ~SkeletonJson(); + + SkeletonData *readSkeletonDataFile(const String &path); + + SkeletonData *readSkeletonData(const char *json); + + void setScale(float scale) { + _scale = scale; + } + + const String &getError() const { + return _error; + } + + private: + AttachmentLoader *_attachmentLoader; + Array _linkedMeshes; + float _scale; + const bool _ownsLoader; + String _error; + + static Sequence *readSequence(Json *sequence); + + static void setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1, float cy1, float cx2, + float cy2, float time2, float value2); + + static int readCurve(Json *curve, CurveTimeline *timeline, int bezier, int frame, int value, float time1, float time2, float value1, + float value2, float scale); + + static void readTimeline(Array &timelines, Json *keyMap, CurveTimeline1 *timeline, float defaultValue, float scale); + + static void readTimeline(Array &timelines, Json *keyMap, BoneTimeline2 *timeline, const char *name1, const char *name2, + float defaultValue, float scale); + + Animation *readAnimation(Json *root, SkeletonData *skeletonData); + + Attachment *readAttachment(Json *map, Skin *skin, int slotIndex, const char *placeholder, SkeletonData *skeletonData); + + void readVertices(Json *attachmentMap, VertexAttachment *attachment, size_t verticesLength); + + bool readDrawOrder(SkeletonData *skeletonData, Json *keyMap, int slotCount, const Array *folderSlots, Array &drawOrder); + + void setError(Json *root, const String &value1, const String &value2); + + int findSlotIndex(SkeletonData *skeletonData, const String &slotName, Array timelines); + }; +} + +#endif /* Spine_SkeletonJson_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonRenderer.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonRenderer.h new file mode 100644 index 0000000..244b521 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SkeletonRenderer.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonRenderer_h +#define Spine_SkeletonRenderer_h + +#include +#include +#include + +namespace spine { + class Skeleton; + + struct SP_API RenderCommand { + float *positions; + float *uvs; + uint32_t *colors; + uint32_t *darkColors; + int32_t numVertices; + uint16_t *indices; + int32_t numIndices; + BlendMode blendMode; + void *texture; + RenderCommand *next; + }; + + class SP_API SkeletonRenderer : public SpineObject { + public: + explicit SkeletonRenderer(); + + ~SkeletonRenderer(); + + RenderCommand *render(Skeleton &skeleton); + + private: + BlockAllocator _allocator; + Array _worldVertices; + Array _quadIndices; + SkeletonClipping _clipping; + Array _renderCommands; + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Skin.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Skin.h new file mode 100644 index 0000000..8875f28 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Skin.h @@ -0,0 +1,170 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Skin_h +#define Spine_Skin_h + +#include +#include +#include + +namespace spine { + class Attachment; + + class Skeleton; + + class BoneData; + + class ConstraintData; + + /// Stores attachments by slot index and placeholder name. Multiple Skeleton instances can use the same skins. + /// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and + /// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide. + class SP_API Skin : public SpineObject { + friend class Skeleton; + + public: + class SP_API AttachmentMap : public SpineObject { + friend class Skin; + + public: + struct SP_API Entry { + size_t _slotIndex; + String _placeholder; + Attachment *_attachment; + + Entry(size_t slotIndex, const String &placeholder, Attachment *attachment) + : _slotIndex(slotIndex), _placeholder(placeholder), _attachment(attachment) { + } + }; + + class SP_API Entries { + friend class AttachmentMap; + + public: + bool hasNext() { + while (true) { + if (_slotIndex >= _buckets.size()) return false; + if (_bucketIndex >= _buckets[_slotIndex].size()) { + _bucketIndex = 0; + ++_slotIndex; + continue; + }; + return true; + } + } + + Entry &next() { + Entry &result = _buckets[_slotIndex][_bucketIndex]; + ++_bucketIndex; + return result; + } + + protected: + Entries(Array> &buckets) : _buckets(buckets), _slotIndex(0), _bucketIndex(0) { + } + + private: + Array> &_buckets; + size_t _slotIndex; + size_t _bucketIndex; + }; + + void put(size_t slotIndex, const String &placeholder, Attachment *attachment); + + Attachment *get(size_t slotIndex, const String &placeholder); + + void remove(size_t slotIndex, const String &placeholder); + + Entries getEntries(); + + protected: + AttachmentMap(); + + private: + int findInBucket(Array &, const String &placeholder); + + Array> _buckets; + }; + + explicit Skin(const String &name); + + ~Skin(); + + /// Adds an attachment to the skin for the specified slot index and placeholder name. + /// If the placeholder name already exists for the slot, the previous value is replaced. + void setAttachment(size_t slotIndex, const String &placeholder, Attachment *attachment); + + /// Returns the attachment for the specified slot index and placeholder name, or NULL. + Attachment *getAttachment(size_t slotIndex, const String &placeholder); + + // Removes the attachment from the skin. + void removeAttachment(size_t slotIndex, const String &placeholder); + + /// Finds the placeholder names for a given slot. The results are added to the passed array. + /// @param slotIndex The target slotIndex. To find the slot index, use SkeletonData::findSlot and SlotData::getIndex. + /// @param names Found placeholder names will be added to this array. + void findNamesForSlot(size_t slotIndex, Array &names); + + /// Finds the attachments for a given slot. The results are added to the passed array of Attachments. + /// @param slotIndex The target slotIndex. To find the slot index, use SkeletonData::findSlot and SlotData::getIndex. + /// @param attachments Found Attachments will be added to this array. + void findAttachmentsForSlot(size_t slotIndex, Array &attachments); + + const String &getName(); + + /// Adds all attachments, bones, and constraints from the specified skin to this skin. + void addSkin(Skin &other); + + /// Adds all attachments, bones, and constraints from the specified skin to this skin. Attachments are deep copied. + void copySkin(Skin &other); + + AttachmentMap::Entries getAttachments(); + + Array &getBones(); + + Array &getConstraints(); + + Color &getColor() { + return _color; + } + + private: + const String _name; + AttachmentMap _attachments; + Array _bones; + Array _constraints; + Color _color; + + /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. + void attachAll(Skeleton &skeleton, Skin &oldSkin); + }; +} + +#endif /* Spine_Skin_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Slider.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Slider.h new file mode 100644 index 0000000..1f4a146 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Slider.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Slider_h +#define Spine_Slider_h + +#include +#include +#include + +namespace spine { + class Skeleton; + class Bone; + class Animation; + + /// Applies an animation based on either the slider's SliderPose::getTime() or a bone's transform property. + /// + /// See https://esotericsoftware.com/spine-sliders Sliders in the Spine User Guide. + // Non-exported base class that inherits from the template + class SliderBase : public ConstraintGeneric { + public: + SliderBase(SliderData &data) : ConstraintGeneric(data) { + } + }; + + class SP_API Slider : public SliderBase { + friend class Skeleton; + friend class SliderTimeline; + friend class SliderMixTimeline; + + RTTI_DECL + + public: + Slider(SliderData &data, Skeleton &skeleton); + + Slider ©(Skeleton &skeleton); + + virtual void update(Skeleton &skeleton, Physics physics) override; + + virtual void sort(Skeleton &skeleton) override; + + virtual bool isSourceActive() override; + + /// When set, the bone's transform property is used to set the slider's SliderPose::getTime(). + Bone &getBone(); + + void setBone(Bone &bone); + + private: + Bone *_bone; + static float _offsets[6]; + }; +} + +#endif /* Spine_Slider_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SliderData.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SliderData.h new file mode 100644 index 0000000..8bbce0b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SliderData.h @@ -0,0 +1,112 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SliderData_h +#define Spine_SliderData_h + +#include +#include +#include +#include + +namespace spine { + class Animation; + class BoneData; + class FromProperty; + class Slider; + class Skeleton; + + /// Stores the setup pose for a Slider + class SP_API SliderData : public ConstraintDataGeneric { + friend class SkeletonBinary; + friend class SkeletonData; + friend class SkeletonJson; + friend class Slider; + friend class SliderMixTimeline; + friend class SliderTimeline; + + RTTI_DECL + + public: + explicit SliderData(const String &name); + ~SliderData(); + + /// Creates a slider instance. + virtual Constraint &create(Skeleton &skeleton) override; + + /// The animation the slider will apply. + Animation &getAnimation(); + void setAnimation(Animation &animation); + + /// When true, the animation is applied by adding it to the current pose rather than overwriting it. + bool getAdditive(); + void setAdditive(bool additive); + + /// When true, the animation repeats after its duration, otherwise the last frame is used. + bool getLoop(); + void setLoop(bool loop); + + /// When set, the bone's transform property is used to set the slider's SliderPose::getTime(). + BoneData *getBone(); + void setBone(BoneData *bone); + + /// When a bone is set, the specified transform property is used to set the slider's SliderPose::getTime(). + FromProperty *getProperty(); + void setProperty(FromProperty *property); + + /// When a bone is set, this is the scale of the property value in relation to the slider time. + float getScale(); + void setScale(float scale); + + /// When a bone is set, the offset is added to the property. + float getOffset(); + void setOffset(float offset); + + /// When a bone is set, the maximum slider time for the bone property range, or 0 if nonessential data was not exported. + float getMax(); + void setMax(float max); + + /// When true and a bone is set, the bone's local transform property is read instead of its world transform. + bool getLocal(); + void setLocal(bool local); + + private: + Animation *_animation; + bool _additive; + bool _loop; + BoneData *_bone; + FromProperty *_property; + float _offset; + float _scale; + float _max; + bool _local; + }; +} + +#endif /* Spine_SliderData_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SliderMixTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SliderMixTimeline.h new file mode 100644 index 0000000..650db0a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SliderMixTimeline.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SliderMixTimeline_h +#define Spine_SliderMixTimeline_h + +#include + +namespace spine { + /// Changes a slider's mix. + class SP_API SliderMixTimeline : public ConstraintTimeline1 { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit SliderMixTimeline(size_t frameCount, size_t bezierCount, int sliderIndex); + + virtual ~SliderMixTimeline(); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + }; +} + +#endif /* Spine_SliderMixTimeline_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SliderPose.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SliderPose.h new file mode 100644 index 0000000..6bab56d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SliderPose.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SliderPose_h +#define Spine_SliderPose_h + +#include +#include + +namespace spine { + class Slider; + + /// Stores a pose for a slider. + class SP_API SliderPose : public Pose { + friend class Slider; + friend class SliderMixTimeline; + friend class SliderTimeline; + friend class SkeletonJson; + friend class SkeletonBinary; + + private: + float _time, _mix; + + public: + SliderPose(); + virtual ~SliderPose(); + + virtual void set(SliderPose &pose) override; + + /// The time in SliderData::getAnimation() to apply the animation. + float getTime(); + void setTime(float time); + + /// A percentage (unbounded) that controls the mix between the constrained and unconstrained poses. + float getMix(); + void setMix(float mix); + }; +} + +#endif \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SliderTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SliderTimeline.h new file mode 100644 index 0000000..dd22579 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SliderTimeline.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SliderTimeline_h +#define Spine_SliderTimeline_h + +#include + +namespace spine { + /// Changes a slider's time. + class SP_API SliderTimeline : public ConstraintTimeline1 { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit SliderTimeline(size_t frameCount, size_t bezierCount, int sliderIndex); + + virtual ~SliderTimeline(); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + }; +} + +#endif /* Spine_SliderTimeline_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Slot.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Slot.h new file mode 100644 index 0000000..320a641 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Slot.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Slot_h +#define Spine_Slot_h + +#include +#include +#include +#include +#include +#include + +namespace spine { + class Bone; + class Skeleton; + class Attachment; + + /// Organizes attachments for Skeleton drawOrder purposes and provide a place to store state for an attachment. + /// + /// State cannot be stored in an attachment itself because attachments are stateless and may be shared across multiple + /// skeletons. + class SP_API Slot : public PosedGeneric { + friend class VertexAttachment; + + friend class Skeleton; + + friend class SkeletonBounds; + + friend class SkeletonClipping; + + friend class SlotCurveTimeline; + + friend class AttachmentTimeline; + + friend class RGBATimeline; + + friend class RGBTimeline; + + friend class AlphaTimeline; + + friend class RGBA2Timeline; + + friend class RGB2Timeline; + + friend class DeformTimeline; + + friend class DrawOrderTimeline; + + friend class EventTimeline; + + friend class IkConstraintTimeline; + + friend class PathConstraintMixTimeline; + + friend class PathConstraintPositionTimeline; + + friend class PathConstraintSpacingTimeline; + + friend class ScaleTimeline; + + friend class ShearTimeline; + + friend class TransformConstraintTimeline; + + friend class TranslateTimeline; + + friend class TwoColorTimeline; + + friend class AnimationState; + + public: + Slot(SlotData &data, Skeleton &skeleton); + + /// The bone this slot belongs to. + Bone &getBone(); + + void setupPose() override; + + private: + Skeleton &_skeleton; + Bone &_bone; + int _attachmentState; + }; +} + +#endif /* Spine_Slot_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SlotCurveTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SlotCurveTimeline.h new file mode 100644 index 0000000..1d33d7e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SlotCurveTimeline.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SlotCurveTimeline_h +#define Spine_SlotCurveTimeline_h + +#include +#include + +namespace spine { + class Slot; + class SlotPose; + + /// Base class for slot timelines that use curves. + class SP_API SlotCurveTimeline : public CurveTimeline, public SlotTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + + RTTI_DECL + + public: + SlotCurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount, int slotIndex); + + virtual ~SlotCurveTimeline(); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + virtual int getSlotIndex() override; + + virtual void setSlotIndex(int inValue) override; + + protected: + /// Applies the timeline to the slot pose. + virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) = 0; + + int _slotIndex; + }; +} + +#endif /* Spine_SlotCurveTimeline_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SlotData.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SlotData.h new file mode 100644 index 0000000..1662e62 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SlotData.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SlotData_h +#define Spine_SlotData_h + +#include +#include +#include +#include +#include + +namespace spine { + class BoneData; + + /// Stores the setup pose for a Slot. + class SP_API SlotData : public PosedDataGeneric { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class PathConstraint; + friend class AttachmentTimeline; + friend class RGBATimeline; + friend class RGBTimeline; + friend class AlphaTimeline; + friend class RGBA2Timeline; + friend class RGB2Timeline; + friend class DeformTimeline; + friend class DrawOrderTimeline; + friend class EventTimeline; + friend class IkConstraintTimeline; + friend class PathConstraintMixTimeline; + friend class PathConstraintPositionTimeline; + friend class PathConstraintSpacingTimeline; + friend class ScaleTimeline; + friend class ShearTimeline; + friend class TransformConstraintTimeline; + friend class TranslateTimeline; + friend class TwoColorTimeline; + friend class Slot; + + public: + SlotData(int index, const String &name, BoneData &boneData); + + /// The Skeleton::getSlots() index for this slot. + int getIndex(); + + /// The bone this slot belongs to. + BoneData &getBoneData(); + + void setAttachmentName(const String &attachmentName); + + /// The name of the attachment that is visible for this slot in the setup pose, or empty if no attachment is visible. + const String &getAttachmentName(); + + /// The blend mode for drawing the slot's attachment. + BlendMode getBlendMode(); + void setBlendMode(BlendMode blendMode); + + /// False if the slot was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. + bool getVisible(); + void setVisible(bool visible); + + private: + const int _index; + BoneData &_boneData; + String _attachmentName; + BlendMode _blendMode; + bool _visible; + }; +} + +#endif /* Spine_SlotData_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SlotPose.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SlotPose.h new file mode 100644 index 0000000..23f46d5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SlotPose.h @@ -0,0 +1,106 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SLOTPOSE_H_ +#define SPINE_SLOTPOSE_H_ + +#include +#include +#include +#include +#include + +namespace spine { + class Attachment; + class VertexAttachment; + + /// Stores a slot's pose. + class SP_API SlotPose : public Pose { + friend class Slot; + friend class SlotCurveTimeline; + friend class DeformTimeline; + friend class RGBATimeline; + friend class RGBTimeline; + friend class AlphaTimeline; + friend class RGBA2Timeline; + friend class RGB2Timeline; + friend class PathConstraint; + friend class SkeletonJson; + friend class SkeletonBinary; + friend class AnimationState; + + protected: + Color _color; + Color _darkColor; + bool _hasDarkColor; + Attachment *_attachment; + int _sequenceIndex; + Array _deform; + + public: + SlotPose(); + virtual ~SlotPose(); + + virtual void set(SlotPose &pose) override; + + /// The color used to tint the slot's attachment. If a dark color is set, this is used as the light color for two color + /// tinting. + Color &getColor(); + + /// The dark color used to tint the slot's attachment for two color tinting. The dark + /// color's alpha is not used. + Color &getDarkColor(); + + /// Returns true if this slot has a dark color. + bool hasDarkColor(); + + void setHasDarkColor(bool hasDarkColor); + + /// The current attachment for the slot, or null if the slot has no attachment. + Attachment *getAttachment(); + + /// Sets the slot's attachment and, if the attachment changed, resets sequenceIndex and clears the deform. + /// The deform is not cleared if the old attachment has the same VertexAttachment::getTimelineAttachment() as the + /// specified attachment. + void setAttachment(Attachment *attachment); + + /// The index of the texture region to display when the slot's attachment has a Sequence. -1 represents the + /// Sequence::getSetupIndex(). + int getSequenceIndex(); + void setSequenceIndex(int sequenceIndex); + + /// Values to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a + /// weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions. + /// + /// See VertexAttachment::computeWorldVertices() and DeformTimeline. + Array &getDeform(); + }; +} + +#endif /* SPINE_SLOTPOSE_H_ */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SlotTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SlotTimeline.h new file mode 100644 index 0000000..6d26af2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SlotTimeline.h @@ -0,0 +1,58 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SlotTimeline_h +#define Spine_SlotTimeline_h + +#include +#include + +namespace spine { + + /// An interface for timelines which change the property of a slot. + class SP_API SlotTimeline { + RTTI_DECL_NOPARENT + + friend class AlphaTimeline; + friend class AttachmentTimeline; + friend class SequenceTimeline; + friend class SlotCurveTimeline; + + public: + SlotTimeline(); + virtual ~SlotTimeline(); + + /// The Skeleton::getSlots() index of the slot that will be changed when this timeline is applied. + virtual int getSlotIndex() = 0; + + virtual void setSlotIndex(int inValue) = 0; + }; +} + +#endif /* Spine_SlotTimeline_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SpacingMode.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SpacingMode.h new file mode 100644 index 0000000..bf8553e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SpacingMode.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SpacingMode_h +#define Spine_SpacingMode_h + +#include + +namespace spine { + /// Controls how bones after the first bone are positioned along the path. + /// + /// @see https://esotericsoftware.com/spine-path-constraints#Spacing-mode Spacing mode in the Spine User Guide. + enum SpacingMode { + SpacingMode_Length = 0, + SpacingMode_Fixed, + SpacingMode_Percent, + SpacingMode_Proportional + }; + + inline SpacingMode SpacingMode_valueOf(const char *value) { + if (strcmp(value, "length") == 0) + return SpacingMode_Length; + else if (strcmp(value, "fixed") == 0) + return SpacingMode_Fixed; + else if (strcmp(value, "percent") == 0) + return SpacingMode_Percent; + else if (strcmp(value, "proportional") == 0) + return SpacingMode_Proportional; + else + return SpacingMode_Length;// default + } +} + +#endif /* Spine_SpacingMode_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SpineObject.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SpineObject.h new file mode 100644 index 0000000..dc89369 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SpineObject.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Object_h +#define Spine_Object_h + +#include +#include + +#include + +namespace spine { + class String; + + class SP_API SpineObject { + public: + void *operator new(size_t sz); + + void *operator new(size_t sz, const char *file, int line); + + void *operator new(size_t sz, void *ptr); + + void operator delete(void *p, const char *file, int line); + + void operator delete(void *p, void *mem); + + void operator delete(void *p); + + virtual ~SpineObject(); + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SpineString.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SpineString.h new file mode 100644 index 0000000..99667e5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/SpineString.h @@ -0,0 +1,255 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_STRING_H +#define SPINE_STRING_H + +#include +#include + +#include +#include + +namespace spine { + class SP_API String : public SpineObject { + public: + String() : _length(0), _buffer(NULL), _tempowner(true) { + } + + String(const char *chars, bool own = false, bool tofree = true) { + _tempowner = tofree; + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + if (!own) { + _buffer = SpineExtension::calloc(_length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, chars, _length + 1); + } else { + _buffer = (char *) chars; + } + } + } + + String(const String &other) { + _tempowner = true; + if (!other._buffer) { + _length = 0; + _buffer = NULL; + } else { + _length = other._length; + _buffer = SpineExtension::calloc(other._length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, other._buffer, other._length + 1); + } + } + + size_t length() const { + return _length; + } + + bool isEmpty() const { + return _length == 0; + } + + const char *buffer() const { + return _buffer; + } + + void own(const String &other) { + if (this == &other) return; + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + _length = other._length; + _buffer = other._buffer; + other._length = 0; + other._buffer = NULL; + } + + void own(const char *chars) { + if (_buffer == chars) return; + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + _buffer = (char *) chars; + } + } + + void unown() { + _length = 0; + _buffer = NULL; + } + + String &operator=(const String &other) { + if (this == &other) return *this; + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + if (!other._buffer) { + _length = 0; + _buffer = NULL; + } else { + _length = other._length; + _buffer = SpineExtension::calloc(other._length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, other._buffer, other._length + 1); + } + return *this; + } + + String &operator=(const char *chars) { + if (_buffer == chars) return *this; + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + if (!chars) { + _length = 0; + _buffer = NULL; + } else { + _length = strlen(chars); + _buffer = SpineExtension::calloc(_length + 1, __FILE__, __LINE__); + memcpy((void *) _buffer, chars, _length + 1); + } + return *this; + } + + String &append(const char *chars) { + size_t len = strlen(chars); + size_t thisLen = _length; + _length = _length + len; + bool same = chars == _buffer; + _buffer = SpineExtension::realloc(_buffer, _length + 1, __FILE__, __LINE__); + memcpy((void *) (_buffer + thisLen), (void *) (same ? _buffer : chars), len + 1); + return *this; + } + + String &append(const String &other) { + size_t len = other.length(); + size_t thisLen = _length; + _length = _length + len; + bool same = other._buffer == _buffer; + _buffer = SpineExtension::realloc(_buffer, _length + 1, __FILE__, __LINE__); + memcpy((void *) (_buffer + thisLen), (void *) (same ? _buffer : other._buffer), len + 1); + return *this; + } + + String &append(int other) { + char str[100]; + snprintf(str, 100, "%i", other); + append(str); + return *this; + } + + String &append(float other) { + char str[100]; + snprintf(str, 100, "%f", other); + append(str); + return *this; + } + + String &append(char c) { + size_t thisLen = _length; + _length = _length + 1; + _buffer = SpineExtension::realloc(_buffer, _length + 1, __FILE__, __LINE__); + _buffer[thisLen] = c; + _buffer[_length] = '\0'; + return *this; + } + + bool startsWith(const String &needle) const { + if (needle.length() > length()) return false; + for (int i = 0; i < (int) needle.length(); i++) { + if (buffer()[i] != needle.buffer()[i]) return false; + } + return true; + } + + int lastIndexOf(const char c) const { + for (int i = (int) length() - 1; i >= 0; i--) { + if (buffer()[i] == c) return i; + } + return -1; + } + + String substring(int startIndex, int length) const { + if (startIndex < 0 || startIndex >= (int) _length || length < 0 || startIndex + length > (int) _length) { + return String(); + } + char *subStr = SpineExtension::calloc(length + 1, __FILE__, __LINE__); + memcpy(subStr, _buffer + startIndex, length); + subStr[length] = '\0'; + return String(subStr, true, true); + } + + String substring(int startIndex) const { + if (startIndex < 0 || startIndex >= (int) _length) { + return String(); + } + int length = (int) _length - startIndex; + char *subStr = SpineExtension::calloc(length + 1, __FILE__, __LINE__); + memcpy(subStr, _buffer + startIndex, length); + subStr[length] = '\0'; + return String(subStr, true, true); + } + + friend bool operator==(const String &a, const String &b) { + if (a._buffer == b._buffer) return true; + if (a._length != b._length) return false; + if (a._buffer && b._buffer) { + return strcmp(a._buffer, b._buffer) == 0; + } else { + return false; + } + } + + friend bool operator!=(const String &a, const String &b) { + return !(a == b); + } + + ~String() { + if (_buffer && _tempowner) { + SpineExtension::free(_buffer, __FILE__, __LINE__); + } + } + + private: + mutable size_t _length; + mutable char *_buffer; + mutable bool _tempowner; + }; +} + + +#endif//SPINE_STRING_H diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TextureLoader.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TextureLoader.h new file mode 100644 index 0000000..60f86af --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TextureLoader.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TextureLoader_h +#define Spine_TextureLoader_h + +#include +#include + +namespace spine { + class AtlasPage; + + class SP_API TextureLoader : public SpineObject { + public: + TextureLoader(); + + virtual ~TextureLoader(); + + virtual void load(AtlasPage &page, const String &path) = 0; + + virtual void unload(void *texture) = 0; + }; +} + +#endif /* Spine_TextureLoader_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TextureRegion.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TextureRegion.h new file mode 100644 index 0000000..158133e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TextureRegion.h @@ -0,0 +1,100 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TextureRegion_h +#define Spine_TextureRegion_h + +#include +#include + +namespace spine { + class SP_API TextureRegion : public SpineObject { + friend class MeshAttachment; + friend class RegionAttachment; + friend class Atlas; + friend class AtlasRegion; + friend class SkeletonRenderer; + + RTTI_DECL_NOPARENT + + public: + TextureRegion() : _rendererObject(nullptr), _u(0), _v(0), _u2(0), _v2(0), _regionWidth(0), _regionHeight(0) {}; + ~TextureRegion() {}; + + float getU() const { + return _u; + }; + void setU(float value) { + _u = value; + } + float getV() const { + return _v; + } + void setV(float value) { + _v = value; + } + float getU2() const { + return _u2; + } + void setU2(float value) { + _u2 = value; + } + float getV2() const { + return _v2; + } + void setV2(float value) { + _v2 = value; + } + int getRegionWidth() const { + return _regionWidth; + }; + void setRegionWidth(int value) { + _regionWidth = value; + } + int getRegionHeight() const { + return _regionHeight; + } + void setRegionHeight(int value) { + _regionHeight = value; + } + void *getRendererObject() const { + return _rendererObject; + } + void setRendererObject(void *value) { + _rendererObject = value; + } + + private: + void *_rendererObject; + float _u, _v, _u2, _v2; + int _regionWidth, _regionHeight; + }; +} + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Timeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Timeline.h new file mode 100644 index 0000000..c9339ea --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Timeline.h @@ -0,0 +1,118 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Timeline_h +#define Spine_Timeline_h + +#include +#include +#include +#include + +namespace spine { + class Skeleton; + + class Event; + + enum MixFrom { + MixFrom_Current = 0, + MixFrom_Setup = 1, + MixFrom_First = 2 + }; + + /// The base class for all timelines. + /// + /// See Applying Animations in the Spine + /// Runtimes Guide. + class SP_API Timeline : public SpineObject { + RTTI_DECL_NOPARENT + + public: + Timeline(size_t frameCount, size_t frameEntries); + + virtual ~Timeline(); + + /// Applies this timeline to the skeleton. + /// + /// See Applying Animations in the Spine + /// Runtimes Guide. + /// @param skeleton The skeleton the timeline is applied to. This provides access to the bones, slots, and other skeleton + /// components the timelines may change. + /// @param lastTime The last time in seconds this timeline was applied. Some timelines trigger only at discrete times, in + /// which case all keys are triggered between lastTime (exclusive) and time (inclusive). Pass -1 the first time a + /// timeline is applied to ensure frame 0 is triggered. + /// @param time The time in seconds the skeleton is being posed for. Timelines find the frame before and after this time and + /// interpolate between the frame values. + /// @param events If any events are fired, they are added to this list. Can be NULL to ignore fired events or if no timelines + /// fire events. + /// @param alpha 0 applies setup or current values (depending on from), 1 uses timeline values, and intermediate values + /// interpolate between them. Adjusting alpha over time can mix a timeline in or out. + /// @param from If true, alpha transitions between setup and timeline values, setup values are used before the first + /// frame (current values are not used). If false, alpha transitions between current and timeline values, no change + /// is made before the first frame. + /// @param add If true, for timelines that support it, their values are added to the setup or current values (depending on + /// from). + /// @param out True when the animation is mixing out, else it is mixing in. Used by timelines that perform instant + /// transitions. + /// @param appliedPose True to modify getAppliedPose(), else getPose() is modified. + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) = 0; + + /// True if this timeline supports additive blending. + bool getAdditive() { + return _additive; + } + + /// True if this timeline sets values instantaneously and does not support interpolation between frames. + bool getInstant() { + return _instant; + } + + size_t getFrameEntries(); + + size_t getFrameCount(); + + Array &getFrames(); + + float getDuration(); + + virtual Array &getPropertyIds(); + + protected: + void setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount); + + Array _propertyIds; + Array _frames; + size_t _frameEntries; + bool _additive; + bool _instant; + }; +} + +#endif /* Spine_Timeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TransformConstraint.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TransformConstraint.h new file mode 100644 index 0000000..4b46735 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TransformConstraint.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraint_h +#define Spine_TransformConstraint_h + +#include +#include +#include +#include + +namespace spine { + class Skeleton; + class Bone; + class BonePose; + + // Non-exported base class that inherits from the template + class TransformConstraintBase : public ConstraintGeneric { + public: + TransformConstraintBase(TransformConstraintData &data) + : ConstraintGeneric(data) { + } + }; + + /// Adjusts the world transform of the constrained bones to match that of the source bone. + /// + /// See https://esotericsoftware.com/spine-transform-constraints Transform constraints in the Spine User Guide. + class SP_API TransformConstraint : public TransformConstraintBase { + friend class Skeleton; + friend class TransformConstraintTimeline; + + public: + RTTI_DECL + + TransformConstraint(TransformConstraintData &data, Skeleton &skeleton); + + virtual TransformConstraint ©(Skeleton &skeleton); + + /// Applies the constraint to the constrained bones. + void update(Skeleton &skeleton, Physics physics) override; + + void sort(Skeleton &skeleton) override; + + bool isSourceActive() override; + + /// The bones that will be modified by this transform constraint. + Array &getBones(); + + /// The bone whose world transform will be matched by the constrained bones. + Bone &getSource(); + + void setSource(Bone &source); + + private: + Array _bones; + Bone *_source; + }; +} + +#endif /* Spine_TransformConstraint_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TransformConstraintData.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TransformConstraintData.h new file mode 100644 index 0000000..6cc3446 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TransformConstraintData.h @@ -0,0 +1,326 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraintData_h +#define Spine_TransformConstraintData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + class TransformConstraint; + class BonePose; + class TransformConstraintPose; + + class FromProperty; + class ToProperty; + + /// Source property for a TransformConstraint. + class SP_API FromProperty : public SpineObject { + friend class SkeletonBinary; + + public: + RTTI_DECL_NOPARENT + + /// The value of this property that corresponds to ToProperty offset. + float _offset; + + /// Constrained properties. + Array _to; + + FromProperty(); + virtual ~FromProperty(); + + /// Reads this property from the specified bone. + virtual float value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) = 0; + }; + + /// Constrained property for a TransformConstraint. + class SP_API ToProperty : public SpineObject { + friend class SkeletonBinary; + + public: + RTTI_DECL_NOPARENT + + /// The value of this property that corresponds to FromProperty offset. + float _offset; + + /// The maximum value of this property when clamped. + float _max; + + /// The scale of the FromProperty value in relation to this property. + float _scale; + + ToProperty(); + virtual ~ToProperty(); + + /// Reads the mix for this property from the specified pose. + virtual float mix(TransformConstraintPose &pose) = 0; + + /// Applies the value to this property. + virtual void apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) = 0; + }; + + class SP_API FromRotate : public FromProperty { + public: + RTTI_DECL + + FromRotate() : FromProperty() { + } + ~FromRotate() { + } + + float value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) override; + }; + + class SP_API ToRotate : public ToProperty { + public: + RTTI_DECL + + ToRotate() : ToProperty() { + } + ~ToRotate() { + } + + float mix(TransformConstraintPose &pose) override; + void apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) override; + }; + + class SP_API FromX : public FromProperty { + public: + RTTI_DECL + + FromX() : FromProperty() { + } + ~FromX() { + } + + float value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) override; + }; + + class SP_API ToX : public ToProperty { + public: + RTTI_DECL + + ToX() : ToProperty() { + } + ~ToX() { + } + + float mix(TransformConstraintPose &pose) override; + void apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) override; + }; + + class SP_API FromY : public FromProperty { + public: + RTTI_DECL + + FromY() : FromProperty() { + } + ~FromY() { + } + + float value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) override; + }; + + class SP_API ToY : public ToProperty { + public: + RTTI_DECL + + ToY() : ToProperty() { + } + ~ToY() { + } + + float mix(TransformConstraintPose &pose) override; + void apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) override; + }; + + class SP_API FromScaleX : public FromProperty { + public: + RTTI_DECL + + FromScaleX() : FromProperty() { + } + ~FromScaleX() { + } + + float value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) override; + }; + + class SP_API ToScaleX : public ToProperty { + public: + RTTI_DECL + + ToScaleX() : ToProperty() { + } + ~ToScaleX() { + } + + float mix(TransformConstraintPose &pose) override; + void apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) override; + }; + + class SP_API FromScaleY : public FromProperty { + public: + RTTI_DECL + + FromScaleY() : FromProperty() { + } + ~FromScaleY() { + } + + float value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) override; + }; + + class SP_API ToScaleY : public ToProperty { + public: + RTTI_DECL + + ToScaleY() : ToProperty() { + } + ~ToScaleY() { + } + + float mix(TransformConstraintPose &pose) override; + void apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) override; + }; + + class SP_API FromShearY : public FromProperty { + public: + RTTI_DECL + + FromShearY() : FromProperty() { + } + ~FromShearY() { + } + + float value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) override; + }; + + class SP_API ToShearY : public ToProperty { + public: + RTTI_DECL + + ToShearY() : ToProperty() { + } + ~ToShearY() { + } + + float mix(TransformConstraintPose &pose) override; + void apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) override; + }; + + /// Stores the setup pose for a TransformConstraint. + /// + /// See https://esotericsoftware.com/spine-transform-constraints Transform constraints in the Spine User Guide. + class SP_API TransformConstraintData : public ConstraintDataGeneric { + public: + RTTI_DECL + static const int ROTATION; + static const int X; + static const int Y; + static const int SCALEX; + static const int SCALEY; + static const int SHEARY; + friend class SkeletonBinary; + friend class SkeletonJson; + friend class TransformConstraint; + friend class Skeleton; + friend class TransformConstraintTimeline; + + public: + explicit TransformConstraintData(const String &name); + ~TransformConstraintData(); + + virtual Constraint &create(Skeleton &skeleton) override; + + /// The bones that will be modified by this transform constraint. + Array &getBones(); + + /// The bone whose world transform will be copied to the constrained bones. + BoneData &getSource(); + void setSource(BoneData &source); + + /// An offset added to the constrained bone rotation. + float getOffsetRotation(); + void setOffsetRotation(float offsetRotation); + + /// An offset added to the constrained bone X translation. + float getOffsetX(); + void setOffsetX(float offsetX); + + /// An offset added to the constrained bone Y translation. + float getOffsetY(); + void setOffsetY(float offsetY); + + /// An offset added to the constrained bone scaleX. + float getOffsetScaleX(); + void setOffsetScaleX(float offsetScaleX); + + /// An offset added to the constrained bone scaleY. + float getOffsetScaleY(); + void setOffsetScaleY(float offsetScaleY); + + /// An offset added to the constrained bone shearY. + float getOffsetShearY(); + void setOffsetShearY(float offsetShearY); + + /// Reads the source bone's local transform instead of its world transform. + bool getLocalSource(); + void setLocalSource(bool localSource); + + /// Sets the constrained bones' local transforms instead of their world transforms. + bool getLocalTarget(); + void setLocalTarget(bool localTarget); + + /// Adds the source bone transform to the constrained bones instead of setting it absolutely. + bool getAdditive(); + void setAdditive(bool additive); + + /// Prevents constrained bones from exceeding the ranged defined by offset and max. + bool getClamp(); + void setClamp(bool clamp); + + /// The mapping of transform properties to other transform properties. + Array &getProperties(); + + private: + Array _bones; + BoneData *_source; + float _offsets[6];// [rotation, x, y, scaleX, scaleY, shearY] + bool _localSource, _localTarget, _additive, _clamp; + Array _properties; + }; +} + +#endif /* Spine_TransformConstraintData_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TransformConstraintPose.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TransformConstraintPose.h new file mode 100644 index 0000000..78f9990 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TransformConstraintPose.h @@ -0,0 +1,93 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraintPose_h +#define Spine_TransformConstraintPose_h + +#include +#include + +namespace spine { + /// Stores a pose for a transform constraint. + class SP_API TransformConstraintPose : public Pose { + friend class FromProperty; + friend class ToProperty; + friend class FromRotate; + friend class ToRotate; + friend class FromX; + friend class ToX; + friend class FromY; + friend class ToY; + friend class FromScaleX; + friend class ToScaleX; + friend class FromScaleY; + friend class ToScaleY; + friend class FromShearY; + friend class ToShearY; + friend class TransformConstraint; + friend class TransformConstraintTimeline; + friend class SkeletonJson; + friend class SkeletonBinary; + + private: + float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY; + + public: + TransformConstraintPose(); + virtual ~TransformConstraintPose(); + + virtual void set(TransformConstraintPose &pose) override; + + /// A percentage (unbounded) that controls the mix between the constrained and unconstrained rotation. + float getMixRotate(); + void setMixRotate(float mixRotate); + + /// A percentage (unbounded) that controls the mix between the constrained and unconstrained translation X. + float getMixX(); + void setMixX(float mixX); + + /// A percentage (unbounded) that controls the mix between the constrained and unconstrained translation Y. + float getMixY(); + void setMixY(float mixY); + + /// A percentage (unbounded) that controls the mix between the constrained and unconstrained scale X. + float getMixScaleX(); + void setMixScaleX(float mixScaleX); + + /// A percentage (unbounded) that controls the mix between the constrained and unconstrained scale Y. + float getMixScaleY(); + void setMixScaleY(float mixScaleY); + + /// A percentage (unbounded) that controls the mix between the constrained and unconstrained shear Y. + float getMixShearY(); + void setMixShearY(float mixShearY); + }; +} + +#endif \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TransformConstraintTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TransformConstraintTimeline.h new file mode 100644 index 0000000..367322e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -0,0 +1,80 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraintTimeline_h +#define Spine_TransformConstraintTimeline_h + +#include +#include + +namespace spine { + + /// Changes a transform constraint's rotate, x, y, scaleX, scaleY, and shearY mix values. + class SP_API TransformConstraintTimeline : public CurveTimeline, public ConstraintTimeline { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TransformConstraintTimeline(size_t frameCount, size_t bezierCount, int transformConstraintIndex); + + virtual ~TransformConstraintTimeline(); + + virtual void apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) override; + + /// Sets the time, rotate mix, translate mix, scale mix, and shear mix for the specified frame. + /// @param frame Between 0 and frameCount, inclusive. + /// @param time The frame time in seconds. + void setFrame(int frame, float time, float mixRotate, float mixX, float mixY, float mixScaleX, float mixScaleY, float mixShearY); + + virtual int getConstraintIndex() const override { + return _constraintIndex; + } + + virtual void setConstraintIndex(int inValue) override { + _constraintIndex = inValue; + } + + private: + int _constraintIndex; + + static const int ENTRIES = 7; + static const int ROTATE = 1; + static const int X = 2; + static const int Y = 3; + static const int SCALEX = 4; + static const int SCALEY = 5; + static const int SHEARY = 6; + }; +} + +#endif /* Spine_TransformConstraintTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TranslateTimeline.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TranslateTimeline.h new file mode 100644 index 0000000..66760ef --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/TranslateTimeline.h @@ -0,0 +1,83 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TranslateTimeline_h +#define Spine_TranslateTimeline_h + +#include + +namespace spine { + + /// Changes a bone's local X and Y translation. + class SP_API TranslateTimeline : public BoneTimeline2 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + protected: + virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override; + }; + + /// Changes a bone's local X translation. + class SP_API TranslateXTimeline : public BoneTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + protected: + virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override; + }; + + /// Changes a bone's local Y translation. + class SP_API TranslateYTimeline : public BoneTimeline1 { + friend class SkeletonBinary; + + friend class SkeletonJson; + + RTTI_DECL + + public: + explicit TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex); + + protected: + virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override; + }; +} + +#endif /* Spine_TranslateTimeline_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Triangulator.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Triangulator.h new file mode 100644 index 0000000..7776a80 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Triangulator.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Triangulator_h +#define Spine_Triangulator_h + +#include +#include + +namespace spine { + class SP_API Triangulator : public SpineObject { + public: + ~Triangulator(); + + Array &triangulate(Array &vertices); + + Array *> &decompose(Array &vertices, Array &triangles); + + private: + Array *> _convexPolygons; + Array *> _convexPolygonsIndices; + + Array _indices; + Array _isConcaveArray; + Array _triangles; + + Pool> _polygonPool; + Pool> _polygonIndicesPool; + + static bool isConcave(int index, int vertexCount, const float *vertices, const int *indices); + + static bool positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y); + + static int winding(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y); + }; +} + +#endif /* Spine_Triangulator_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Update.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Update.h new file mode 100644 index 0000000..52fd951 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Update.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Update_h +#define Spine_Update_h + +#include +#include +#include +#include + +namespace spine { + class Skeleton; + + /// The interface for items updated by Skeleton::updateWorldTransform(). + class SP_API Update : public SpineObject { + RTTI_DECL_NOPARENT + public: + Update(); + virtual ~Update(); + + /// @param physics Determines how physics and other non-deterministic updates are applied. + virtual void update(Skeleton &skeleton, Physics physics) = 0; + }; +} + +#endif /* Spine_Update_h */ \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Version.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Version.h new file mode 100644 index 0000000..c60430f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/Version.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_VERSION_H_ +#define SPINE_VERSION_H_ + +#define SPINE_MAJOR_VERSION 4 +#define SPINE_MINOR_VERSION 3 +#define SPINE_VERSION_STRING "4.3" + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/VertexAttachment.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/VertexAttachment.h new file mode 100644 index 0000000..5fff2ab --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/VertexAttachment.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_VertexAttachment_h +#define Spine_VertexAttachment_h + +#include + +#include + +namespace spine { + class Slot; + class Skeleton; + + /// An attachment with vertices that are transformed by one or more bones and can be deformed by + /// SlotPose::getDeform(). + class SP_API VertexAttachment : public Attachment { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class DeformTimeline; + + RTTI_DECL + + public: + explicit VertexAttachment(const String &name); + + virtual ~VertexAttachment(); + + + /// Transforms the attachment's local vertices to world coordinates. If SlotPose::getDeform() is not empty, + /// it is used to deform the vertices. + /// + /// See https://esotericsoftware.com/spine-runtime-skeletons#World-transforms World transforms in the Spine + /// Runtimes Guide. + /// @param start The index of the first vertices value to transform. Each vertex has 2 values, x and y. + /// @param count The number of world vertex values to output. Must be <= WorldVerticesLength - start. + /// @param worldVertices The output world vertices. Must have a length >= offset + count * stride / 2. + /// @param offset The worldVertices index to begin writing values. + /// @param stride The number of worldVertices entries between the value pairs written. + virtual void computeWorldVertices(Skeleton &skeleton, Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride = 2); + + virtual void computeWorldVertices(Skeleton &skeleton, Slot &slot, size_t start, size_t count, Array &worldVertices, size_t offset, + size_t stride = 2); + + /// Gets a unique ID for this attachment. + int getId(); + + /// The bones that affect the vertices. The entries are, for each vertex, the number of bones affecting the + /// vertex followed by that many bone indices, which is Skeleton::getBones() index. Empty if this attachment + /// has no weights. + Array &getBones(); + + void setBones(Array &bones); + + /// The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are x,y pairs + /// for each vertex. For a weighted attachment, the values are x,y,weight triplets for each bone affecting each + /// vertex. + Array &getVertices(); + + void setVertices(Array &vertices); + + size_t getWorldVerticesLength(); + + void setWorldVerticesLength(size_t inValue); + + Attachment *getTimelineAttachment(); + + void setTimelineAttachment(Attachment *attachment); + + void copyTo(VertexAttachment &other); + + protected: + Array _bones; + Array _vertices; + size_t _worldVerticesLength; + + private: + const int _id; + + static int getNextID(); + }; +} + +#endif /* Spine_VertexAttachment_h */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/dll.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/dll.h new file mode 100644 index 0000000..2681a53 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/dll.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SHAREDLIB_H +#define SPINE_SHAREDLIB_H + +#ifdef _WIN32 +#define DLLIMPORT __declspec(dllimport) +#define DLLEXPORT __declspec(dllexport) +#else +#ifndef DLLIMPORT +#define DLLIMPORT +#endif +#ifndef DLLEXPORT +#define DLLEXPORT +#endif +#endif + +#ifdef SPINEPLUGIN_API +#define SP_API SPINEPLUGIN_API +#else +#define SP_API +#endif + +#endif /* SPINE_SHAREDLIB_H */ diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/spine.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/spine.h new file mode 100644 index 0000000..6467ee8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/include/spine/spine.h @@ -0,0 +1,139 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SPINE_H_ +#define SPINE_SPINE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Animation.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Animation.cpp new file mode 100644 index 0000000..2bfa2a0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Animation.cpp @@ -0,0 +1,124 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace spine; + +Animation::Animation(const String &name) : _timelines(), _timelineIds(), _bones(), _duration(0), _name(name), _color(1, 1, 1, 1) { +} + +bool Animation::hasTimeline(Array &ids) { + for (size_t i = 0; i < ids.size(); i++) { + if (_timelineIds.containsKey(ids[i])) return true; + } + return false; +} + +Animation::~Animation() { + ArrayUtils::deleteElements(_timelines); +} + +void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop, Array *events, float alpha, MixFrom from, bool add, + bool out, bool appliedPose) { + if (loop && _duration != 0) { + time = MathUtil::fmod(time, _duration); + if (lastTime > 0) { + lastTime = MathUtil::fmod(lastTime, _duration); + } + } + + for (size_t i = 0, n = _timelines.size(); i < n; ++i) { + _timelines[i]->apply(skeleton, lastTime, time, events, alpha, from, add, out, appliedPose); + } +} + +const String &Animation::getName() { + return _name; +} + +const Array &Animation::getBones() { + return _bones; +} + +Color &Animation::getColor() { + return _color; +} + +Array &Animation::getTimelines() { + return _timelines; +} + +float Animation::getDuration() { + return _duration; +} + +void Animation::setDuration(float inValue) { + _duration = inValue; +} + +int Animation::search(Array &frames, float target) { + size_t n = (int) frames.size(); + for (size_t i = 1; i < n; i++) { + if (frames[i] > target) return (int) (i - 1); + } + return (int) (n - 1); +} + +int Animation::search(Array &frames, float target, int step) { + size_t n = frames.size(); + for (size_t i = step; i < n; i += step) + if (frames[i] > target) return (int) (i - step); + return (int) (n - step); +} + +void Animation::setTimelines(Array &timelines, Array &bones) { + _timelines = timelines; + _bones = bones; + + size_t n = timelines.size(); + _timelineIds.clear(); + for (size_t i = 0; i < n; i++) { + Timeline *timeline = timelines[i]; + Array &propertyIds = timeline->getPropertyIds(); + for (size_t ii = 0; ii < propertyIds.size(); ii++) { + _timelineIds.put(propertyIds[ii], true); + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AnimationState.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AnimationState.cpp new file mode 100644 index 0000000..b1c6c9f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AnimationState.cpp @@ -0,0 +1,1239 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +#ifdef SPINE_USE_STD_FUNCTION +void dummyOnAnimationEventFunc(AnimationState *state, spine::EventType type, TrackEntry *entry, Event *event) { + SP_UNUSED(state); + SP_UNUSED(type); + SP_UNUSED(entry); + SP_UNUSED(event); +} + +#define SP_ANIMATION_LISTENER_USER_DATA_CTOR +#define SP_ANIMATION_LISTENER_CLEAR_USER_DATA() +#define SP_INVOKE_ANIMATION_LISTENER(listener, state, type, entry, event, userData) listener(&state, type, entry, event) +#else +void dummyOnAnimationEventFunc(AnimationState *state, spine::EventType type, TrackEntry *entry, Event *event, void *userData) { + SP_UNUSED(state); + SP_UNUSED(type); + SP_UNUSED(entry); + SP_UNUSED(event); + SP_UNUSED(userData); +} + +#define SP_ANIMATION_LISTENER_USER_DATA_CTOR _listenerUserData(NULL), +#define SP_ANIMATION_LISTENER_CLEAR_USER_DATA() _listenerUserData = NULL +#define SP_INVOKE_ANIMATION_LISTENER(listener, state, type, entry, event, userData) listener(&state, type, entry, event, userData) +#endif + +TrackEntry::TrackEntry() + : _animation(NULL), _previous(NULL), _next(NULL), _mixingFrom(NULL), _mixingTo(0), _trackIndex(0), _loop(false), _additive(false), + _reverse(false), _shortestRotation(false), _keepHold(false), _eventThreshold(0), _mixAttachmentThreshold(0), _alphaAttachmentThreshold(0), + _mixDrawOrderThreshold(0), _animationStart(0), _animationEnd(0), _animationLast(0), _nextAnimationLast(0), _delay(0), _trackTime(0), + _trackLast(0), _nextTrackLast(0), _trackEnd(0), _timeScale(1.0f), _alpha(0), _mixTime(0), _mixDuration(0), _totalAlpha(0), + _mixInterpolation(&Interpolation::linear()), _listener(dummyOnAnimationEventFunc), SP_ANIMATION_LISTENER_USER_DATA_CTOR _listenerObject(NULL), + _state(NULL) { +} + +TrackEntry::~TrackEntry() { +} + +int TrackEntry::getTrackIndex() { + return _trackIndex; +} + +Animation &TrackEntry::getAnimation() { + return *_animation; +} + +void TrackEntry::setAnimation(Animation &animation) { + _animation = &animation; +} + +TrackEntry *TrackEntry::getPrevious() { + return _previous; +} + +bool TrackEntry::getLoop() { + return _loop; +} + +void TrackEntry::setLoop(bool inValue) { + _loop = inValue; +} + +bool TrackEntry::getAdditive() { + return _additive; +} + +void TrackEntry::setAdditive(bool inValue) { + _additive = inValue; +} + +bool TrackEntry::getReverse() { + return _reverse; +} + +void TrackEntry::setReverse(bool inValue) { + _reverse = inValue; +} + +bool TrackEntry::getShortestRotation() { + return _shortestRotation; +} + +void TrackEntry::setShortestRotation(bool inValue) { + _shortestRotation = inValue; +} + +float TrackEntry::getDelay() { + return _delay; +} + +void TrackEntry::setDelay(float inValue) { + if (inValue < 0) { + return; + } + _delay = inValue; +} + +float TrackEntry::getTrackTime() { + return _trackTime; +} + +void TrackEntry::setTrackTime(float inValue) { + _trackTime = inValue; +} + +float TrackEntry::getTrackEnd() { + return _trackEnd; +} + +void TrackEntry::setTrackEnd(float inValue) { + _trackEnd = inValue; +} + +float TrackEntry::getAnimationStart() { + return _animationStart; +} + +void TrackEntry::setAnimationStart(float inValue) { + _animationStart = inValue; +} + +float TrackEntry::getAnimationEnd() { + return _animationEnd; +} + +void TrackEntry::setAnimationEnd(float inValue) { + _animationEnd = inValue; +} + +float TrackEntry::getAnimationLast() { + return _animationLast; +} + +void TrackEntry::setAnimationLast(float inValue) { + _animationLast = inValue; + _nextAnimationLast = inValue; +} + +float TrackEntry::getAnimationTime() { + if (!_loop) return MathUtil::min(_trackTime + _animationStart, _animationEnd); + float duration = _animationEnd - _animationStart; + if (duration == 0) return _animationStart; + return MathUtil::fmod(_trackTime, duration) + _animationStart; +} + +float TrackEntry::getTimeScale() { + return _timeScale; +} + +void TrackEntry::setTimeScale(float inValue) { + _timeScale = inValue; +} + +float TrackEntry::getAlpha() { + return _alpha; +} + +void TrackEntry::setAlpha(float inValue) { + _alpha = inValue; +} + +float TrackEntry::getEventThreshold() { + return _eventThreshold; +} + +void TrackEntry::setEventThreshold(float inValue) { + _eventThreshold = inValue; +} + +float TrackEntry::getMixAttachmentThreshold() { + return _mixAttachmentThreshold; +} + +void TrackEntry::setMixAttachmentThreshold(float inValue) { + _mixAttachmentThreshold = inValue; +} + +float TrackEntry::getAlphaAttachmentThreshold() { + return _alphaAttachmentThreshold; +} + +void TrackEntry::setAlphaAttachmentThreshold(float inValue) { + _alphaAttachmentThreshold = inValue; +} + +float TrackEntry::getMixDrawOrderThreshold() { + return _mixDrawOrderThreshold; +} + +void TrackEntry::setMixDrawOrderThreshold(float inValue) { + _mixDrawOrderThreshold = inValue; +} + +TrackEntry *TrackEntry::getNext() { + return _next; +} + +bool TrackEntry::isComplete() { + return _trackTime >= _animationEnd - _animationStart; +} + +float TrackEntry::getMixTime() { + return _mixTime; +} + +void TrackEntry::setMixTime(float inValue) { + _mixTime = inValue; +} + +float TrackEntry::getMixDuration() { + return _mixDuration; +} + +void TrackEntry::setMixDuration(float inValue) { + _mixDuration = inValue; +} + +void TrackEntry::setMixDuration(float mixDuration, float delay) { + _mixDuration = mixDuration; + if (delay <= 0) delay = _previous == nullptr ? 0 : MathUtil::max(delay + _previous->getTrackComplete() - mixDuration, 0.0f); + this->_delay = delay; +} + +Interpolation &TrackEntry::getMixInterpolation() { + return *_mixInterpolation; +} + +void TrackEntry::setMixInterpolation(Interpolation &mixInterpolation) { + _mixInterpolation = &mixInterpolation; +} + +float TrackEntry::mix() { + if (_mixDuration == 0) return 1; + float mix = _mixTime / _mixDuration; + if (mix >= 1) return 1; + if (_mixInterpolation == &Interpolation::linear()) return mix; + mix = _mixInterpolation->apply(mix); + if (mix < 0) return 0; + if (mix > 1) return 1; + return mix; +} + +TrackEntry *TrackEntry::getMixingFrom() { + return _mixingFrom; +} + +TrackEntry *TrackEntry::getMixingTo() { + return _mixingTo; +} + +void TrackEntry::resetRotationDirections() { + _timelinesRotation.clear(); +} + +#ifdef SPINE_USE_STD_FUNCTION +void TrackEntry::setListener(AnimationStateListener inValue) { + _listener = inValue; + _listenerObject = NULL; +} +#else +void TrackEntry::setListener(AnimationStateListener inValue, void *userData) { + _listener = inValue; + _listenerUserData = userData; + _listenerObject = NULL; +} +#endif + +void TrackEntry::setListener(AnimationStateListenerObject *inValue) { + _listener = dummyOnAnimationEventFunc; + SP_ANIMATION_LISTENER_CLEAR_USER_DATA(); + _listenerObject = inValue; +} + +void TrackEntry::reset() { + _animation = NULL; + _previous = NULL; + _next = NULL; + _mixingFrom = NULL; + _mixingTo = NULL; + _mixInterpolation = &Interpolation::linear(); + + setRendererObject(NULL); + + _timelineMode.clear(); + _timelineHoldMix.clear(); + _timelinesRotation.clear(); + + _listener = dummyOnAnimationEventFunc; + SP_ANIMATION_LISTENER_CLEAR_USER_DATA(); + _listenerObject = NULL; +} + +float TrackEntry::getTrackComplete() { + float duration = _animationEnd - _animationStart; + if (duration != 0) { + if (_loop) return duration * (1 + (int) (_trackTime / duration));// Completion of next loop. + if (_trackTime < duration) return duration; // Before duration. + } + return _trackTime;// Next update. +} + +bool TrackEntry::wasApplied() { + return _nextTrackLast != -1; +} + +bool TrackEntry::isEmptyAnimation() { + return _animation == AnimationState::getEmptyAnimation(); +} + +EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry *trackEntry, Event *event) : _type(eventType), _entry(trackEntry), _event(event) { +} + +EventQueue *EventQueue::newEventQueue(AnimationState &state) { + return new (__FILE__, __LINE__) EventQueue(state); +} + +EventQueueEntry EventQueue::newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event) { + return EventQueueEntry(eventType, entry, event); +} + +EventQueue::EventQueue(AnimationState &state) : _state(state), _drainDisabled(false) { +} + +EventQueue::~EventQueue() { +} + +void EventQueue::start(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Start, entry)); + _state._animationsChanged = true; +} + +void EventQueue::interrupt(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Interrupt, entry)); +} + +void EventQueue::end(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_End, entry)); + _state._animationsChanged = true; +} + +void EventQueue::dispose(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Dispose, entry)); +} + +void EventQueue::complete(TrackEntry *entry) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Complete, entry)); +} + +void EventQueue::event(TrackEntry *entry, Event *event) { + _eventQueueEntries.add(newEventQueueEntry(EventType_Event, entry, event)); +} + +/// Raises all events in the queue and drains the queue. +void EventQueue::drain() { + if (_drainDisabled) { + return; + } + + _drainDisabled = true; + + AnimationState &state = _state; + + // Don't cache _eventQueueEntries.size() so callbacks can queue their own events (eg, call setAnimation in AnimationState_Complete). + for (size_t i = 0; i < _eventQueueEntries.size(); ++i) { + EventQueueEntry queueEntry = _eventQueueEntries[i]; + TrackEntry *trackEntry = queueEntry._entry; + + switch (queueEntry._type) { + case EventType_Start: + case EventType_Interrupt: + case EventType_Complete: + if (!trackEntry->_listenerObject) + SP_INVOKE_ANIMATION_LISTENER(trackEntry->_listener, state, queueEntry._type, trackEntry, NULL, trackEntry->_listenerUserData); + else + trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + if (!state._listenerObject) + SP_INVOKE_ANIMATION_LISTENER(state._listener, state, queueEntry._type, trackEntry, NULL, state._listenerUserData); + else + state._listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + break; + case EventType_End: + if (!trackEntry->_listenerObject) + SP_INVOKE_ANIMATION_LISTENER(trackEntry->_listener, state, queueEntry._type, trackEntry, NULL, trackEntry->_listenerUserData); + else + trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + if (!state._listenerObject) + SP_INVOKE_ANIMATION_LISTENER(state._listener, state, queueEntry._type, trackEntry, NULL, state._listenerUserData); + else + state._listenerObject->callback(&state, queueEntry._type, trackEntry, NULL); + /* Fall through. */ + case EventType_Dispose: + if (!trackEntry->_listenerObject) + SP_INVOKE_ANIMATION_LISTENER(trackEntry->_listener, state, EventType_Dispose, trackEntry, NULL, trackEntry->_listenerUserData); + else + trackEntry->_listenerObject->callback(&state, EventType_Dispose, trackEntry, NULL); + if (!state._listenerObject) + SP_INVOKE_ANIMATION_LISTENER(state._listener, state, EventType_Dispose, trackEntry, NULL, state._listenerUserData); + else + state._listenerObject->callback(&state, EventType_Dispose, trackEntry, NULL); + + if (!_state.getManualTrackEntryDisposal()) _state.disposeTrackEntry(trackEntry); + break; + case EventType_Event: + if (!trackEntry->_listenerObject) + SP_INVOKE_ANIMATION_LISTENER(trackEntry->_listener, state, queueEntry._type, trackEntry, queueEntry._event, + trackEntry->_listenerUserData); + else + trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, queueEntry._event); + if (!state._listenerObject) + SP_INVOKE_ANIMATION_LISTENER(state._listener, state, queueEntry._type, trackEntry, queueEntry._event, state._listenerUserData); + else + state._listenerObject->callback(&state, queueEntry._type, trackEntry, queueEntry._event); + break; + } + } + _eventQueueEntries.clear(); + + _drainDisabled = false; +} + +AnimationState::AnimationState(AnimationStateData &data) + : _data(&data), _queue(EventQueue::newEventQueue(*this)), _animationsChanged(false), _listener(dummyOnAnimationEventFunc), + SP_ANIMATION_LISTENER_USER_DATA_CTOR _listenerObject(NULL), _unkeyedState(0), _timeScale(1), _manualTrackEntryDisposal(false) { +} + +AnimationState::~AnimationState() { + for (size_t i = 0; i < _tracks.size(); i++) { + TrackEntry *entry = _tracks[i]; + if (entry) { + TrackEntry *from = entry->_mixingFrom; + while (from) { + TrackEntry *curr = from; + from = curr->_mixingFrom; + delete curr; + } + TrackEntry *next = entry->_next; + while (next) { + TrackEntry *curr = next; + next = curr->_next; + delete curr; + } + delete entry; + } + } + delete _queue; +} + +void AnimationState::update(float delta) { + delta *= _timeScale; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *currentP = _tracks[i]; + if (currentP == NULL) { + continue; + } + + TrackEntry ¤t = *currentP; + + current._animationLast = current._nextAnimationLast; + current._trackLast = current._nextTrackLast; + + float currentDelta = delta * current._timeScale; + + if (current._delay > 0) { + current._delay -= currentDelta; + if (current._delay > 0) { + continue; + } + currentDelta = -current._delay; + current._delay = 0; + } + + TrackEntry *next = current._next; + if (next != NULL) { + // When the next entry's delay is passed, change to the next entry, preserving leftover time. + float nextTime = current._trackLast - next->_delay; + if (nextTime >= 0) { + next->_delay = 0; + next->_trackTime += current._timeScale == 0 ? 0 : (nextTime / current._timeScale + delta) * next->_timeScale; + current._trackTime += currentDelta; + setTrack(i, next, true); + while (next->_mixingFrom != NULL) { + next->_mixTime += delta; + next = next->_mixingFrom; + } + continue; + } + } else if (current._trackLast >= current._trackEnd && current._mixingFrom == NULL) { + // clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. + _tracks[i] = NULL; + + _queue->end(currentP); + clearNext(currentP); + continue; + } + + if (current._mixingFrom != NULL && updateMixingFrom(currentP, delta)) { + // End mixing from entries once all have completed. + TrackEntry *from = current._mixingFrom; + current._mixingFrom = NULL; + if (from != NULL) from->_mixingTo = NULL; + while (from != NULL) { + _queue->end(from); + from = from->_mixingFrom; + } + } + + current._trackTime += currentDelta; + } + + _queue->drain(); +} + +bool AnimationState::apply(Skeleton &skeleton) { + if (_animationsChanged) { + animationsChanged(); + } + + bool applied = false; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *currentP = _tracks[i]; + if (currentP == NULL || currentP->_delay > 0) { + continue; + } + + TrackEntry ¤t = *currentP; + + applied = true; + + // Apply mixing from entries first. + float alpha = current._alpha; + if (current._mixingFrom != NULL) { + alpha *= applyMixingFrom(currentP, skeleton); + } else if (current._trackTime >= current._trackEnd && current._next == NULL) { + alpha = 0;// Set to setup pose the last time the entry will be applied. + } + + // Apply current entry. + float animationLast = current._animationLast, animationTime = current.getAnimationTime(); + float applyTime = animationTime; + Array *applyEvents = &_events; + if (current._reverse) { + applyTime = current._animation->getDuration() - applyTime; + applyEvents = NULL; + } + size_t timelineCount = current._animation->_timelines.size(); + Array &timelines = current._animation->_timelines; + if (i == 0 && alpha == 1) { + for (size_t ii = 0; ii < timelineCount; ++ii) { + Timeline *timeline = timelines[ii]; + if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) + applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, MixFrom_Setup, true); + else + timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, MixFrom_Setup, false, false, false); + } + } else { + Array &timelineMode = current._timelineMode; + bool retainAttachments = alpha >= current._alphaAttachmentThreshold; + bool add = current._additive, shortestRotation = add || current._shortestRotation; + bool firstFrame = !shortestRotation && current._timelinesRotation.size() != timelines.size() << 1; + if (firstFrame) current._timelinesRotation.setSize(timelines.size() << 1, 0); + Array &timelinesRotation = current._timelinesRotation; + + for (size_t ii = 0; ii < timelineCount; ++ii) { + Timeline *timeline = timelines[ii]; + assert(timeline); + + MixFrom mixFrom = (MixFrom) (timelineMode[ii] & Mode); + + if (!shortestRotation && timeline->getRTTI().isExactly(RotateTimeline::rtti)) + applyRotateTimeline(static_cast(timeline), skeleton, applyTime, alpha, mixFrom, timelinesRotation, ii << 1, + firstFrame); + else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) + applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, mixFrom, retainAttachments); + else + timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, mixFrom, add, false, false); + } + } + + if (current._reverse) eventsReverse(currentP, animationLast, animationTime); + queueEvents(currentP, animationTime); + _events.clear(); + current._nextAnimationLast = animationTime; + current._nextTrackLast = current._trackTime; + } + + int setupState = _unkeyedState + AttachSetup; + Array &slots = skeleton.getSlots(); + for (int i = 0, n = (int) slots.size(); i < n; i++) { + Slot *slot = slots[i]; + if (slot->_attachmentState == setupState) { + const String &attachmentName = slot->getData().getAttachmentName(); + slot->_pose.setAttachment(attachmentName.isEmpty() ? NULL : skeleton.getAttachment(slot->getData().getIndex(), attachmentName)); + } + } + _unkeyedState += 2; + + _queue->drain(); + return applied; +} + +void AnimationState::clearTracks() { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) clearTrack(i); + _tracks.clear(); + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); +} + +void AnimationState::clearTrack(size_t trackIndex) { + if (trackIndex >= _tracks.size()) return; + + TrackEntry *current = _tracks[trackIndex]; + if (current == NULL) return; + + _queue->end(current); + + clearNext(current); + + TrackEntry *entry = current; + while (true) { + TrackEntry *from = entry->_mixingFrom; + if (from == NULL) break; + + _queue->end(from); + entry->_mixingFrom = NULL; + entry->_mixingTo = NULL; + entry = from; + } + + _tracks[current->_trackIndex] = NULL; + + _queue->drain(); +} + +TrackEntry &AnimationState::setAnimation(size_t trackIndex, const String &animationName, bool loop) { + Animation *animation = _data->_skeletonData->findAnimation(animationName); + assert(animation != NULL); + return setAnimation(trackIndex, *animation, loop); +} + +TrackEntry &AnimationState::setAnimation(size_t trackIndex, Animation &animation, bool loop) { + bool interrupt = true; + TrackEntry *current = expandToIndex(trackIndex); + if (current != NULL) { + if (current->_nextTrackLast == -1 && current->_animation == &animation) { + // Don't mix from an entry that was never applied. + _tracks[trackIndex] = current->_mixingFrom; + _queue->interrupt(current); + _queue->end(current); + clearNext(current); + current = current->_mixingFrom; + interrupt = false; + } else { + clearNext(current); + } + } + + TrackEntry *entry = newTrackEntry(trackIndex, &animation, loop, current); + setTrack(trackIndex, entry, interrupt); + _queue->drain(); + + return *entry; +} + +TrackEntry &AnimationState::addAnimation(size_t trackIndex, const String &animationName, bool loop, float delay) { + Animation *animation = _data->_skeletonData->findAnimation(animationName); + assert(animation != NULL); + return addAnimation(trackIndex, *animation, loop, delay); +} + +TrackEntry &AnimationState::addAnimation(size_t trackIndex, Animation &animation, bool loop, float delay) { + TrackEntry *last = expandToIndex(trackIndex); + if (last != NULL) { + while (last->_next != NULL) last = last->_next; + } + + TrackEntry *entry = newTrackEntry(trackIndex, &animation, loop, last); + + if (last == NULL) { + setTrack(trackIndex, entry, true); + _queue->drain(); + if (delay < 0) delay = 0; + } else { + last->_next = entry; + entry->_previous = last; + if (delay <= 0) delay = MathUtil::max(delay + last->getTrackComplete() - entry->_mixDuration, 0.0f); + } + + entry->_delay = delay; + return *entry; +} + +TrackEntry &AnimationState::setEmptyAnimation(size_t trackIndex, float mixDuration) { + TrackEntry &entry = setAnimation(trackIndex, *AnimationState::getEmptyAnimation(), false); + entry._mixDuration = mixDuration; + entry._trackEnd = mixDuration; + return entry; +} + +TrackEntry &AnimationState::addEmptyAnimation(size_t trackIndex, float mixDuration, float delay) { + TrackEntry &entry = addAnimation(trackIndex, *AnimationState::getEmptyAnimation(), false, delay); + if (delay <= 0) entry._delay = MathUtil::max(entry._delay + entry._mixDuration - mixDuration, 0.0f); + entry._mixDuration = mixDuration; + entry._trackEnd = mixDuration; + return entry; +} + +void AnimationState::setEmptyAnimations(float mixDuration) { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *current = _tracks[i]; + if (current != NULL) { + setEmptyAnimation(i, mixDuration); + } + } + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); +} + +TrackEntry *AnimationState::getTrack(size_t trackIndex) { + return trackIndex >= _tracks.size() ? NULL : _tracks[trackIndex]; +} + +AnimationStateData &AnimationState::getData() { + return *_data; +} + +Array &AnimationState::getTracks() { + return _tracks; +} + +float AnimationState::getTimeScale() { + return _timeScale; +} + +void AnimationState::setTimeScale(float inValue) { + _timeScale = inValue; +} + +#ifdef SPINE_USE_STD_FUNCTION +void AnimationState::setListener(AnimationStateListener inValue) { + _listener = inValue; + _listenerObject = NULL; +} +#else +void AnimationState::setListener(AnimationStateListener inValue, void *userData) { + _listener = inValue; + _listenerUserData = userData; + _listenerObject = NULL; +} +#endif + +void AnimationState::setListener(AnimationStateListenerObject *inValue) { + _listener = dummyOnAnimationEventFunc; + SP_ANIMATION_LISTENER_CLEAR_USER_DATA(); + _listenerObject = inValue; +} + +void AnimationState::disableQueue() { + _queue->_drainDisabled = true; +} + +void AnimationState::enableQueue() { + _queue->_drainDisabled = false; +} + +void AnimationState::setManualTrackEntryDisposal(bool inValue) { + _manualTrackEntryDisposal = inValue; +} + +bool AnimationState::getManualTrackEntryDisposal() { + return _manualTrackEntryDisposal; +} + +void AnimationState::disposeTrackEntry(TrackEntry *entry) { + entry->reset(); + _trackEntryPool.free(entry); +} + +Animation *AnimationState::getEmptyAnimation() { + static Array timelines; + static Array bones; + static Animation ret(String("")); + static bool initialized = false; + if (!initialized) { + ret.setTimelines(timelines, bones); + initialized = true; + } + return &ret; +} + +void AnimationState::applyAttachmentTimeline(AttachmentTimeline *attachmentTimeline, Skeleton &skeleton, float time, MixFrom from, bool retain) { + Slot *slot = skeleton.getSlots()[attachmentTimeline->getSlotIndex()]; + if (!slot->getBone().isActive()) return; + if (!retain && slot->_attachmentState == _unkeyedState + AttachRetain) return; + + bool setup = time < attachmentTimeline->getFrames()[0]; + const String *name = NULL; + if (!setup) { + name = &attachmentTimeline->getAttachmentNames()[Animation::search(attachmentTimeline->getFrames(), time)]; + setup = !retain && name->isEmpty(); + } + if (setup) { + if (from == MixFrom_Current) return; + name = &slot->getData().getAttachmentName(); + } + slot->_pose.setAttachment(name->isEmpty() ? NULL : skeleton.getAttachment(slot->getData().getIndex(), *name)); + if (retain) + slot->_attachmentState = _unkeyedState + AttachRetain; + else if (!setup) + slot->_attachmentState = _unkeyedState + AttachSetup; +} + + +void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, MixFrom from, + Array &timelinesRotation, size_t i, bool firstFrame) { + if (firstFrame) timelinesRotation[i] = 0; + + if (alpha == 1) { + static_cast(rotateTimeline)->apply(skeleton, 0, time, NULL, 1, from, false, false, false); + return; + } + + Bone *bone = skeleton._bones[rotateTimeline->_boneIndex]; + if (!bone->isActive()) return; + BonePose &pose = bone->_pose; + BonePose &setup = bone->_data._setupPose; + Array &frames = rotateTimeline->_frames; + float r1, r2; + if (time < frames[0]) { + switch (from) { + case MixFrom_Setup: + pose._rotation = setup._rotation; + return; + case MixFrom_Current: + return; + case MixFrom_First: + break; + } + r1 = pose._rotation; + r2 = setup._rotation; + } else { + r1 = from == MixFrom_Setup ? setup._rotation : pose._rotation; + r2 = setup._rotation + rotateTimeline->getCurveValue(time); + } + + // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. + float total, diff = r2 - r1; + diff -= MathUtil::ceil(diff / 360 - 0.5) * 360; + if (diff == 0) { + total = timelinesRotation[i]; + } else { + float lastTotal, lastDiff; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } else { + lastTotal = timelinesRotation[i]; + lastDiff = timelinesRotation[i + 1]; + } + float loops = lastTotal - MathUtil::fmod(lastTotal, 360.f); + total = diff + loops; + bool current = diff >= 0, dir = lastTotal >= 0; + if (MathUtil::abs(lastDiff) <= 90 && MathUtil::sign(lastDiff) != MathUtil::sign(diff)) { + if (MathUtil::abs(lastTotal - loops) > 180) { + total += 360.f * MathUtil::sign(lastTotal); + dir = current; + } else if (loops != 0) + total -= 360.f * MathUtil::sign(lastTotal); + else + dir = current; + } + if (dir != current) { + total += 360 * MathUtil::sign(lastTotal); + } + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + pose._rotation = r1 + total * alpha; +} + +bool AnimationState::updateMixingFrom(TrackEntry *to, float delta) { + TrackEntry *from = to->_mixingFrom; + if (from == NULL) { + return true; + } + + bool finished = updateMixingFrom(from, delta); + + from->_animationLast = from->_nextAnimationLast; + from->_trackLast = from->_nextTrackLast; + + // The from entry was applied at least once and the mix is complete. + if (to->_nextTrackLast != -1 && to->_mixTime >= to->_mixDuration) { + // Mixing is complete for all entries before the from entry or the mix is instantaneous. + if (from->_totalAlpha == 0 || to->_mixDuration == 0) { + to->_mixingFrom = from->_mixingFrom; + if (from->_mixingFrom) from->_mixingFrom->_mixingTo = to; + if (from->_totalAlpha == 0) { + for (TrackEntry *next = to; next->_mixingTo != NULL; next = next->_mixingTo) next->_keepHold = true; + } + _queue->end(from); + } + return finished; + } + + from->_trackTime += delta * from->_timeScale; + to->_mixTime += delta; + + return false; +} + +float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton) { + TrackEntry *from = to->_mixingFrom; + float fromMix = from->_mixingFrom != NULL ? applyMixingFrom(from, skeleton) : 1; + float mix = to->mix(); + + float a = from->_alpha * fromMix, keep = 1 - mix * to->_alpha; + float alphaMix = a * (1 - mix), alphaHold = keep > 0 ? alphaMix / keep : a; + + Array &timelines = from->_animation->_timelines; + size_t timelineCount = timelines.size(); + Array &timelineMode = from->_timelineMode; + Array &timelineHoldMix = from->_timelineHoldMix; + + bool retainAttachments = mix < from->_mixAttachmentThreshold, drawOrder = mix < from->_mixDrawOrderThreshold; + bool add = from->_additive, shortestRotation = add || from->_shortestRotation; + bool firstFrame = !shortestRotation && from->_timelinesRotation.size() != timelines.size() << 1; + if (firstFrame) from->_timelinesRotation.setSize(timelines.size() << 1, 0); + Array &timelinesRotation = from->_timelinesRotation; + + float animationLast = from->_animationLast, animationTime = from->getAnimationTime(); + float applyTime = animationTime; + Array *events = NULL; + if (from->_reverse) + applyTime = from->_animation->_duration - applyTime; + else if (mix < from->_eventThreshold) + events = &_events; + + from->_totalAlpha = 0; + for (size_t i = 0; i < timelineCount; i++) { + Timeline *timeline = timelines[i]; + int mode = timelineMode[i]; + MixFrom mixFrom = (MixFrom) (mode & Mode); + float alpha; + if ((mode & Hold) != 0) { + TrackEntry *holdMix = timelineHoldMix[i]; + alpha = holdMix == NULL ? alphaHold : alphaHold * (1 - holdMix->mix()); + } else { + if (!drawOrder && timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) && mixFrom == MixFrom_Current) continue; + alpha = alphaMix; + } + from->_totalAlpha += alpha; + if (!shortestRotation && timeline->getRTTI().isExactly(RotateTimeline::rtti)) { + applyRotateTimeline((RotateTimeline *) timeline, skeleton, applyTime, alpha, mixFrom, timelinesRotation, i << 1, firstFrame); + } else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) { + applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, mixFrom, + retainAttachments && alpha >= from->_alphaAttachmentThreshold); + } else { + bool out = !drawOrder || !timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) || mixFrom == MixFrom_Current; + timeline->apply(skeleton, animationLast, applyTime, events, alpha, mixFrom, add, out, false); + } + } + + if (from->_reverse && mix < from->_eventThreshold) eventsReverse(from, animationLast, animationTime); + if (to->_mixDuration > 0) { + queueEvents(from, animationTime); + } + + _events.clear(); + + from->_nextAnimationLast = animationTime; + from->_nextTrackLast = from->_trackTime; + return mix; +} + +void AnimationState::queueEvents(TrackEntry *entry, float animationTime) { + float animationStart = entry->_animationStart, animationEnd = entry->_animationEnd, duration = animationEnd - animationStart; + bool reverse = entry->_reverse; + float split = duration != 0 ? MathUtil::fmod(entry->_trackLast, duration) : 0; + if (reverse) split = duration - split; + + // Queue events before complete. + size_t i = 0, n = _events.size(); + for (; i < n; ++i) { + Event *e = _events[i]; + if ((e->_time < split) != reverse) break; + if (e->_time >= animationStart && e->_time <= animationEnd) _queue->event(entry, e); + } + + // Queue complete if completed a loop iteration or the animation. + bool complete = false; + if (entry->_loop) { + if (duration == 0) + complete = true; + else { + int cycles = (int) (entry->_trackTime / duration); + complete = cycles > 0 && cycles > (int) (entry->_trackLast / duration); + } + } else { + complete = animationTime >= animationEnd && entry->_animationLast < animationEnd; + } + if (complete) _queue->complete(entry); + + // Queue events after complete. + for (; i < n; ++i) { + Event *e = _events[i]; + if (e->_time >= animationStart && e->_time <= animationEnd) _queue->event(entry, e); + } +} + +void AnimationState::eventsReverse(TrackEntry *entry, float animationLast, float animationTime) { + float duration = entry->_animation->getDuration(), from = duration - animationLast, to = duration - animationTime; + Array &timelines = entry->_animation->_timelines; + for (size_t i = 0, n = timelines.size(); i < n; i++) { + if (!timelines[i]->getRTTI().isExactly(EventTimeline::rtti)) continue; + EventTimeline *eventTimeline = static_cast(timelines[i]); + Array &timelineEvents = eventTimeline->getEvents(); + Array &frames = eventTimeline->getFrames(); + int frameCount = (int) frames.size(); + if (from >= to) { + for (int ii = 0; ii < frameCount; ii++) { + if (frames[ii] < to) continue; + if (frames[ii] >= from) break; + _events.add(timelineEvents[ii]); + } + } else { + for (int ii = 0; ii < frameCount; ii++) { + if (frames[ii] >= from) break; + _events.add(timelineEvents[ii]); + } + int ii = 0; + for (; ii < frameCount; ii++) + if (frames[ii] >= to) break; + for (; ii < frameCount; ii++) _events.add(timelineEvents[ii]); + } + } +} + +void AnimationState::setTrack(size_t index, TrackEntry *current, bool interrupt) { + TrackEntry *from = expandToIndex(index); + _tracks[index] = current; + current->_previous = NULL; + + if (from != NULL) { + from->_next = NULL; + if (interrupt) _queue->interrupt(from); + + current->_mixingFrom = from; + from->_mixingTo = current; + current->_mixTime = 0; + from->_timelinesRotation.clear();// Reset rotation for mixing out, in case entry was mixed in. + } + + _queue->start(current);// triggers animationsChanged +} + +TrackEntry *AnimationState::expandToIndex(size_t index) { + if (index < _tracks.size()) return _tracks[index]; + while (index >= _tracks.size()) _tracks.add(NULL); + return NULL; +} + +TrackEntry *AnimationState::newTrackEntry(size_t trackIndex, Animation *animation, bool loop, TrackEntry *last) { + TrackEntry *entryP = _trackEntryPool.obtain();// Pooling + TrackEntry &entry = *entryP; + entry.setAnimationState(this); + + entry._trackIndex = (int) trackIndex; + entry._animation = animation; + entry._loop = loop; + + entry._additive = false; + entry._reverse = false; + entry._shortestRotation = false; + + entry._eventThreshold = 0; + entry._alphaAttachmentThreshold = 0; + entry._mixAttachmentThreshold = 0; + entry._mixDrawOrderThreshold = 0; + + entry._animationStart = 0; + entry._animationEnd = animation->getDuration(); + entry._animationLast = -1; + entry._nextAnimationLast = -1; + + entry._delay = 0; + entry._trackTime = 0; + entry._trackLast = -1; + entry._nextTrackLast = -1;// nextTrackLast == -1 signifies a TrackEntry that wasn't applied yet. + entry._trackEnd = FLT_MAX;// loop ? float.MaxValue : animation.Duration; + entry._timeScale = 1; + + entry._alpha = 1; + entry._mixTime = 0; + entry._mixDuration = (last == NULL) ? 0 : _data->getMix(*last->_animation, *animation); + entry._mixInterpolation = &Interpolation::linear(); + entry._totalAlpha = 0; + entry._keepHold = false; + + return entryP; +} + +void AnimationState::clearNext(TrackEntry *entry) { + TrackEntry *next = entry->_next; + while (next != NULL) { + _queue->dispose(next); + next = next->_next; + } + entry->_next = NULL; +} + +void AnimationState::animationsChanged() { + _animationsChanged = false; + + for (size_t i = 0, n = _tracks.size(); i < n; ++i) { + TrackEntry *track = _tracks[i]; + if (!track) continue; + TrackEntry *entry = track; + + while (entry->_mixingFrom != NULL) entry = entry->_mixingFrom; + + do { + computeHold(entry, track); + entry = entry->_mixingTo; + } while (entry != NULL); + } + _propertyIDs.clear(); +} + +void AnimationState::computeHold(TrackEntry *entry, TrackEntry *track) { + Array &timelines = entry->_animation->_timelines; + size_t timelinesCount = timelines.size(); + Array &timelineMode = entry->_timelineMode; + timelineMode.setSize(timelinesCount, 0); + entry->_timelineHoldMix.clear(); + Array &timelineHoldMix = entry->_timelineHoldMix; + timelineHoldMix.setSize(timelinesCount, NULL); + bool add = entry->_additive, keepHold = entry->_keepHold; + TrackEntry *to = entry->_mixingTo; + + for (size_t i = 0; i < timelinesCount; ++i) { + Timeline *timeline = timelines[i]; + Array &ids = timeline->getPropertyIds(); + int mixFrom = from(track, timeline, ids); + + if (add && timeline->getAdditive()) { + timelineMode[i] = mixFrom; + continue; + } + + // Hold if the next entry will overwrite this property. + int mode; + if (to == NULL || timeline->getInstant() || (to->_additive && timeline->getAdditive()) || !to->_animation->hasTimeline(ids)) + mode = mixFrom; + else { + mode = mixFrom | Hold; + // Find next entry that doesn't overwrite this property. Its mix fades out the hold. + for (TrackEntry *next = to->_mixingTo; next != NULL; next = next->_mixingTo) { + if ((next->_additive && timeline->getAdditive()) || !next->_animation->hasTimeline(ids)) { + if (next->_mixDuration > 0) timelineHoldMix[i] = next; + break; + } + } + } + if (keepHold) mode = (mode & ~Hold) | (timelineMode[i] & Hold); + timelineMode[i] = mode; + } +} + +int AnimationState::from(TrackEntry *track, Timeline *timeline, Array &ids) { + int mixFrom = Setup; + for (size_t i = 0, n = ids.size(); i < n; i++) { + TrackEntry *owner = _propertyIDs.putMissing(ids[i], track); + if (owner != NULL) { + if (owner != track) { + while (++i < n) _propertyIDs.putMissing(ids[i], track); + return Current; + } + mixFrom = First; + } + } + if (timeline->getRTTI().isExactly(DrawOrderFolderTimeline::rtti)) { + TrackEntry **first = _propertyIDs.get(DrawOrderTimeline::getPropertyId()); + if (first != NULL) return *first != track ? Current : First; + } + return mixFrom; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AnimationStateData.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AnimationStateData.cpp new file mode 100644 index 0000000..6fe13a2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AnimationStateData.cpp @@ -0,0 +1,87 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +using namespace spine; + +AnimationStateData::AnimationStateData(SkeletonData &skeletonData) : _skeletonData(&skeletonData), _defaultMix(0) { +} + +void AnimationStateData::setMix(const String &fromName, const String &toName, float duration) { + Animation *from = _skeletonData->findAnimation(fromName); + Animation *to = _skeletonData->findAnimation(toName); + assert(from != NULL); + assert(to != NULL); + + setMix(*from, *to, duration); +} + +void AnimationStateData::setMix(Animation &from, Animation &to, float duration) { + AnimationPair key(&from, &to); + _animationToMixTime.put(key, duration); +} + +float AnimationStateData::getMix(Animation &from, Animation &to) { + AnimationPair key(&from, &to); + + if (_animationToMixTime.containsKey(key)) return _animationToMixTime[key]; + return _defaultMix; +} + +SkeletonData &AnimationStateData::getSkeletonData() { + return *_skeletonData; +} + +float AnimationStateData::getDefaultMix() { + return _defaultMix; +} + +void AnimationStateData::setDefaultMix(float inValue) { + _defaultMix = inValue; +} + +void AnimationStateData::clear() { + _defaultMix = 0; + _animationToMixTime.clear(); +} + +AnimationStateData::AnimationPair::AnimationPair(Animation *a1, Animation *a2) : _a1(a1), _a2(a2) { +} + +bool AnimationStateData::AnimationPair::operator==(const AnimationPair &other) const { + return _a1->_name == other._a1->_name && _a2->_name == other._a2->_name; +} + +size_t AnimationStateData::AnimationPairHash::operator()(const AnimationPair &pair) const { + MapHash hash; + return hash(pair._a1->_name) * 31 + hash(pair._a2->_name); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Atlas.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Atlas.cpp new file mode 100644 index 0000000..7eb5b5e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Atlas.cpp @@ -0,0 +1,361 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(AtlasRegion, TextureRegion) + +Atlas::Atlas(const String &path, TextureLoader *textureLoader, bool createTexture) : _textureLoader(textureLoader) { + int dirLength; + char *dir; + int length; + const char *data; + + /* Get directory from atlas path. */ + const char *lastForwardSlash = strrchr(path.buffer(), '/'); + const char *lastBackwardSlash = strrchr(path.buffer(), '\\'); + const char *lastSlash = lastForwardSlash > lastBackwardSlash ? lastForwardSlash : lastBackwardSlash; + if (lastSlash == path) lastSlash++; /* Never drop starting slash. */ + dirLength = (int) (lastSlash ? lastSlash - path.buffer() : 0); + dir = SpineExtension::calloc(dirLength + 1, __FILE__, __LINE__); + memcpy(dir, path.buffer(), dirLength); + dir[dirLength] = '\0'; + + data = SpineExtension::readFile(path, &length); + if (data) { + load(data, length, dir, createTexture); + } + + SpineExtension::free(data, __FILE__, __LINE__); + SpineExtension::free(dir, __FILE__, __LINE__); +} + +Atlas::Atlas(const char *data, int length, const char *dir, TextureLoader *textureLoader, bool createTexture) : _textureLoader(textureLoader) { + load(data, length, dir, createTexture); +} + +Atlas::~Atlas() { + if (_textureLoader) { + for (size_t i = 0, n = _pages.size(); i < n; ++i) { + _textureLoader->unload(_pages[i]->texture); + } + } + ArrayUtils::deleteElements(_pages); + ArrayUtils::deleteElements(_regions); +} + +void Atlas::flipV() { + for (size_t i = 0, n = _regions.size(); i < n; ++i) { + AtlasRegion *regionP = _regions[i]; + AtlasRegion ®ion = *regionP; + region._v = 1 - region._v; + region._v2 = 1 - region._v2; + } +} + +AtlasRegion *Atlas::findRegion(const String &name) { + for (size_t i = 0, n = _regions.size(); i < n; ++i) + if (_regions[i]->_name == name) return _regions[i]; + return nullptr; +} + +Array &Atlas::getPages() { + return _pages; +} + +Array &Atlas::getRegions() { + return _regions; +} + +struct SimpleString { + char *start; + char *end; + int length; + + SimpleString trim() { + while (isspace((unsigned char) *start) && start < end) start++; + if (start == end) { + length = (int) (end - start); + return *this; + } + end--; + while (((unsigned char) *end == '\r') && end >= start) end--; + end++; + length = (int) (end - start); + return *this; + } + + int indexOf(char needle) { + char *c = start; + while (c < end) { + if (*c == needle) return (int) (c - start); + c++; + } + return -1; + } + + int indexOf(char needle, int at) { + char *c = start + at; + while (c < end) { + if (*c == needle) return (int) (c - start); + c++; + } + return -1; + } + + SimpleString substr(int s, int e) { + e = s + e; + SimpleString result; + result.start = start + s; + result.end = start + e; + result.length = e - s; + return result; + } + + SimpleString substr(int s) { + SimpleString result; + result.start = start + s; + result.end = end; + result.length = (int) (result.end - result.start); + return result; + } + + bool equals(const char *str) { + int otherLen = (int) strlen(str); + if (length != otherLen) return false; + for (int i = 0; i < length; i++) { + if (start[i] != str[i]) return false; + } + return true; + } + + char *copy() { + char *string = SpineExtension::calloc(length + 1, __FILE__, __LINE__); + memcpy(string, start, length); + string[length] = '\0'; + return string; + } + + int toInt() { + return (int) strtol(start, &end, 10); + } +}; + +struct AtlasInput { + const char *start; + const char *end; + char *index; + int length; + SimpleString line; + + AtlasInput(const char *data, int length) : start(data), end(data + length), index((char *) data), length(length) { + } + + SimpleString *readLine() { + if (index >= end) return 0; + line.start = index; + while (index < end && *index != '\n') index++; + line.end = index; + if (index != end) index++; + line = line.trim(); + line.length = (int) (end - start); + return &line; + } + + static int readEntry(SimpleString entry[5], SimpleString *line) { + if (line == nullptr) return 0; + line->trim(); + if (line->length == 0) return 0; + + int colon = line->indexOf(':'); + if (colon == -1) return 0; + entry[0] = line->substr(0, colon).trim(); + for (int i = 1, lastMatch = colon + 1;; i++) { + int comma = line->indexOf(',', lastMatch); + if (comma == -1) { + entry[i] = line->substr(lastMatch).trim(); + return i; + } + entry[i] = line->substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + if (i == 4) return 4; + } + } +}; + +int indexOf(const char **array, int count, SimpleString *str) { + for (int i = 0; i < count; i++) + if (str->equals(array[i])) return i; + return 0; +} + +void Atlas::load(const char *begin, int length, const char *dir, bool createTexture) { + static const char *formatNames[] = {"", "Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888", "RGBA8888"}; + static const char *textureFilterNames[] = + {"", "Nearest", "Linear", "MipMap", "MipMapNearestNearest", "MipMapLinearNearest", "MipMapNearestLinear", "MipMapLinearLinear"}; + + int dirLength = (int) strlen(dir); + int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\'; + AtlasInput reader(begin, length); + SimpleString entry[5]; + AtlasPage *page = nullptr; + + SimpleString *line = reader.readLine(); + while (line != nullptr && line->length == 0) line = reader.readLine(); + + while (true) { + if (line == nullptr || line->length == 0) break; + if (reader.readEntry(entry, line) == 0) break; + line = reader.readLine(); + } + + while (true) { + if (line == nullptr) break; + if (line->trim().length == 0) { + page = nullptr; + line = reader.readLine(); + } else if (page == nullptr) { + char *name = line->copy(); + char *path = SpineExtension::calloc(dirLength + needsSlash + strlen(name) + 1, __FILE__, __LINE__); + memcpy(path, dir, dirLength); + if (needsSlash) path[dirLength] = '/'; + strcpy(path + dirLength + needsSlash, name); + page = new (__FILE__, __LINE__) AtlasPage(String(name, true)); + + while (true) { + line = reader.readLine(); + if (reader.readEntry(entry, line) == 0) break; + if (entry[0].equals("size")) { + page->width = entry[1].toInt(); + page->height = entry[2].toInt(); + } else if (entry[0].equals("format")) { + page->format = (Format) indexOf(formatNames, 8, &entry[1]); + } else if (entry[0].equals("filter")) { +#ifdef SPINE_UE4 + page->minFilter = (SpineTextureFilter) indexOf(textureFilterNames, 8, &entry[1]); + page->magFilter = (SpineTextureFilter) indexOf(textureFilterNames, 8, &entry[2]); +#else + page->minFilter = (TextureFilter) indexOf(textureFilterNames, 8, &entry[1]); + page->magFilter = (TextureFilter) indexOf(textureFilterNames, 8, &entry[2]); +#endif + } else if (entry[0].equals("repeat")) { + page->uWrap = TextureWrap_ClampToEdge; + page->vWrap = TextureWrap_ClampToEdge; + if (entry[1].indexOf('x') != -1) page->uWrap = TextureWrap_Repeat; + if (entry[1].indexOf('y') != -1) page->vWrap = TextureWrap_Repeat; + } else if (entry[0].equals("pma")) { + page->pma = entry[1].equals("true"); + } + } + + page->index = (int) _pages.size(); + if (createTexture && _textureLoader) _textureLoader->load(*page, String(path)); + page->texturePath = String(path, true); + _pages.add(page); + } else { + AtlasRegion *region = new (__FILE__, __LINE__) AtlasRegion(); + region->_page = page; + region->_rendererObject = page->texture; + region->_name = String(line->copy(), true); + while (true) { + line = reader.readLine(); + int count = reader.readEntry(entry, line); + if (count == 0) break; + if (entry[0].equals("xy")) { + region->_x = entry[1].toInt(); + region->_y = entry[2].toInt(); + } else if (entry[0].equals("size")) { + region->_packedWidth = entry[1].toInt(); + region->_packedHeight = entry[2].toInt(); + } else if (entry[0].equals("bounds")) { + region->_x = entry[1].toInt(); + region->_y = entry[2].toInt(); + region->_packedWidth = entry[3].toInt(); + region->_packedHeight = entry[4].toInt(); + } else if (entry[0].equals("offset")) { + region->_offsetX = entry[1].toInt(); + region->_offsetY = entry[2].toInt(); + } else if (entry[0].equals("orig")) { + region->_originalWidth = entry[1].toInt(); + region->_originalHeight = entry[2].toInt(); + } else if (entry[0].equals("offsets")) { + region->_offsetX = entry[1].toInt(); + region->_offsetY = entry[2].toInt(); + region->_originalWidth = entry[3].toInt(); + region->_originalHeight = entry[4].toInt(); + } else if (entry[0].equals("rotate")) { + if (entry[1].equals("true")) { + region->_degrees = 90; + } else if (!entry[1].equals("false")) { + region->_degrees = entry[1].toInt(); + } + region->_rotate = region->_degrees == 90; + } else if (entry[0].equals("index")) { + region->_index = entry[1].toInt(); + } else { + region->_names.add(String(entry[0].copy())); + for (int i = 0; i < count; i++) { + region->_values.add(entry[i + 1].toInt()); + } + } + } + if (region->_originalWidth == 0 && region->_originalHeight == 0) { + region->_originalWidth = region->_packedWidth; + region->_originalHeight = region->_packedHeight; + } + + region->_u = (float) region->_x / page->width; + region->_v = (float) region->_y / page->height; + if (region->_degrees == 90) { + region->_u2 = (float) (region->_x + region->_packedHeight) / page->width; + region->_v2 = (float) (region->_y + region->_packedWidth) / page->height; + } else { + region->_u2 = (float) (region->_x + region->_packedWidth) / page->width; + region->_v2 = (float) (region->_y + region->_packedHeight) / page->height; + } + // Calculate regionWidth/Height from UV coordinates + region->_regionWidth = abs((int) ((region->_u2 - region->_u) * page->width)); + region->_regionHeight = abs((int) ((region->_v2 - region->_v) * page->height)); + + if (region->_degrees == 90) { + int temp = region->_packedWidth; + region->_packedWidth = region->_packedHeight; + region->_packedHeight = temp; + } + + _regions.add(region); + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AtlasAttachmentLoader.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AtlasAttachmentLoader.cpp new file mode 100644 index 0000000..33a7cb0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AtlasAttachmentLoader.cpp @@ -0,0 +1,96 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +AtlasAttachmentLoader::AtlasAttachmentLoader(Atlas &atlas) : AttachmentLoader(), _atlas(&atlas) { +} + +static void findRegions(Atlas *atlas, AtlasAttachmentLoader *loader, const String &name, const String &basePath, Sequence *sequence) { + Array ®ions = sequence->getRegions(); + for (int i = 0, n = (int) regions.size(); i < n; i++) { + String path = sequence->getPath(basePath, i); + regions[i] = loader->findRegion(path); + } +} + +RegionAttachment *AtlasAttachmentLoader::newRegionAttachment(Skin &skin, const String &placeholder, const String &name, const String &path, + Sequence *sequence) { + SP_UNUSED(skin); + SP_UNUSED(placeholder); + findRegions(_atlas, this, name, path, sequence); + return new (__FILE__, __LINE__) RegionAttachment(name, sequence); +} + +MeshAttachment *AtlasAttachmentLoader::newMeshAttachment(Skin &skin, const String &placeholder, const String &name, const String &path, + Sequence *sequence) { + SP_UNUSED(skin); + SP_UNUSED(placeholder); + findRegions(_atlas, this, name, path, sequence); + return new (__FILE__, __LINE__) MeshAttachment(name, sequence); +} + +BoundingBoxAttachment *AtlasAttachmentLoader::newBoundingBoxAttachment(Skin &skin, const String &placeholder, const String &name) { + SP_UNUSED(skin); + SP_UNUSED(placeholder); + return new (__FILE__, __LINE__) BoundingBoxAttachment(name); +} + +PathAttachment *AtlasAttachmentLoader::newPathAttachment(Skin &skin, const String &placeholder, const String &name) { + SP_UNUSED(skin); + SP_UNUSED(placeholder); + return new (__FILE__, __LINE__) PathAttachment(name); +} + +PointAttachment *AtlasAttachmentLoader::newPointAttachment(Skin &skin, const String &placeholder, const String &name) { + SP_UNUSED(skin); + SP_UNUSED(placeholder); + return new (__FILE__, __LINE__) PointAttachment(name); +} + +ClippingAttachment *AtlasAttachmentLoader::newClippingAttachment(Skin &skin, const String &placeholder, const String &name) { + SP_UNUSED(skin); + SP_UNUSED(placeholder); + return new (__FILE__, __LINE__) ClippingAttachment(name); +} + +AtlasRegion *AtlasAttachmentLoader::findRegion(const String &name) { + return _atlas->findRegion(name); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Attachment.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Attachment.cpp new file mode 100644 index 0000000..5f5ac65 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Attachment.cpp @@ -0,0 +1,93 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(Attachment) + +Attachment::Attachment(const String &name) : _name(name), _timelineAttachment(this), _refCount(0) { + assert(_name.length() > 0); +} + +Attachment::~Attachment() { +} + +const String &Attachment::getName() const { + return _name; +} + +Attachment *Attachment::getTimelineAttachment() { + return _timelineAttachment; +} + +void Attachment::setTimelineAttachment(Attachment *attachment) { + _timelineAttachment = attachment; +} + +Array &Attachment::getTimelineSlots() { + return _timelineSlots; +} + +void Attachment::setTimelineSlots(Array &timelineSlots) { + _timelineSlots.clearAndAddAll(timelineSlots); +} + +bool Attachment::isTimelineActive(Array &slots, int slotIndex, bool appliedPose) { + Slot *slot = slots[slotIndex]; + if (slot->getBone().isActive()) { + Attachment *attachment = appliedPose ? slot->getAppliedPose().getAttachment() : slot->getPose().getAttachment(); + if (attachment != NULL && attachment->getTimelineAttachment() == this) return true; + } + for (size_t i = 0, n = _timelineSlots.size(); i < n; ++i) { + slot = slots[_timelineSlots[i]]; + if (!slot->getBone().isActive()) continue; + Attachment *attachment = appliedPose ? slot->getAppliedPose().getAttachment() : slot->getPose().getAttachment(); + if (attachment != NULL && attachment->getTimelineAttachment() == this) return true; + } + return false; +} + +int Attachment::getRefCount() { + return _refCount; +} + +void Attachment::reference() { + _refCount++; +} + +void Attachment::dereference() { + _refCount--; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AttachmentLoader.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AttachmentLoader.cpp new file mode 100644 index 0000000..290eb74 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AttachmentLoader.cpp @@ -0,0 +1,46 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +AttachmentLoader::AttachmentLoader() { +} + +AttachmentLoader::~AttachmentLoader() { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AttachmentTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AttachmentTimeline.cpp new file mode 100644 index 0000000..579b38d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -0,0 +1,89 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL_MULTI(AttachmentTimeline, Timeline, SlotTimeline) + +AttachmentTimeline::AttachmentTimeline(size_t frameCount, int slotIndex) : Timeline(frameCount, 1), SlotTimeline(), _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Attachment << 32) | slotIndex}; + setPropertyIds(ids, 1); + _instant = true; + + _attachmentNames.ensureCapacity(frameCount); + for (size_t i = 0; i < frameCount; ++i) { + _attachmentNames.add(String()); + } +} + +AttachmentTimeline::~AttachmentTimeline() { +} + +void AttachmentTimeline::setAttachment(Skeleton &skeleton, SlotPose &pose, String *attachmentName) { + pose.setAttachment(attachmentName == NULL || attachmentName->isEmpty() ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName)); +} + +void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(alpha); + SP_UNUSED(add); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone.isActive()) return; + SlotPose &pose = appliedPose ? *slot->_appliedPose : slot->_pose; + + if (out || time < _frames[0]) { + if (from != MixFrom_Current) setAttachment(skeleton, pose, &slot->_data._attachmentName); + } else { + setAttachment(skeleton, pose, &_attachmentNames[Animation::search(_frames, time)]); + } +} + +void AttachmentTimeline::setFrame(int frame, float time, const String &attachmentName) { + _frames[frame] = time; + _attachmentNames[frame] = attachmentName; +} + +Array &AttachmentTimeline::getAttachmentNames() { + return _attachmentNames; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Bone.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Bone.cpp new file mode 100644 index 0000000..044c1b7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Bone.cpp @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(Bone, Update) + +bool Bone::yDown = true; + +Bone::Bone(BoneData &data, Bone *parent) + : PosedGeneric(data), PosedActive(), _parent(parent), _children(), _sorted(false) { + _constrainedPose._bone = this; + _appliedPose->_bone = this; +} + +Bone::Bone(Bone &bone, Bone *parent) + : PosedGeneric(bone._data), PosedActive(), _parent(parent), _children(), _sorted(false) { + _constrainedPose._bone = this; + _appliedPose->_bone = this; + _pose.set(bone._pose); +} + +Bone *Bone::getParent() { + return _parent; +} + +Array &Bone::getChildren() { + return _children; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BoneData.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BoneData.cpp new file mode 100644 index 0000000..84169d5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BoneData.cpp @@ -0,0 +1,93 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +#include + +using namespace spine; + +BoneData::BoneData(int index, const String &name, BoneData *parent) + : PosedDataGeneric(name), _index(index), _parent(parent), _length(0), _color(0.61f, 0.61f, 0.61f, 1.0f), _icon(), _iconSize(1), + _iconRotation(0), _visible(true) { + assert(index >= 0); +} + +int BoneData::getIndex() { + return _index; +} + +BoneData *BoneData::getParent() { + return _parent; +} + +float BoneData::getLength() { + return _length; +} + +void BoneData::setLength(float inValue) { + _length = inValue; +} + +Color &BoneData::getColor() { + return _color; +} + +const String &BoneData::getIcon() { + return _icon; +} + +void BoneData::setIcon(const String &icon) { + this->_icon = icon; +} + +float BoneData::getIconSize() { + return _iconSize; +} + +void BoneData::setIconSize(float iconSize) { + _iconSize = iconSize; +} + +float BoneData::getIconRotation() { + return _iconRotation; +} + +void BoneData::setIconRotation(float iconRotation) { + _iconRotation = iconRotation; +} + +bool BoneData::getVisible() { + return _visible; +} + +void BoneData::setVisible(bool inValue) { + this->_visible = inValue; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BoneLocal.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BoneLocal.cpp new file mode 100644 index 0000000..5dc687b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BoneLocal.cpp @@ -0,0 +1,128 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +BoneLocal::BoneLocal() : _x(0), _y(0), _rotation(0), _scaleX(1), _scaleY(1), _shearX(0), _shearY(0), _inherit(Inherit_Normal) { +} + +BoneLocal::~BoneLocal() { +} + +void BoneLocal::set(BoneLocal &pose) { + _x = pose._x; + _y = pose._y; + _rotation = pose._rotation; + _scaleX = pose._scaleX; + _scaleY = pose._scaleY; + _shearX = pose._shearX; + _shearY = pose._shearY; + _inherit = pose._inherit; +} + +float BoneLocal::getX() { + return _x; +} + +void BoneLocal::setX(float x) { + _x = x; +} + +float BoneLocal::getY() { + return _y; +} + +void BoneLocal::setY(float y) { + _y = y; +} + +void BoneLocal::setPosition(float x, float y) { + _x = x; + _y = y; +} + +float BoneLocal::getRotation() { + return _rotation; +} + +void BoneLocal::setRotation(float rotation) { + _rotation = rotation; +} + +float BoneLocal::getScaleX() { + return _scaleX; +} + +void BoneLocal::setScaleX(float scaleX) { + _scaleX = scaleX; +} + +float BoneLocal::getScaleY() { + return _scaleY; +} + +void BoneLocal::setScaleY(float scaleY) { + _scaleY = scaleY; +} + +void BoneLocal::setScale(float scaleX, float scaleY) { + _scaleX = scaleX; + _scaleY = scaleY; +} + +void BoneLocal::setScale(float scale) { + _scaleX = scale; + _scaleY = scale; +} + +float BoneLocal::getShearX() { + return _shearX; +} + +void BoneLocal::setShearX(float shearX) { + _shearX = shearX; +} + +float BoneLocal::getShearY() { + return _shearY; +} + +void BoneLocal::setShearY(float shearY) { + _shearY = shearY; +} + +Inherit BoneLocal::getInherit() { + return _inherit; +} + +void BoneLocal::setInherit(Inherit inherit) { + _inherit = inherit; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BonePose.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BonePose.cpp new file mode 100644 index 0000000..8e8e133 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BonePose.cpp @@ -0,0 +1,419 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include "spine/RTTI.h" +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(BonePose, Update); + +BonePose::BonePose() : BoneLocal(), _bone(nullptr), _a(0), _b(0), _worldX(0), _c(0), _d(0), _worldY(0), _world(0), _local(0) { +} + +BonePose::~BonePose() { +} + +void BonePose::update(Skeleton &skeleton, Physics physics) { + if (_world != skeleton._update) updateWorldTransform(skeleton); +} + +void BonePose::updateWorldTransform(Skeleton &skeleton) { + if (_local == skeleton._update) + updateLocalTransform(skeleton); + else + _world = skeleton._update; + + if (_bone->getParent() == nullptr) {// Root bone. + float sx = skeleton.getScaleX(), sy = skeleton.getScaleY(); + float rx = (_rotation + _shearX) * MathUtil::Deg_Rad; + float ry = (_rotation + 90 + _shearY) * MathUtil::Deg_Rad; + _a = MathUtil::cos(rx) * _scaleX * sx; + _b = MathUtil::cos(ry) * _scaleY * sx; + _c = MathUtil::sin(rx) * _scaleX * sy; + _d = MathUtil::sin(ry) * _scaleY * sy; + _worldX = _x * sx + skeleton.getX(); + _worldY = _y * sy + skeleton.getY(); + return; + } + + BonePose &parent = _bone->getParent()->getAppliedPose(); + float pa = parent._a, pb = parent._b, pc = parent._c, pd = parent._d; + _worldX = pa * _x + pb * _y + parent._worldX; + _worldY = pc * _x + pd * _y + parent._worldY; + + switch (_inherit) { + case Inherit_Normal: { + float rx = (_rotation + _shearX) * MathUtil::Deg_Rad; + float ry = (_rotation + 90 + _shearY) * MathUtil::Deg_Rad; + float la = MathUtil::cos(rx) * _scaleX; + float lb = MathUtil::cos(ry) * _scaleY; + float lc = MathUtil::sin(rx) * _scaleX; + float ld = MathUtil::sin(ry) * _scaleY; + _a = pa * la + pb * lc; + _b = pa * lb + pb * ld; + _c = pc * la + pd * lc; + _d = pc * lb + pd * ld; + return; + } + case Inherit_OnlyTranslation: { + float sx = skeleton.getScaleX(), sy = skeleton.getScaleY(); + float rx = (_rotation + _shearX) * MathUtil::Deg_Rad; + float ry = (_rotation + 90 + _shearY) * MathUtil::Deg_Rad; + _a = MathUtil::cos(rx) * _scaleX * sx; + _b = MathUtil::cos(ry) * _scaleY * sx; + _c = MathUtil::sin(rx) * _scaleX * sy; + _d = MathUtil::sin(ry) * _scaleY * sy; + break; + } + case Inherit_NoRotationOrReflection: { + float sx = skeleton.getScaleX(), sy = skeleton.getScaleY(), sxi = 1 / sx, syi = 1 / sy; + pa *= sxi; + pc *= syi; + float s = pa * pa + pc * pc, r; + if (s > MathUtil::EpsilonSq) { + s = MathUtil::abs(pa * pd * syi - pb * sxi * pc) / s; + pb = pc * s; + pd = pa * s; + r = _rotation - MathUtil::atan2Deg(pc, pa); + } else { + pa = 0; + pc = 0; + r = _rotation - 90 + MathUtil::atan2Deg(pd, pb); + } + float rx = (r + _shearX) * MathUtil::Deg_Rad; + float ry = (r + _shearY + 90) * MathUtil::Deg_Rad; + float la = MathUtil::cos(rx) * _scaleX; + float lb = MathUtil::cos(ry) * _scaleY; + float lc = MathUtil::sin(rx) * _scaleX; + float ld = MathUtil::sin(ry) * _scaleY; + _a = (pa * la - pb * lc) * sx; + _b = (pa * lb - pb * ld) * sx; + _c = (pc * la + pd * lc) * sy; + _d = (pc * lb + pd * ld) * sy; + break; + } + case Inherit_NoScale: + case Inherit_NoScaleOrReflection: { + float sx = skeleton.getScaleX(), sy = skeleton.getScaleY(), sxi = 1 / sx, syi = 1 / sy; + float r = _rotation * MathUtil::Deg_Rad, cosR = MathUtil::cos(r), sinR = MathUtil::sin(r); + float za = (pa * cosR + pb * sinR) * sxi; + float zc = (pc * cosR + pd * sinR) * syi; + float s = 1 / MathUtil::sqrt(za * za + zc * zc); + za *= s; + zc *= s; + float zb = -zc, zd = za; + if (_inherit == Inherit_NoScale && (pa * pd - pb * pc < 0) != ((sx < 0) != (sy < 0))) { + zb = -zb; + zd = -zd; + } + float rx = _shearX * MathUtil::Deg_Rad; + float ry = (90 + _shearY) * MathUtil::Deg_Rad; + float la = MathUtil::cos(rx) * _scaleX; + float lb = MathUtil::cos(ry) * _scaleY; + float lc = MathUtil::sin(rx) * _scaleX; + float ld = MathUtil::sin(ry) * _scaleY; + _a = (za * la + zb * lc) * sx; + _b = (za * lb + zb * ld) * sx; + _c = (zc * la + zd * lc) * sy; + _d = (zc * lb + zd * ld) * sy; + break; + } + } +} + +void BonePose::updateLocalTransform(Skeleton &skeleton) { + _local = 0; + _world = skeleton._update; + + float sx = skeleton.getScaleX(), sy = skeleton.getScaleY(); + if (_bone->getParent() == nullptr) { + float sxi = 1 / sx, syi = 1 / sy; + _x = (_worldX - skeleton.getX()) * sxi; + _y = (_worldY - skeleton.getY()) * syi; + setLocal(_a * sxi, _b * sxi, _c * syi, _d * syi, 0); + return; + } + + BonePose &parent = _bone->getParent()->getAppliedPose(); + float pa = parent._a, pb = parent._b, pc = parent._c, pd = parent._d; + float pad = pa * pd - pb * pc, pid = 1 / pad; + float ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid; + float dx = _worldX - parent._worldX, dy = _worldY - parent._worldY; + _x = dx * ia - dy * ib; + _y = dy * id - dx * ic; + + switch (_inherit) { + case Inherit_Normal: + setLocal(ia * _a - ib * _c, ia * _b - ib * _d, id * _c - ic * _a, id * _d - ic * _b, 0); + break; + case Inherit_OnlyTranslation: { + float sxi = 1 / sx, syi = 1 / sy; + setLocal(_a * sxi, _b * sxi, _c * syi, _d * syi, 0); + break; + } + case Inherit_NoRotationOrReflection: { + float sxi = 1 / sx, syi = 1 / sy; + pa *= sxi; + pc *= syi; + float wa = _a * sxi, wb = _b * sxi, wc = _c * syi, wd = _d * syi; + float s = 1 / (pa * pa + pc * pc), det = 1 / MathUtil::abs(pad * sxi * syi); + setLocal((pa * wa + pc * wc) * s, (pa * wb + pc * wd) * s, (pa * wc - pc * wa) * det, (pa * wd - pc * wb) * det, + MathUtil::atan2Deg(pc, pa)); + break; + } + case Inherit_NoScale: + case Inherit_NoScaleOrReflection: { + float sxi = 1 / sx, syi = 1 / sy; + float wa = _a * sxi, wb = _b * sxi, wc = _c * syi, wd = _d * syi; + float tx = pd * _a - pb * _c, ty = pa * _c - pc * _a; + if (pad < 0) { + tx = -tx; + ty = -ty; + } + float r = MathUtil::atan2Deg(ty, tx); + _rotation = r; + r *= MathUtil::Deg_Rad; + float cosR = MathUtil::cos(r), sinR = MathUtil::sin(r); + float za = (pa * cosR + pb * sinR) * sxi; + float zc = (pc * cosR + pd * sinR) * syi; + float s = 1 / MathUtil::sqrt(za * za + zc * zc); + za *= s; + zc *= s; + float si = _inherit == Inherit_NoScale && (pad < 0) != ((sx < 0) != (sy < 0)) ? -1.0f : 1.0f; + setLocal(za * wa + zc * wc, za * wb + zc * wd, (za * wc - zc * wa) * si, (za * wd - zc * wb) * si); + break; + } + } +} + +void BonePose::setLocal(float ra, float rb, float rc, float rd) { + float x = ra * ra + rc * rc, y = rb * rb + rd * rd; + if (x > MathUtil::EpsilonSq) { + _shearX = MathUtil::atan2Deg(rc, ra); + _scaleX = MathUtil::sqrt(x); + } else { + _shearX = 0; + _scaleX = 0; + } + _scaleY = MathUtil::sqrt(y); + if (y > MathUtil::EpsilonSq) { + _shearY = MathUtil::atan2Deg(rd, rb); + if (ra * rd - rb * rc < 0) { + _scaleY = -_scaleY; + _shearY += 90; + } else + _shearY -= 90; + if (_shearY > 180) + _shearY -= 360; + else if (_shearY <= -180)// + _shearY += 360; + } else + _shearY = 0; +} + +void BonePose::setLocal(float ra, float rb, float rc, float rd, float ro) { + _shearX = 0; + float x = ra * ra + rc * rc, y = rb * rb + rd * rd; + if (x > MathUtil::EpsilonSq) { + float r = MathUtil::atan2Deg(rc, ra); + _rotation = r + ro; + _scaleX = MathUtil::sqrt(x); + _scaleY = MathUtil::sqrt(y); + if (y > MathUtil::EpsilonSq) { + _shearY = MathUtil::atan2Deg(rd, rb); + if (ra * rd - rb * rc < 0) { + _scaleY = -_scaleY; + _shearY += 90 - r; + } else + _shearY -= 90 + r; + if (_shearY > 180) + _shearY -= 360; + else if (_shearY <= -180)// + _shearY += 360; + } else + _shearY = 0; + } else { + _scaleX = 0; + _scaleY = MathUtil::sqrt(y); + _shearY = 0; + _rotation = y > MathUtil::EpsilonSq ? MathUtil::atan2Deg(rd, rb) - 90 + ro : ro; + } +} + +void BonePose::validateLocalTransform(Skeleton &skeleton) { + if (_local == skeleton._update) updateLocalTransform(skeleton); +} + +void BonePose::modifyLocal(Skeleton &skeleton) { + if (_local == skeleton._update) updateLocalTransform(skeleton); + _world = 0; + resetWorld(skeleton, skeleton._update); +} + +void BonePose::modifyWorld(Skeleton &skeleton) { + int update = skeleton._update; + _local = update; + _world = update; + resetWorld(skeleton, update); +} + +void BonePose::resetWorld(Skeleton &skeleton, int update) { + Array &children = _bone->getChildren(); + for (size_t i = 0, n = children.size(); i < n; i++) { + BonePose &child = children[i]->getAppliedPose(); + if (child._world == update) { + if (child._local == update) child.updateLocalTransform(skeleton); + child._world = 0; + child.resetWorld(skeleton, update); + } + } +} + +float BonePose::getA() { + return _a; +} + +void BonePose::setA(float a) { + this->_a = a; +} + +float BonePose::getB() { + return _b; +} + +void BonePose::setB(float b) { + this->_b = b; +} + +float BonePose::getC() { + return _c; +} + +void BonePose::setC(float c) { + this->_c = c; +} + +float BonePose::getD() { + return _d; +} + +void BonePose::setD(float d) { + this->_d = d; +} + +float BonePose::getWorldX() { + return _worldX; +} + +void BonePose::setWorldX(float worldX) { + this->_worldX = worldX; +} + +float BonePose::getWorldY() { + return _worldY; +} + +void BonePose::setWorldY(float worldY) { + this->_worldY = worldY; +} + +float BonePose::getWorldRotationX() { + return MathUtil::atan2(_c, _a) * MathUtil::Rad_Deg; +} + +float BonePose::getWorldRotationY() { + return MathUtil::atan2(_d, _b) * MathUtil::Rad_Deg; +} + +float BonePose::getWorldScaleX() { + return MathUtil::sqrt(_a * _a + _c * _c); +} + +float BonePose::getWorldScaleY() { + return MathUtil::sqrt(_b * _b + _d * _d); +} + + +void BonePose::worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY) { + float det = _a * _d - _b * _c; + float x = worldX - _worldX, y = worldY - _worldY; + outLocalX = (x * _d - y * _b) / det; + outLocalY = (y * _a - x * _c) / det; +} + +void BonePose::localToWorld(float localX, float localY, float &outWorldX, float &outWorldY) { + outWorldX = localX * _a + localY * _b + _worldX; + outWorldY = localX * _c + localY * _d + _worldY; +} + +void BonePose::worldToParent(float worldX, float worldY, float &outParentX, float &outParentY) { + if (_bone->getParent() == nullptr) { + outParentX = worldX; + outParentY = worldY; + } else { + _bone->getParent()->getAppliedPose().worldToLocal(worldX, worldY, outParentX, outParentY); + } +} + +void BonePose::parentToWorld(float parentX, float parentY, float &outWorldX, float &outWorldY) { + if (_bone->getParent() == nullptr) { + outWorldX = parentX; + outWorldY = parentY; + } else { + _bone->getParent()->getAppliedPose().localToWorld(parentX, parentY, outWorldX, outWorldY); + } +} + +float BonePose::worldToLocalRotation(float worldRotation) { + worldRotation *= MathUtil::Deg_Rad; + float sinRot = MathUtil::sin(worldRotation), cosRot = MathUtil::cos(worldRotation); + return MathUtil::atan2(_a * sinRot - _c * cosRot, _d * cosRot - _b * sinRot) * MathUtil::Rad_Deg + _rotation - _shearX; +} + +float BonePose::localToWorldRotation(float localRotation) { + localRotation = (localRotation - _rotation - _shearX) * MathUtil::Deg_Rad; + float sinRot = MathUtil::sin(localRotation), cosRot = MathUtil::cos(localRotation); + return MathUtil::atan2(cosRot * _c + sinRot * _d, cosRot * _a + sinRot * _b) * MathUtil::Rad_Deg; +} + +void BonePose::rotateWorld(float degrees) { + degrees *= MathUtil::Deg_Rad; + float sinRot = MathUtil::sin(degrees), cosRot = MathUtil::cos(degrees); + float ra = _a, rb = _b; + _a = cosRot * ra - sinRot * _c; + _b = cosRot * rb - sinRot * _d; + _c = sinRot * ra + cosRot * _c; + _d = sinRot * rb + cosRot * _d; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BoneTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BoneTimeline.cpp new file mode 100644 index 0000000..6010ff9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BoneTimeline.cpp @@ -0,0 +1,93 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +// Define static constants for BoneTimeline2 +const int BoneTimeline2::ENTRIES = 3; +const int BoneTimeline2::VALUE1 = 1; +const int BoneTimeline2::VALUE2 = 2; + +RTTI_IMPL_NOPARENT(BoneTimeline) + +RTTI_IMPL_MULTI(BoneTimeline1, CurveTimeline1, BoneTimeline) + +BoneTimeline1::BoneTimeline1(size_t frameCount, size_t bezierCount, int boneIndex, Property property) + : CurveTimeline1(frameCount, bezierCount), BoneTimeline(boneIndex), _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) property << 32) | boneIndex}; + setPropertyIds(ids, 1); + _additive = true; +} + +void BoneTimeline1::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + + Bone *bone = skeleton._bones[_boneIndex]; + if (bone->isActive()) { + _apply(appliedPose ? *bone->_appliedPose : bone->_pose, bone->_data._setupPose, time, alpha, from, add, out); + } +} + +RTTI_IMPL_MULTI(BoneTimeline2, CurveTimeline, BoneTimeline) + +BoneTimeline2::BoneTimeline2(size_t frameCount, size_t bezierCount, int boneIndex, Property property1, Property property2) + : CurveTimeline(frameCount, BoneTimeline2::ENTRIES, bezierCount), BoneTimeline(boneIndex), _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) property1 << 32) | boneIndex, ((PropertyId) property2 << 32) | boneIndex}; + setPropertyIds(ids, 2); + _additive = true; +} + +void BoneTimeline2::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + + Bone *bone = skeleton._bones[_boneIndex]; + if (bone->isActive()) { + _apply(appliedPose ? *bone->_appliedPose : bone->_pose, bone->_data._setupPose, time, alpha, from, add, out); + } +} + +void BoneTimeline2::setFrame(size_t frame, float time, float value1, float value2) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + VALUE1] = value1; + _frames[frame + VALUE2] = value2; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BoundingBoxAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BoundingBoxAttachment.cpp new file mode 100644 index 0000000..ffe8663 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/BoundingBoxAttachment.cpp @@ -0,0 +1,47 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL(BoundingBoxAttachment, VertexAttachment) + +BoundingBoxAttachment::BoundingBoxAttachment(const String &name) : VertexAttachment(name), _color(0.38f, 0.94f, 0.0f, 1.0f) { +} + +Color &BoundingBoxAttachment::getColor() { + return _color; +} + +Attachment &BoundingBoxAttachment::copy() { + BoundingBoxAttachment *copy = new (__FILE__, __LINE__) BoundingBoxAttachment(getName()); + copyTo(*copy); + return *copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ClippingAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ClippingAttachment.cpp new file mode 100644 index 0000000..03fb86f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ClippingAttachment.cpp @@ -0,0 +1,76 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +RTTI_IMPL(ClippingAttachment, VertexAttachment) + +ClippingAttachment::ClippingAttachment(const String &name) : VertexAttachment(name), _endSlot(NULL), _convex(false), _inverse(false), _color() { +} + +SlotData *ClippingAttachment::getEndSlot() { + return _endSlot; +} + +void ClippingAttachment::setEndSlot(SlotData *inValue) { + _endSlot = inValue; +} + +bool ClippingAttachment::getConvex() { + return _convex; +} + +void ClippingAttachment::setConvex(bool convex) { + _convex = convex; +} + +bool ClippingAttachment::getInverse() { + return _inverse; +} + +void ClippingAttachment::setInverse(bool inverse) { + _inverse = inverse; +} + +Color &ClippingAttachment::getColor() { + return _color; +} + +Attachment &ClippingAttachment::copy() { + ClippingAttachment *copy = new (__FILE__, __LINE__) ClippingAttachment(getName()); + copyTo(*copy); + copy->_endSlot = _endSlot; + copy->_convex = _convex; + copy->_inverse = _inverse; + return *copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ColorTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ColorTimeline.cpp new file mode 100644 index 0000000..546a8b5 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ColorTimeline.cpp @@ -0,0 +1,507 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(RGBATimeline, SlotCurveTimeline) + +RGBATimeline::RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex) : SlotCurveTimeline(frameCount, ENTRIES, bezierCount, slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, ((PropertyId) Property_Alpha << 32) | slotIndex}; + setPropertyIds(ids, 2); +} + +RGBATimeline::~RGBATimeline() { +} + +void RGBATimeline::setFrame(int frame, float time, float r, float g, float b, float a) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; + _frames[frame + A] = a; +} + +void RGBATimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) { + SP_UNUSED(add); + Color &color = pose._color; + if (time < _frames[0]) { + Color &setup = slot._data._setupPose._color; + switch (from) { + case MixFrom_Setup: + color.set(setup); + break; + case MixFrom_First: + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, (setup.a - color.a) * alpha); + break; + case MixFrom_Current: + break; + } + return; + } + + float r, g, b, a; + int i = Animation::search(_frames, time, ENTRIES); + int curveType = (int) _curves[i / ENTRIES]; + switch (curveType) { + case LINEAR: { + float before = _frames[i]; + r = _frames[i + R]; + g = _frames[i + G]; + b = _frames[i + B]; + a = _frames[i + A]; + float t = (time - before) / (_frames[i + ENTRIES] - before); + r += (_frames[i + ENTRIES + R] - r) * t; + g += (_frames[i + ENTRIES + G] - g) * t; + b += (_frames[i + ENTRIES + B] - b) * t; + a += (_frames[i + ENTRIES + A] - a) * t; + break; + } + case STEPPED: { + r = _frames[i + R]; + g = _frames[i + G]; + b = _frames[i + B]; + a = _frames[i + A]; + break; + } + default: { + r = getBezierValue(time, i, R, curveType - BEZIER); + g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER); + b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER); + a = getBezierValue(time, i, A, curveType + BEZIER_SIZE * 3 - BEZIER); + break; + } + } + + if (alpha == 1) + color.set(r, g, b, a); + else { + if (from == MixFrom_Setup) { + Color &setup = slot._data._setupPose._color; + color.set(setup.r + (r - setup.r) * alpha, setup.g + (g - setup.g) * alpha, setup.b + (b - setup.b) * alpha, + setup.a + (a - setup.a) * alpha); + } else + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } +} + +RTTI_IMPL(RGBTimeline, SlotCurveTimeline) + +RGBTimeline::RGBTimeline(size_t frameCount, size_t bezierCount, int slotIndex) : SlotCurveTimeline(frameCount, ENTRIES, bezierCount, slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex}; + setPropertyIds(ids, 1); +} + +RGBTimeline::~RGBTimeline() { +} + +void RGBTimeline::setFrame(int frame, float time, float r, float g, float b) { + frame <<= 2; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; +} + +void RGBTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) { + SP_UNUSED(add); + Color &color = pose._color; + float r, g, b; + if (time < _frames[0]) { + Color &setup = slot._data._setupPose._color; + switch (from) { + case MixFrom_Setup: + color.r = setup.r; + color.g = setup.g; + color.b = setup.b; + break; + case MixFrom_First: + color.r += (setup.r - color.r) * alpha; + color.g += (setup.g - color.g) * alpha; + color.b += (setup.b - color.b) * alpha; + break; + case MixFrom_Current: + break; + } + return; + } + + int i = Animation::search(_frames, time, ENTRIES); + int curveType = (int) _curves[i >> 2]; + switch (curveType) { + case LINEAR: { + float before = _frames[i]; + r = _frames[i + R]; + g = _frames[i + G]; + b = _frames[i + B]; + float t = (time - before) / (_frames[i + ENTRIES] - before); + r += (_frames[i + ENTRIES + R] - r) * t; + g += (_frames[i + ENTRIES + G] - g) * t; + b += (_frames[i + ENTRIES + B] - b) * t; + break; + } + case STEPPED: { + r = _frames[i + R]; + g = _frames[i + G]; + b = _frames[i + B]; + break; + } + default: { + r = getBezierValue(time, i, R, curveType - BEZIER); + g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER); + b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER); + break; + } + } + + if (alpha != 1) { + if (from == MixFrom_Setup) { + Color &setup = slot._data._setupPose._color; + r = setup.r + (r - setup.r) * alpha; + g = setup.g + (g - setup.g) * alpha; + b = setup.b + (b - setup.b) * alpha; + } else { + r = color.r + (r - color.r) * alpha; + g = color.g + (g - color.g) * alpha; + b = color.b + (b - color.b) * alpha; + } + } + color.r = r < 0 ? 0 : (r > 1 ? 1 : r); + color.g = g < 0 ? 0 : (g > 1 ? 1 : g); + color.b = b < 0 ? 0 : (b > 1 ? 1 : b); +} + +RTTI_IMPL_MULTI(AlphaTimeline, CurveTimeline1, SlotTimeline) + +AlphaTimeline::AlphaTimeline(size_t frameCount, size_t bezierCount, int slotIndex) + : CurveTimeline1(frameCount, bezierCount), SlotTimeline(), _slotIndex(slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Alpha << 32) | slotIndex}; + setPropertyIds(ids, 1); +} + +AlphaTimeline::~AlphaTimeline() { +} + +int AlphaTimeline::getSlotIndex() { + return _slotIndex; +} + +void AlphaTimeline::setSlotIndex(int inValue) { + _slotIndex = inValue; +} + +void AlphaTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(add); + SP_UNUSED(out); + + Slot *slot = skeleton._slots[_slotIndex]; + if (!slot->_bone._active) return; + + Color &color = (appliedPose ? *slot->_appliedPose : slot->_pose)._color; + if (time < _frames[0]) { + float setup = slot->_data._setupPose._color.a; + switch (from) { + case MixFrom_Setup: + color.a = setup; + break; + case MixFrom_First: + color.a += (setup - color.a) * alpha; + break; + case MixFrom_Current: + break; + } + return; + } + + float a = getCurveValue(time); + if (alpha != 1) { + if (from == MixFrom_Setup) { + Color &setup = slot->_data._setupPose._color; + a = setup.a + (a - setup.a) * alpha; + } else + a = color.a + (a - color.a) * alpha; + } + color.a = a < 0 ? 0 : (a > 1 ? 1 : a); +} + +RTTI_IMPL(RGBA2Timeline, SlotCurveTimeline) + +RGBA2Timeline::RGBA2Timeline(size_t frameCount, size_t bezierCount, int slotIndex) : SlotCurveTimeline(frameCount, ENTRIES, bezierCount, slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, ((PropertyId) Property_Alpha << 32) | slotIndex, + ((PropertyId) Property_Rgb2 << 32) | slotIndex}; + setPropertyIds(ids, 3); +} + +RGBA2Timeline::~RGBA2Timeline() { +} + +void RGBA2Timeline::setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2) { + frame <<= 3; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; + _frames[frame + A] = a; + _frames[frame + R2] = r2; + _frames[frame + G2] = g2; + _frames[frame + B2] = b2; +} + +void RGBA2Timeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) { + SP_UNUSED(add); + Color &light = pose._color; + Color &dark = pose._darkColor; + float r2, g2, b2; + if (time < _frames[0]) { + SlotPose &setup = slot._data._setupPose; + Color &setupLight = setup._color; + Color &setupDark = setup._darkColor; + switch (from) { + case MixFrom_Setup: + light.set(setupLight); + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + break; + case MixFrom_First: + light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha, + (setupLight.a - light.a) * alpha); + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + break; + case MixFrom_Current: + break; + } + return; + } + + float r, g, b, a; + int i = Animation::search(_frames, time, ENTRIES); + int curveType = (int) _curves[i >> 3]; + switch (curveType) { + case LINEAR: { + float before = _frames[i]; + r = _frames[i + R]; + g = _frames[i + G]; + b = _frames[i + B]; + a = _frames[i + A]; + r2 = _frames[i + R2]; + g2 = _frames[i + G2]; + b2 = _frames[i + B2]; + float t = (time - before) / (_frames[i + ENTRIES] - before); + r += (_frames[i + ENTRIES + R] - r) * t; + g += (_frames[i + ENTRIES + G] - g) * t; + b += (_frames[i + ENTRIES + B] - b) * t; + a += (_frames[i + ENTRIES + A] - a) * t; + r2 += (_frames[i + ENTRIES + R2] - r2) * t; + g2 += (_frames[i + ENTRIES + G2] - g2) * t; + b2 += (_frames[i + ENTRIES + B2] - b2) * t; + break; + } + case STEPPED: { + r = _frames[i + R]; + g = _frames[i + G]; + b = _frames[i + B]; + a = _frames[i + A]; + r2 = _frames[i + R2]; + g2 = _frames[i + G2]; + b2 = _frames[i + B2]; + break; + } + default: { + r = getBezierValue(time, i, R, curveType - BEZIER); + g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER); + b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER); + a = getBezierValue(time, i, A, curveType + BEZIER_SIZE * 3 - BEZIER); + r2 = getBezierValue(time, i, R2, curveType + BEZIER_SIZE * 4 - BEZIER); + g2 = getBezierValue(time, i, G2, curveType + BEZIER_SIZE * 5 - BEZIER); + b2 = getBezierValue(time, i, B2, curveType + BEZIER_SIZE * 6 - BEZIER); + break; + } + } + + if (alpha == 1) + light.set(r, g, b, a); + else if (from == MixFrom_Setup) { + SlotPose &setup = slot._data._setupPose; + Color &setupLight = setup._color; + light.set(setupLight.r + (r - setupLight.r) * alpha, setupLight.g + (g - setupLight.g) * alpha, setupLight.b + (b - setupLight.b) * alpha, + setupLight.a + (a - setupLight.a) * alpha); + Color &setupDark = setup._darkColor; + r2 = setupDark.r + (r2 - setupDark.r) * alpha; + g2 = setupDark.g + (g2 - setupDark.g) * alpha; + b2 = setupDark.b + (b2 - setupDark.b) * alpha; + } else { + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + r2 = dark.r + (r2 - dark.r) * alpha; + g2 = dark.g + (g2 - dark.g) * alpha; + b2 = dark.b + (b2 - dark.b) * alpha; + } + + dark.r = r2 < 0 ? 0 : (r2 > 1 ? 1 : r2); + dark.g = g2 < 0 ? 0 : (g2 > 1 ? 1 : g2); + dark.b = b2 < 0 ? 0 : (b2 > 1 ? 1 : b2); +} + +RTTI_IMPL(RGB2Timeline, SlotCurveTimeline) + +RGB2Timeline::RGB2Timeline(size_t frameCount, size_t bezierCount, int slotIndex) : SlotCurveTimeline(frameCount, ENTRIES, bezierCount, slotIndex) { + PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, ((PropertyId) Property_Rgb2 << 32) | slotIndex}; + setPropertyIds(ids, 2); +} + +RGB2Timeline::~RGB2Timeline() { +} + +void RGB2Timeline::setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + R] = r; + _frames[frame + G] = g; + _frames[frame + B] = b; + _frames[frame + R2] = r2; + _frames[frame + G2] = g2; + _frames[frame + B2] = b2; +} + +void RGB2Timeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) { + SP_UNUSED(add); + Color &light = pose._color; + Color &dark = pose._darkColor; + float r, g, b, r2, g2, b2; + if (time < _frames[0]) { + SlotPose &setup = slot._data._setupPose; + Color &setupLight = setup._color; + Color &setupDark = setup._darkColor; + switch (from) { + case MixFrom_Setup: + light.r = setupLight.r; + light.g = setupLight.g; + light.b = setupLight.b; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + break; + case MixFrom_First: + light.r += (setupLight.r - light.r) * alpha; + light.g += (setupLight.g - light.g) * alpha; + light.b += (setupLight.b - light.b) * alpha; + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + break; + case MixFrom_Current: + break; + } + return; + } + + int i = Animation::search(_frames, time, ENTRIES); + int curveType = (int) _curves[i / ENTRIES]; + switch (curveType) { + case LINEAR: { + float before = _frames[i]; + r = _frames[i + R]; + g = _frames[i + G]; + b = _frames[i + B]; + r2 = _frames[i + R2]; + g2 = _frames[i + G2]; + b2 = _frames[i + B2]; + float t = (time - before) / (_frames[i + ENTRIES] - before); + r += (_frames[i + ENTRIES + R] - r) * t; + g += (_frames[i + ENTRIES + G] - g) * t; + b += (_frames[i + ENTRIES + B] - b) * t; + r2 += (_frames[i + ENTRIES + R2] - r2) * t; + g2 += (_frames[i + ENTRIES + G2] - g2) * t; + b2 += (_frames[i + ENTRIES + B2] - b2) * t; + break; + } + case STEPPED: { + r = _frames[i + R]; + g = _frames[i + G]; + b = _frames[i + B]; + r2 = _frames[i + R2]; + g2 = _frames[i + G2]; + b2 = _frames[i + B2]; + break; + } + default: { + r = getBezierValue(time, i, R, curveType - BEZIER); + g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER); + b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER); + r2 = getBezierValue(time, i, R2, curveType + BEZIER_SIZE * 3 - BEZIER); + g2 = getBezierValue(time, i, G2, curveType + BEZIER_SIZE * 4 - BEZIER); + b2 = getBezierValue(time, i, B2, curveType + BEZIER_SIZE * 5 - BEZIER); + break; + } + } + + if (alpha != 1) { + if (from == MixFrom_Setup) { + SlotPose &setup = slot._data._setupPose; + Color &setupLight = setup._color; + r = setupLight.r + (r - setupLight.r) * alpha; + g = setupLight.g + (g - setupLight.g) * alpha; + b = setupLight.b + (b - setupLight.b) * alpha; + Color &setupDark = setup._darkColor; + r2 = setupDark.r + (r2 - setupDark.r) * alpha; + g2 = setupDark.g + (g2 - setupDark.g) * alpha; + b2 = setupDark.b + (b2 - setupDark.b) * alpha; + } else { + r = light.r + (r - light.r) * alpha; + g = light.g + (g - light.g) * alpha; + b = light.b + (b - light.b) * alpha; + r2 = dark.r + (r2 - dark.r) * alpha; + g2 = dark.g + (g2 - dark.g) * alpha; + b2 = dark.b + (b2 - dark.b) * alpha; + } + } + + light.r = r < 0 ? 0 : (r > 1 ? 1 : r); + light.g = g < 0 ? 0 : (g > 1 ? 1 : g); + light.b = b < 0 ? 0 : (b > 1 ? 1 : b); + dark.r = r2 < 0 ? 0 : (r2 > 1 ? 1 : r2); + dark.g = g2 < 0 ? 0 : (g2 > 1 ? 1 : g2); + dark.b = b2 < 0 ? 0 : (b2 > 1 ? 1 : b2); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Constraint.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Constraint.cpp new file mode 100644 index 0000000..b9eb21e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Constraint.cpp @@ -0,0 +1,40 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL(Constraint, Update) + +Constraint::Constraint() { +} + +Constraint::~Constraint() { +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ConstraintData.cpp new file mode 100644 index 0000000..b8fee72 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ConstraintData.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(ConstraintData) \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ConstraintTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ConstraintTimeline.cpp new file mode 100644 index 0000000..e7c7751 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ConstraintTimeline.cpp @@ -0,0 +1,40 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(ConstraintTimeline) + +ConstraintTimeline::ConstraintTimeline() { +} + +ConstraintTimeline::~ConstraintTimeline() { +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ConstraintTimeline1.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ConstraintTimeline1.cpp new file mode 100644 index 0000000..9ddd0ee --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ConstraintTimeline1.cpp @@ -0,0 +1,43 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL_MULTI(ConstraintTimeline1, CurveTimeline1, ConstraintTimeline) + +ConstraintTimeline1::ConstraintTimeline1(size_t frameCount, size_t bezierCount, int constraintIndex, Property property) + : CurveTimeline1(frameCount, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex) { + PropertyId ids[] = {((PropertyId) property << 32) | constraintIndex}; + setPropertyIds(ids, 1); +} + +ConstraintTimeline1::~ConstraintTimeline1() { +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/CurveTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/CurveTimeline.cpp new file mode 100644 index 0000000..6dfbf9c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/CurveTimeline.cpp @@ -0,0 +1,171 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +RTTI_IMPL(CurveTimeline, Timeline) + +CurveTimeline::CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount) : Timeline(frameCount, frameEntries) { + _curves.setSize(frameCount + bezierCount * BEZIER_SIZE, 0); + _curves[frameCount - 1] = STEPPED; +} + +CurveTimeline::~CurveTimeline() { +} + +void CurveTimeline::setLinear(size_t frame) { + _curves[frame] = LINEAR; +} + +void CurveTimeline::setStepped(size_t frame) { + _curves[frame] = STEPPED; +} + +void CurveTimeline::setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, float cy2, + float time2, float value2) { + size_t i = getFrameCount() + bezier * BEZIER_SIZE; + if (value == 0) _curves[frame] = BEZIER + i; + float tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03; + float dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 0.006; + float ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + float dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667; + float x = time1 + dx, y = value1 + dy; + for (size_t n = i + BEZIER_SIZE; i < n; i += 2) { + _curves[i] = x; + _curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } +} + +float CurveTimeline::getBezierValue(float time, size_t frameIndex, size_t valueOffset, size_t i) { + if (_curves[i] > time) { + float x = _frames[frameIndex], y = _frames[frameIndex + valueOffset]; + return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y); + } + size_t n = i + BEZIER_SIZE; + for (i += 2; i < n; i += 2) { + if (_curves[i] >= time) { + float x = _curves[i - 2], y = _curves[i - 1]; + return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y); + } + } + frameIndex += getFrameEntries(); + float x = _curves[n - 2], y = _curves[n - 1]; + return y + (time - x) / (_frames[frameIndex] - x) * (_frames[frameIndex + valueOffset] - y); +} + +Array &CurveTimeline::getCurves() { + return _curves; +} + +RTTI_IMPL(CurveTimeline1, CurveTimeline) + +CurveTimeline1::CurveTimeline1(size_t frameCount, size_t bezierCount) : CurveTimeline(frameCount, CurveTimeline1::ENTRIES, bezierCount) { +} + +CurveTimeline1::~CurveTimeline1() { +} + +void CurveTimeline1::setFrame(size_t frame, float time, float value) { + frame <<= 1; + _frames[frame] = time; + _frames[frame + CurveTimeline1::VALUE] = value; +} + +float CurveTimeline1::getCurveValue(float time) { + int i = (int) _frames.size() - 2; + for (int ii = 2; ii <= i; ii += 2) { + if (_frames[ii] > time) { + i = ii - 2; + break; + } + } + + int curveType = (int) _curves[i >> 1]; + switch (curveType) { + case CurveTimeline::LINEAR: { + float before = _frames[i], value = _frames[i + CurveTimeline1::VALUE]; + return value + + (time - before) / (_frames[i + CurveTimeline1::ENTRIES] - before) * + (_frames[i + CurveTimeline1::ENTRIES + CurveTimeline1::VALUE] - value); + } + case CurveTimeline::STEPPED: + return _frames[i + CurveTimeline1::VALUE]; + } + return getBezierValue(time, i, CurveTimeline1::VALUE, curveType - CurveTimeline1::BEZIER); +} + +float CurveTimeline1::getRelativeValue(float time, float alpha, MixFrom from, bool add, float current, float setup) { + if (time < _frames[0]) return beforeFirstKey(from, alpha, current, setup); + float value = getCurveValue(time); + return from == MixFrom_Setup ? setup + value * alpha : current + (add ? value : value + setup - current) * alpha; +} + +float CurveTimeline1::getAbsoluteValue(float time, float alpha, MixFrom from, bool add, float current, float setup) { + if (time < _frames[0]) return beforeFirstKey(from, alpha, current, setup); + float value = getCurveValue(time); + return from == MixFrom_Setup ? setup + (add ? value : value - setup) * alpha : current + (add ? value : value - current) * alpha; +} + +float CurveTimeline1::getAbsoluteValue(float time, float alpha, MixFrom from, bool add, float current, float setup, float value) { + if (time < _frames[0]) return beforeFirstKey(from, alpha, current, setup); + return from == MixFrom_Setup ? setup + (add ? value : value - setup) * alpha : current + (add ? value : value - current) * alpha; +} + +float CurveTimeline1::getScaleValue(float time, float alpha, MixFrom from, bool add, bool out, float current, float setup) { + if (time < _frames[0]) return beforeFirstKey(from, alpha, current, setup); + float value = getCurveValue(time) * setup; + if (alpha == 1 && !add) return value; + float base = from == MixFrom_Setup ? setup : current; + if (add) return base + (value - setup) * alpha; + if (out) return base + (MathUtil::abs(value) * MathUtil::sign(base) - base) * alpha; + base = MathUtil::abs(base) * MathUtil::sign(value); + return base + (value - base) * alpha; +} + +float CurveTimeline1::beforeFirstKey(MixFrom from, float alpha, float current, float setup) { + switch (from) { + case MixFrom_Setup: + return setup; + case MixFrom_First: + return current + (setup - current) * alpha; + case MixFrom_Current: + return current; + } + return current; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/DeformTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/DeformTimeline.cpp new file mode 100644 index 0000000..07e497b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/DeformTimeline.cpp @@ -0,0 +1,357 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(DeformTimeline, SlotCurveTimeline) + +DeformTimeline::DeformTimeline(size_t frameCount, size_t bezierCount, int slotIndex, VertexAttachment &attachment) + : SlotCurveTimeline(frameCount, 1, bezierCount, slotIndex), _attachment(&attachment) { + PropertyId ids[] = {((PropertyId) Property_Deform << 32) | ((slotIndex << 16 | attachment._id) & 0xffffffff)}; + setPropertyIds(ids, 1); + _additive = true; + + _vertices.ensureCapacity(frameCount); + for (size_t i = 0; i < frameCount; ++i) { + Array vec; + _vertices.add(vec); + } +} + + +void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(out); + + Array &slots = skeleton.getSlots(); + if (!_attachment->isTimelineActive(slots, getSlotIndex(), appliedPose)) return; + Array &timelineSlots = _attachment->getTimelineSlots(); + + Array &frames = _frames; + if (time < frames[0]) { + applyBeforeFirst(*slots[getSlotIndex()], appliedPose, alpha, from); + for (size_t i = 0; i < timelineSlots.size(); ++i) applyBeforeFirst(*slots[timelineSlots[i]], appliedPose, alpha, from); + return; + } + + Array *v1 = NULL; + Array *v2 = NULL; + float percent = 0; + if (time >= frames[frames.size() - 1]) { + v1 = &_vertices[frames.size() - 1]; + } else { + int frame = Animation::search(frames, time); + percent = getCurvePercent(time, frame); + v1 = &_vertices[frame]; + v2 = &_vertices[frame + 1]; + } + + size_t vertexCount = _vertices[0].size(); + applyToSlot(*slots[getSlotIndex()], appliedPose, *v1, v2, percent, vertexCount, alpha, from, add); + for (size_t i = 0; i < timelineSlots.size(); ++i) + applyToSlot(*slots[timelineSlots[i]], appliedPose, *v1, v2, percent, vertexCount, alpha, from, add); +} + +void DeformTimeline::applyBeforeFirst(Slot &slot, bool appliedPose, float alpha, MixFrom from) { + if (!slot.getBone().isActive()) return; + SlotPose &pose = appliedPose ? slot.getAppliedPose() : slot.getPose(); + Attachment *attachment = pose.getAttachment(); + if (attachment == NULL || attachment->getTimelineAttachment() != _attachment) return; + Array &deformArray = pose.getDeform(); + if (deformArray.size() == 0) from = MixFrom_Setup; + switch (from) { + case MixFrom_Setup: + deformArray.clear(); + break; + case MixFrom_First: { + if (alpha == 1) { + deformArray.clear(); + return; + } + size_t vertexCount = _vertices[0].size(); + deformArray.setSize(vertexCount, 0); + VertexAttachment *vertexAttachment = static_cast(attachment); + if (vertexAttachment->getBones().size() == 0) { + Array &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) deformArray[i] += (setupVertices[i] - deformArray[i]) * alpha; + } else { + float a = 1 - alpha; + for (size_t i = 0; i < vertexCount; i++) deformArray[i] *= a; + } + break; + } + case MixFrom_Current: + break; + } +} + +void DeformTimeline::applyToPose(SlotPose &pose, Array &v1, Array *v2, float percent, size_t vertexCount, float alpha, MixFrom from, + bool add) { + Attachment *slotAttachment = pose.getAttachment(); + if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) return; + + VertexAttachment *vertexAttachment = static_cast(slotAttachment); + if (vertexAttachment->getTimelineAttachment() != _attachment) return; + + Array &deformArray = pose.getDeform(); + if (deformArray.size() == 0) from = MixFrom_Setup; + bool fromSetup = from == MixFrom_Setup; + deformArray.setSize(vertexCount, 0); + Array &deform = deformArray; + + if (v2 == NULL) { + if (alpha == 1) { + if (add && !fromSetup) { + if (vertexAttachment->getBones().size() == 0) { + Array &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) deform[i] += v1[i] - setupVertices[i]; + } else { + for (size_t i = 0; i < vertexCount; i++) deform[i] += v1[i]; + } + } else { + memcpy(deform.buffer(), v1.buffer(), vertexCount * sizeof(float)); + } + } else if (fromSetup) { + if (vertexAttachment->getBones().size() == 0) { + Array &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float setup = setupVertices[i]; + deform[i] = setup + (v1[i] - setup) * alpha; + } + } else { + for (size_t i = 0; i < vertexCount; i++) deform[i] = v1[i] * alpha; + } + } else if (add) { + if (vertexAttachment->getBones().size() == 0) { + Array &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) deform[i] += (v1[i] - setupVertices[i]) * alpha; + } else { + for (size_t i = 0; i < vertexCount; i++) deform[i] += v1[i] * alpha; + } + } else { + for (size_t i = 0; i < vertexCount; i++) deform[i] += (v1[i] - deform[i]) * alpha; + } + return; + } + + if (alpha == 1) { + if (add && !fromSetup) { + if (vertexAttachment->getBones().size() == 0) { + Array &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = v1[i]; + deform[i] += prev + ((*v2)[i] - prev) * percent - setupVertices[i]; + } + } else { + for (size_t i = 0; i < vertexCount; i++) { + float prev = v1[i]; + deform[i] += prev + ((*v2)[i] - prev) * percent; + } + } + } else if (percent == 0) { + memcpy(deform.buffer(), v1.buffer(), vertexCount * sizeof(float)); + } else { + for (size_t i = 0; i < vertexCount; i++) { + float prev = v1[i]; + deform[i] = prev + ((*v2)[i] - prev) * percent; + } + } + } else if (fromSetup) { + if (vertexAttachment->getBones().size() == 0) { + Array &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = v1[i], setup = setupVertices[i]; + deform[i] = setup + (prev + ((*v2)[i] - prev) * percent - setup) * alpha; + } + } else { + for (size_t i = 0; i < vertexCount; i++) { + float prev = v1[i]; + deform[i] = (prev + ((*v2)[i] - prev) * percent) * alpha; + } + } + } else if (add) { + if (vertexAttachment->getBones().size() == 0) { + Array &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) { + float prev = v1[i]; + deform[i] += (prev + ((*v2)[i] - prev) * percent - setupVertices[i]) * alpha; + } + } else { + for (size_t i = 0; i < vertexCount; i++) { + float prev = v1[i]; + deform[i] += (prev + ((*v2)[i] - prev) * percent) * alpha; + } + } + } else { + for (size_t i = 0; i < vertexCount; i++) { + float prev = v1[i]; + deform[i] += (prev + ((*v2)[i] - prev) * percent - deform[i]) * alpha; + } + } +} + +void DeformTimeline::applyToSlot(Slot &slot, bool appliedPose, Array &v1, Array *v2, float percent, size_t vertexCount, float alpha, + MixFrom from, bool add) { + if (!slot.getBone().isActive()) return; + SlotPose &pose = appliedPose ? slot.getAppliedPose() : slot.getPose(); + Attachment *attachment = pose.getAttachment(); + if (attachment == NULL || attachment->getTimelineAttachment() != _attachment) return; + applyToPose(pose, v1, v2, percent, vertexCount, alpha, from, add); +} + +void DeformTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) { + Array &frames = _frames; + if (time < frames[0]) { + Array &deformArray = pose.getDeform(); + if (deformArray.size() == 0) from = MixFrom_Setup; + switch (from) { + case MixFrom_Setup: + deformArray.clear(); + break; + case MixFrom_First: { + if (alpha == 1) { + deformArray.clear(); + return; + } + size_t vertexCount = _vertices[0].size(); + deformArray.setSize(vertexCount, 0); + VertexAttachment *vertexAttachment = static_cast(pose.getAttachment()); + if (vertexAttachment->getBones().size() == 0) { + Array &setupVertices = vertexAttachment->getVertices(); + for (size_t i = 0; i < vertexCount; i++) deformArray[i] += (setupVertices[i] - deformArray[i]) * alpha; + } else { + float a = 1 - alpha; + for (size_t i = 0; i < vertexCount; i++) deformArray[i] *= a; + } + break; + } + case MixFrom_Current: + break; + } + return; + } + + Array *v1 = NULL; + Array *v2 = NULL; + float percent = 0; + if (time >= frames[frames.size() - 1]) { + v1 = &_vertices[frames.size() - 1]; + } else { + int frame = Animation::search(frames, time); + percent = getCurvePercent(time, frame); + v1 = &_vertices[frame]; + v2 = &_vertices[frame + 1]; + } + + applyToPose(pose, *v1, v2, percent, _vertices[0].size(), alpha, from, add); +} + +void DeformTimeline::setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, float cy2, + float time2, float value2) { + SP_UNUSED(value1); + SP_UNUSED(value2); + Array &curves = _curves; + size_t i = getFrameCount() + bezier * BEZIER_SIZE; + if (value == 0) curves[frame] = BEZIER + (float) i; + float tmpx = (time1 - cx1 * 2 + cx2) * 0.03f, tmpy = cy2 * 0.03f - cy1 * 0.06f; + float dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006f, dddy = (cy1 - cy2 + 0.33333333f) * 0.018f; + float ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + float dx = (cx1 - time1) * 0.3f + tmpx + dddx * 0.16666667f, dy = cy1 * 0.3f + tmpy + dddy * 0.16666667f; + float x = time1 + dx, y = dy; + for (size_t n = i + BEZIER_SIZE; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } +} + +float DeformTimeline::getCurvePercent(float time, int frame) { + Array &curves = _curves; + int i = (int) curves[frame]; + switch (i) { + case LINEAR: { + float x = _frames[frame]; + return (time - x) / (_frames[frame + getFrameEntries()] - x); + } + case STEPPED: { + return 0; + } + } + i -= BEZIER; + if (curves[i] > time) { + float x = _frames[frame]; + return curves[i + 1] * (time - x) / (curves[i] - x); + } + int n = i + BEZIER_SIZE; + for (i += 2; i < n; i += 2) { + if (curves[i] >= time) { + float x = curves[i - 2], y = curves[i - 1]; + return y + (time - x) / (curves[i] - x) * (curves[i + 1] - y); + } + } + float x = curves[n - 2], y = curves[n - 1]; + return y + (1 - y) * (time - x) / (_frames[frame + getFrameEntries()] - x); +} + +void DeformTimeline::setFrame(int frame, float time, Array &vertices) { + _frames[frame] = time; + _vertices[frame].clear(); + _vertices[frame].addAll(vertices); +} + +Array> &DeformTimeline::getVertices() { + return _vertices; +} + +VertexAttachment &DeformTimeline::getAttachment() { + return *_attachment; +} + +void DeformTimeline::setAttachment(VertexAttachment &inValue) { + _attachment = &inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/DrawOrder.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/DrawOrder.cpp new file mode 100644 index 0000000..ef248cc --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/DrawOrder.cpp @@ -0,0 +1,69 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +DrawOrder::DrawOrder(Array &setupPose) : _setupPose(setupPose), _pose(), _constrainedPose(), _appliedPose(&_pose) { +} + +void DrawOrder::setupPose() { + _pose.clear(); + _pose.setSize(_setupPose.size(), NULL); + for (size_t i = 0, n = _setupPose.size(); i < n; ++i) { + _pose[i] = _setupPose[i]; + } +} + +Array &DrawOrder::getPose() { + return _pose; +} + +Array &DrawOrder::getAppliedPose() { + return *_appliedPose; +} + +void DrawOrder::unconstrained() { + _appliedPose = &_pose; +} + +void DrawOrder::constrained() { + _appliedPose = &_constrainedPose; +} + +void DrawOrder::reset() { + _constrainedPose.clear(); + _constrainedPose.setSize(_pose.size(), NULL); + for (size_t i = 0, n = _pose.size(); i < n; ++i) { + _constrainedPose[i] = _pose[i]; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/DrawOrderFolderTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/DrawOrderFolderTimeline.cpp new file mode 100644 index 0000000..5c9e1c3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/DrawOrderFolderTimeline.cpp @@ -0,0 +1,113 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(DrawOrderFolderTimeline, Timeline) + +DrawOrderFolderTimeline::DrawOrderFolderTimeline(size_t frameCount, Array &slots, size_t slotCount) : Timeline(frameCount, 1) { + Array ids(slots.size()); + for (size_t i = 0; i < slots.size(); ++i) ids.add(((PropertyId) Property_DrawOrderFolder << 32) | (PropertyId) slots[i]); + setPropertyIds(ids.buffer(), ids.size()); + + _slots.addAll(slots); + _drawOrders.ensureCapacity(frameCount); + _inFolder.setSize(slotCount, false); + for (size_t i = 0; i < _slots.size(); ++i) _inFolder[_slots[i]] = true; + _instant = true; + for (size_t i = 0; i < frameCount; ++i) { + Array vec; + _drawOrders.add(vec); + } +} + +void DrawOrderFolderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, + bool out, bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(alpha); + SP_UNUSED(add); + Array &pose = appliedPose ? skeleton._drawOrder.getAppliedPose() : skeleton._drawOrder.getPose(); + Array &setupPose = skeleton._slots; + + if (out || time < _frames[0]) { + if (from != MixFrom_Current) setup(pose, setupPose); + } else { + Array &drawOrder = _drawOrders[Animation::search(_frames, time)]; + if (drawOrder.size() == 0) + setup(pose, setupPose); + else + apply(pose, setupPose, drawOrder); + } +} + +size_t DrawOrderFolderTimeline::getFrameCount() { + return _frames.size(); +} + +Array &DrawOrderFolderTimeline::getSlots() { + return _slots; +} + +Array> &DrawOrderFolderTimeline::getDrawOrders() { + return _drawOrders; +} + +void DrawOrderFolderTimeline::setFrame(size_t frame, float time, Array *drawOrder) { + _frames[frame] = time; + _drawOrders[frame].clear(); + if (drawOrder != NULL) _drawOrders[frame].addAll(*drawOrder); +} + +void DrawOrderFolderTimeline::setup(Array &pose, Array &setupPose) { + for (size_t i = 0, found = 0, done = _slots.size();; ++i) { + if (_inFolder[pose[i]->getData().getIndex()]) { + pose[i] = setupPose[_slots[found]]; + if (++found == done) break; + } + } +} + +void DrawOrderFolderTimeline::apply(Array &pose, Array &setupPose, Array &drawOrderIndices) { + for (size_t i = 0, found = 0, done = _slots.size();; ++i) { + if (_inFolder[pose[i]->getData().getIndex()]) { + pose[i] = setupPose[_slots[drawOrderIndices[found]]]; + if (++found == done) break; + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/DrawOrderTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/DrawOrderTimeline.cpp new file mode 100644 index 0000000..1282c15 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -0,0 +1,102 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(DrawOrderTimeline, Timeline) + +PropertyId DrawOrderTimeline::getPropertyId() { + return ((PropertyId) Property_DrawOrder << 32); +} + +DrawOrderTimeline::DrawOrderTimeline(size_t frameCount) : Timeline(frameCount, 1) { + PropertyId ids[] = {getPropertyId()}; + setPropertyIds(ids, 1); + _instant = true; + + _drawOrders.ensureCapacity(frameCount); + for (size_t i = 0; i < frameCount; ++i) { + Array vec; + _drawOrders.add(vec); + } +} + +void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) { + SP_UNUSED(appliedPose); + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(alpha); + SP_UNUSED(add); + + Array &pose = appliedPose ? skeleton._drawOrder.getAppliedPose() : skeleton._drawOrder.getPose(); + Array &setup = skeleton._slots; + if (out || time < _frames[0]) { + if (from != MixFrom_Current) { + pose.setSize(setup.size(), NULL); + for (size_t i = 0, n = setup.size(); i < n; ++i) pose[i] = setup[i]; + } + return; + } + + Array &drawOrderToSetupIndex = _drawOrders[Animation::search(_frames, time)]; + if (drawOrderToSetupIndex.size() == 0) { + pose.setSize(setup.size(), NULL); + for (size_t i = 0, n = setup.size(); i < n; ++i) pose[i] = setup[i]; + } else { + pose.setSize(drawOrderToSetupIndex.size(), NULL); + for (size_t i = 0, n = drawOrderToSetupIndex.size(); i < n; ++i) pose[i] = setup[drawOrderToSetupIndex[i]]; + } +} + +void DrawOrderTimeline::setFrame(size_t frame, float time, Array *drawOrder) { + _frames[frame] = time; + _drawOrders[frame].clear(); + if (drawOrder != NULL) { + _drawOrders[frame].addAll(*drawOrder); + } +} + +size_t DrawOrderTimeline::getFrameCount() { + return _frames.size(); +} + +Array> &DrawOrderTimeline::getDrawOrders() { + return _drawOrders; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Event.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Event.cpp new file mode 100644 index 0000000..fa6cfb7 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Event.cpp @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +Event::Event(float time, const EventData &data) : _data(data), _time(time), _intValue(0), _floatValue(0), _stringValue(), _volume(0), _balance(0) { +} + +const EventData &Event::getData() { + return _data; +} + +float Event::getTime() { + return _time; +} + +int Event::getInt() { + return _intValue; +} + +void Event::setInt(int inValue) { + _intValue = inValue; +} + +float Event::getFloat() { + return _floatValue; +} + +void Event::setFloat(float inValue) { + _floatValue = inValue; +} + +const String &Event::getString() { + return _stringValue; +} + +void Event::setString(const String &inValue) { + _stringValue = inValue; +} + + +float Event::getVolume() { + return _volume; +} + +void Event::setVolume(float inValue) { + _volume = inValue; +} + +float Event::getBalance() { + return _balance; +} + +void Event::setBalance(float inValue) { + _balance = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/EventData.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/EventData.cpp new file mode 100644 index 0000000..5db90fa --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/EventData.cpp @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +EventData::EventData(const String &name) : _name(name), _audioPath(), _setupPose(-1, *this) { + assert(_name.length() > 0); +} + +/// The name of the event, which is unique within the skeleton. +const String &EventData::getName() const { + return _name; +} + +Event &EventData::getSetupPose() { + return _setupPose; +} + +const Event &EventData::getSetupPose() const { + return _setupPose; +} + +const String &EventData::getAudioPath() const { + return _audioPath; +} + +void EventData::setAudioPath(const String &inValue) { + _audioPath = inValue; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/EventTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/EventTimeline.cpp new file mode 100644 index 0000000..4ca3053 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/EventTimeline.cpp @@ -0,0 +1,106 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(EventTimeline, Timeline) + +EventTimeline::EventTimeline(size_t frameCount) : Timeline(frameCount, 1) { + PropertyId ids[] = {((PropertyId) Property_Event << 32)}; + setPropertyIds(ids, 1); + _events.setSize(frameCount, NULL); + _instant = true; +} + +EventTimeline::~EventTimeline() { + ArrayUtils::deleteElements(_events); +} + +void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *pEvents, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) { + SP_UNUSED(skeleton); + if (pEvents == NULL) return; + + Array &events = *pEvents; + + size_t frameCount = _frames.size(); + + if (lastTime > time) { + // Apply after lastTime for looped animations. + apply(skeleton, lastTime, FLT_MAX, pEvents, 0, MixFrom_Current, false, false, false); + lastTime = -1.0f; + } else if (lastTime >= _frames[frameCount - 1]) { + // Last time is after last frame. + return; + } + + if (time < _frames[0]) return;// Time is before first frame. + + int i; + if (lastTime < _frames[0]) { + i = 0; + } else { + i = Animation::search(_frames, lastTime) + 1; + float frameTime = _frames[i]; + while (i > 0) { + // Fire multiple events with the same frame. + if (_frames[i - 1] != frameTime) break; + i--; + } + } + + for (; (size_t) i < frameCount && time >= _frames[i]; i++) events.add(_events[i]); +} + +void EventTimeline::setFrame(size_t frame, Event &event) { + _frames[frame] = event.getTime(); + _events[frame] = &event; +} + +size_t EventTimeline::getFrameCount() { + return _frames.size(); +} + +Array &EventTimeline::getEvents() { + return _events; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Extension.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Extension.cpp new file mode 100644 index 0000000..8369aae --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Extension.cpp @@ -0,0 +1,124 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +#include + +using namespace spine; + +SpineExtension *SpineExtension::_instance = NULL; + +void SpineExtension::setInstance(SpineExtension *inValue) { + assert(inValue); + + _instance = inValue; +} + +SpineExtension *SpineExtension::getInstance() { + if (!_instance) _instance = getDefaultExtension(); + assert(_instance); + + return _instance; +} + +SpineExtension::~SpineExtension() { +} + +SpineExtension::SpineExtension() { +} + +DefaultSpineExtension::~DefaultSpineExtension() { +} + +void *DefaultSpineExtension::_alloc(size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + if (size == 0) return 0; + void *ptr = ::malloc(size); + return ptr; +} + +void *DefaultSpineExtension::_calloc(size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + if (size == 0) return 0; + + void *ptr = ::malloc(size); + if (ptr) { + memset(ptr, 0, size); + } + return ptr; +} + +void *DefaultSpineExtension::_realloc(void *ptr, size_t size, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + void *mem = NULL; + if (size == 0) return 0; + if (ptr == NULL) + mem = ::malloc(size); + else + mem = ::realloc(ptr, size); + return mem; +} + +void DefaultSpineExtension::_free(void *mem, const char *file, int line) { + SP_UNUSED(file); + SP_UNUSED(line); + + ::free(mem); +} + +char *DefaultSpineExtension::_readFile(const String &path, int *length) { +#if !defined(__EMSCRIPTEN__) && !defined(SPINE_NO_FILE_IO) + char *data; + FILE *file = fopen(path.buffer(), "rb"); + if (!file) return 0; + + fseek(file, 0, SEEK_END); + *length = (int) ftell(file); + fseek(file, 0, SEEK_SET); + + data = SpineExtension::alloc(*length, __FILE__, __LINE__); + fread(data, 1, *length, file); + fclose(file); + + return data; +#else + return nullptr; +#endif +} + +DefaultSpineExtension::DefaultSpineExtension() : SpineExtension() { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/IkConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/IkConstraint.cpp new file mode 100644 index 0000000..4a5af58 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/IkConstraint.cpp @@ -0,0 +1,327 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(IkConstraint, Constraint) + +IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : IkConstraintBase(data), _target(skeleton._bones[data._target->getIndex()]) { + + _bones.ensureCapacity(data._bones.size()); + for (size_t i = 0; i < data._bones.size(); i++) { + BoneData *boneData = data._bones[i]; + _bones.add(&skeleton._bones[boneData->getIndex()]->_constrainedPose); + } +} + +IkConstraint &IkConstraint::copy(Skeleton &skeleton) { + IkConstraint *copy = new (__FILE__, __LINE__) IkConstraint(_data, skeleton); + copy->_pose.set(_pose); + return *copy; +} + +void IkConstraint::update(Skeleton &skeleton, Physics physics) { + IkConstraintPose &p = *_appliedPose; + if (p._mix == 0) return; + BonePose &target = *_target->_appliedPose; + switch (_bones.size()) { + case 1: { + apply(skeleton, *_bones[0], target._worldX, target._worldY, p._compress, p._stretch, _data._scaleYMode, p._mix); + } break; + case 2: { + apply(skeleton, *_bones[0], *_bones[1], target._worldX, target._worldY, p._bendDirection, p._stretch, _data._scaleYMode, p._softness, + p._mix); + } break; + } +} + +void IkConstraint::sort(Skeleton &skeleton) { + skeleton.sortBone(_target); + Bone *parent = _bones[0]->_bone; + skeleton.sortBone(parent); + skeleton._updateCache.add(this); + parent->_sorted = false; + skeleton.sortReset(parent->_children); + skeleton.constrained(*parent); + if (_bones.size() > 1) skeleton.constrained(*_bones[1]->_bone); +} + +Array &IkConstraint::getBones() { + return _bones; +} + +Bone &IkConstraint::getTarget() { + return *_target; +} + +void IkConstraint::setTarget(Bone &target) { + _target = ⌖ +} + +bool IkConstraint::isSourceActive() { + return _target->_active; +} + +void IkConstraint::apply(Skeleton &skeleton, BonePose &bone, float targetX, float targetY, bool compress, bool stretch, ScaleYMode scaleYMode, + float mix) { + bone.modifyLocal(skeleton); + BonePose &p = *bone._bone->_parent->_appliedPose; + float pa = p._a, pb = p._b, pc = p._c, pd = p._d; + float sx = skeleton.getScaleX(), sy = skeleton.getScaleY(); + float rotationIK = -bone._shearX - bone._rotation, tx, ty; + switch (bone._inherit) { + case Inherit_OnlyTranslation: + tx = (targetX - bone._worldX) * MathUtil::sign(sx); + ty = (targetY - bone._worldY) * MathUtil::sign(sy); + break; + case Inherit_NoRotationOrReflection: { + float s = MathUtil::abs(pa * pd - pb * pc) / MathUtil::max(MathUtil::Epsilon, pa * pa + pc * pc); + float sa = pa / sx; + float sc = pc / sy; + pb = -sc * s * sx; + pd = sa * s * sy; + rotationIK += MathUtil::atan2Deg(sc, sa); + // Fall through. + } + default: + float x = targetX - p._worldX, y = targetY - p._worldY; + float d = pa * pd - pb * pc; + if (MathUtil::abs(d) <= MathUtil::Epsilon) { + tx = 0; + ty = 0; + } else { + tx = (x * pd - y * pb) / d - bone._x; + ty = (y * pa - x * pc) / d - bone._y; + } + } + rotationIK += MathUtil::atan2Deg(ty, tx); + if (bone._scaleX < 0) rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK <= -180)// + rotationIK += 360; + bone._rotation += rotationIK * mix; + if (compress || stretch) { + switch (bone._inherit) { + case Inherit_NoScale: + case Inherit_NoScaleOrReflection: + tx = targetX - bone._worldX; + ty = targetY - bone._worldY; + break; + default: + break; + } + float b = bone._bone->_data.getLength() * bone._scaleX; + if (b > MathUtil::Epsilon) { + float dd = tx * tx + ty * ty; + if ((compress && dd < b * b) || (stretch && dd > b * b)) { + float s = (MathUtil::sqrt(dd) / b - 1) * mix + 1; + bone._scaleX *= s; + switch (scaleYMode) { + case ScaleYMode_Uniform: + bone._scaleY *= s; + break; + case ScaleYMode_Volume: + bone._scaleY /= s < 0.7f ? 0.25f + 0.642857f * s : s; + break; + default: + break; + } + } + } + } +} + +void IkConstraint::apply(Skeleton &skeleton, BonePose &parent, BonePose &child, float targetX, float targetY, int bendDir, bool stretch, + ScaleYMode scaleYMode, float softness, float mix) { + if (parent._inherit != Inherit_Normal || child._inherit != Inherit_Normal) return; + parent.modifyLocal(skeleton); + child.modifyLocal(skeleton); + float px = parent._x, py = parent._y, psx = parent._scaleX, psy = parent._scaleY, csx = child._scaleX; + int os1, os2, s2; + if (psx < 0) { + psx = -psx; + os1 = 180; + s2 = -1; + } else { + os1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + os2 = 180; + } else + os2 = 0; + float cwx, cwy, a = parent._a, b = parent._b, c = parent._c, d = parent._d; + bool u = MathUtil::abs(psx - psy) <= MathUtil::Epsilon; + if (!u || stretch) { + child._y = 0; + cwx = a * child._x + parent._worldX; + cwy = c * child._x + parent._worldY; + } else { + cwx = a * child._x + b * child._y + parent._worldX; + cwy = c * child._x + d * child._y + parent._worldY; + } + BonePose &pp = *parent._bone->_parent->_appliedPose; + a = pp._a; + b = pp._b; + c = pp._c; + d = pp._d; + float id = a * d - b * c, x = cwx - pp._worldX, y = cwy - pp._worldY; + id = MathUtil::abs(id) <= MathUtil::Epsilon ? 0 : 1 / id; + float dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + float l1 = MathUtil::sqrt(dx * dx + dy * dy), l2 = child._bone->_data.getLength() * csx, a1, a2; + if (l1 < MathUtil::Epsilon) { + apply(skeleton, parent, targetX, targetY, false, stretch, ScaleYMode_None, mix); + child._rotation = 0; + return; + } + x = targetX - pp._worldX; + y = targetY - pp._worldY; + float tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + float dd = tx * tx + ty * ty; + if (softness != 0) { + softness *= psx * (csx + 1) * 0.5f; + float td = MathUtil::sqrt(dd), sd = td - l1 - l2 * psx + softness; + if (sd > 0) { + float p = MathUtil::min(1.0f, sd / (softness * 2)) - 1; + p = (sd - softness * (1 - p * p)) / td; + tx -= p * tx; + ty -= p * ty; + dd = tx * tx + ty * ty; + } + } + + if (u) { + l2 *= psx; + float cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) { + cos = -1; + a2 = MathUtil::Pi * bendDir; + } else if (cos > 1) { + cos = 1; + a2 = 0; + if (stretch) { + a = (MathUtil::sqrt(dd) / (l1 + l2) - 1) * mix + 1; + parent._scaleX *= a; + switch (scaleYMode) { + case ScaleYMode_Uniform: + parent._scaleY *= a; + break; + case ScaleYMode_Volume: + parent._scaleY /= a < 0.7f ? 0.25f + 0.642857f * a : a; + break; + default: + break; + } + } + } else + a2 = MathUtil::acos(cos) * bendDir; + a = l1 + l2 * cos; + b = l2 * MathUtil::sin(a2); + a1 = MathUtil::atan2(ty * a - tx * b, tx * a + ty * b); + } else { + a = psx * l2; + b = psy * l2; + float aa = a * a, bb = b * b, ta = MathUtil::atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + float c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; + if (d >= 0) { + float q = MathUtil::sqrt(d); + if (c1 < 0) q = -q; + q = -(c1 + q) * 0.5f; + float r0 = q / c2, r1 = c / q; + float r = MathUtil::abs(r0) < MathUtil::abs(r1) ? r0 : r1; + r0 = dd - r * r; + if (r0 >= 0) { + y = MathUtil::sqrt(r0) * bendDir; + a1 = ta - MathUtil::atan2(y, r); + a2 = MathUtil::atan2(y / psy, (r - l1) / psx); + goto outer_break; + } + } + float minAngle = MathUtil::Pi, minX = l1 - a, minDist = minX * minX, minY = 0; + float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) { + c = MathUtil::acos(c); + x = a * MathUtil::cos(c) + l1; + y = b * MathUtil::sin(c); + d = x * x + y * y; + if (d < minDist) { + minAngle = c; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) * 0.5f) { + a1 = ta - MathUtil::atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } else { + a1 = ta - MathUtil::atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } +outer_break: + float os = MathUtil::atan2(child._y, child._x) * s2; + a1 = (a1 - os) * MathUtil::Rad_Deg + os1 - parent._rotation; + if (a1 > 180) + a1 -= 360; + else if (a1 <= -180)// + a1 += 360; + parent._rotation += a1 * mix; + a2 = ((a2 + os) * MathUtil::Rad_Deg - child._shearX) * s2 + os2 - child._rotation; + if (a2 > 180) + a2 -= 360; + else if (a2 <= -180)// + a2 += 360; + child._rotation += a2 * mix; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/IkConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/IkConstraintData.cpp new file mode 100644 index 0000000..0429153 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/IkConstraintData.cpp @@ -0,0 +1,65 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(IkConstraintData, ConstraintData) + +IkConstraintData::IkConstraintData(const String &name) + : ConstraintDataGeneric(name), _target(NULL), _scaleYMode(ScaleYMode_None) { +} + +Array &IkConstraintData::getBones() { + return _bones; +} + +BoneData &IkConstraintData::getTarget() { + return *_target; +} + +void IkConstraintData::setTarget(BoneData &inValue) { + _target = &inValue; +} + +ScaleYMode IkConstraintData::getScaleYMode() { + return _scaleYMode; +} + +void IkConstraintData::setScaleYMode(ScaleYMode scaleYMode) { + _scaleYMode = scaleYMode; +} + +Constraint &IkConstraintData::create(Skeleton &skeleton) { + return *(new (__FILE__, __LINE__) IkConstraint(*this, skeleton)); +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/IkConstraintPose.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/IkConstraintPose.cpp new file mode 100644 index 0000000..b76ff38 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/IkConstraintPose.cpp @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +IkConstraintPose::IkConstraintPose() : _bendDirection(0), _compress(false), _stretch(false), _mix(0), _softness(0) { +} + +IkConstraintPose::~IkConstraintPose() { +} + +void IkConstraintPose::set(IkConstraintPose &pose) { + _mix = pose._mix; + _softness = pose._softness; + _bendDirection = pose._bendDirection; + _compress = pose._compress; + _stretch = pose._stretch; +} + +float IkConstraintPose::getMix() { + return _mix; +} + +void IkConstraintPose::setMix(float mix) { + _mix = mix; +} + +float IkConstraintPose::getSoftness() { + return _softness; +} + +void IkConstraintPose::setSoftness(float softness) { + _softness = softness; +} + +int IkConstraintPose::getBendDirection() { + return _bendDirection; +} + +void IkConstraintPose::setBendDirection(int bendDirection) { + _bendDirection = bendDirection; +} + +bool IkConstraintPose::getCompress() { + return _compress; +} + +void IkConstraintPose::setCompress(bool compress) { + _compress = compress; +} + +bool IkConstraintPose::getStretch() { + return _stretch; +} + +void IkConstraintPose::setStretch(bool stretch) { + _stretch = stretch; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/IkConstraintTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/IkConstraintTimeline.cpp new file mode 100644 index 0000000..1f1de42 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -0,0 +1,137 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL_MULTI(IkConstraintTimeline, CurveTimeline, ConstraintTimeline) + +IkConstraintTimeline::IkConstraintTimeline(size_t frameCount, size_t bezierCount, int constraintIndex) + : CurveTimeline(frameCount, IkConstraintTimeline::ENTRIES, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex) { + PropertyId ids[] = {((PropertyId) Property_IkConstraint << 32) | constraintIndex}; + setPropertyIds(ids, 1); +} + +IkConstraintTimeline::~IkConstraintTimeline() { +} + +void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, + bool out, bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(add); + + IkConstraint *constraint = (IkConstraint *) skeleton._constraints[_constraintIndex]; + if (!constraint->isActive()) return; + IkConstraintPose &pose = appliedPose ? *constraint->_appliedPose : constraint->_pose; + + if (time < _frames[0]) { + IkConstraintPose &setup = constraint->_data._setupPose; + switch (from) { + case MixFrom_Setup: + pose._mix = setup._mix; + pose._softness = setup._softness; + pose._bendDirection = setup._bendDirection; + pose._compress = setup._compress; + pose._stretch = setup._stretch; + break; + case MixFrom_First: + pose._mix += (setup._mix - pose._mix) * alpha; + pose._softness += (setup._softness - pose._softness) * alpha; + pose._bendDirection = setup._bendDirection; + pose._compress = setup._compress; + pose._stretch = setup._stretch; + break; + case MixFrom_Current: + break; + } + return; + } + + float mix = 0, softness = 0; + int i = Animation::search(_frames, time, ENTRIES); + int curveType = (int) _curves[i / ENTRIES]; + switch (curveType) { + case LINEAR: { + float before = _frames[i]; + mix = _frames[i + MIX]; + softness = _frames[i + SOFTNESS]; + float t = (time - before) / (_frames[i + ENTRIES] - before); + mix += (_frames[i + ENTRIES + MIX] - mix) * t; + softness += (_frames[i + ENTRIES + SOFTNESS] - softness) * t; + break; + } + case STEPPED: { + mix = _frames[i + MIX]; + softness = _frames[i + SOFTNESS]; + break; + } + default: { + mix = getBezierValue(time, i, MIX, curveType - BEZIER); + softness = getBezierValue(time, i, SOFTNESS, curveType + BEZIER_SIZE - BEZIER); + } + } + + IkConstraintPose &base = from == MixFrom_Setup ? constraint->_data._setupPose : pose; + pose._mix = base._mix + (mix - base._mix) * alpha; + pose._softness = base._softness + (softness - base._softness) * alpha; + if (out) { + if (from == MixFrom_Setup) { + pose._bendDirection = base._bendDirection; + pose._compress = base._compress; + pose._stretch = base._stretch; + } + } else { + pose._bendDirection = (int) _frames[i + BEND_DIRECTION]; + pose._compress = _frames[i + COMPRESS] != 0; + pose._stretch = _frames[i + STRETCH] != 0; + } +} + +void IkConstraintTimeline::setFrame(int frame, float time, float mix, float softness, int bendDirection, bool compress, bool stretch) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + MIX] = mix; + _frames[frame + SOFTNESS] = softness; + _frames[frame + BEND_DIRECTION] = (float) bendDirection; + _frames[frame + COMPRESS] = compress ? 1 : 0; + _frames[frame + STRETCH] = stretch ? 1 : 0; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/InheritTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/InheritTimeline.cpp new file mode 100644 index 0000000..cfd07cf --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/InheritTimeline.cpp @@ -0,0 +1,81 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL_MULTI(InheritTimeline, Timeline, BoneTimeline) + +InheritTimeline::InheritTimeline(size_t frameCount, int boneIndex) : Timeline(frameCount, ENTRIES), BoneTimeline(boneIndex), _boneIndex(boneIndex) { + PropertyId ids[] = {((PropertyId) Property_Inherit << 32) | boneIndex}; + setPropertyIds(ids, 1); + _instant = true; +} + +InheritTimeline::~InheritTimeline() { +} + +void InheritTimeline::setFrame(int frame, float time, Inherit inherit) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + INHERIT] = (float) inherit; +} + +void InheritTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(alpha); + SP_UNUSED(add); + + Bone *bone = skeleton._bones[_boneIndex]; + if (!bone->isActive()) return; + BonePose &pose = appliedPose ? *bone->_appliedPose : bone->_pose; + + if (out) { + if (from != MixFrom_Current) pose._inherit = bone->_data._setupPose._inherit; + } else { + if (time < _frames[0]) { + if (from != MixFrom_Current) pose._inherit = bone->_data._setupPose._inherit; + } else { + int idx = Animation::search(_frames, time, ENTRIES) + INHERIT; + pose._inherit = static_cast((int) _frames[idx]); + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Interpolation.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Interpolation.cpp new file mode 100644 index 0000000..b139090 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Interpolation.cpp @@ -0,0 +1,112 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +using namespace spine; + +namespace { + class LinearInterpolation : public Interpolation { + public: + float apply(float a) override { + return a; + } + }; + + class SmoothInterpolation : public Interpolation { + public: + float apply(float a) override { + return a * a * (3 - 2 * a); + } + }; + + class SlowFastInterpolation : public Interpolation { + public: + float apply(float a) override { + return a * a; + } + }; + + class FastSlowInterpolation : public Interpolation { + public: + float apply(float a) override { + return (a - 1) * (a - 1) * -1 + 1; + } + }; + + class CircleInterpolation : public Interpolation { + public: + float apply(float a) override { + if (a <= 0.5f) { + a *= 2; + return (1 - MathUtil::sqrt(1 - a * a)) / 2; + } + a--; + a *= 2; + return (MathUtil::sqrt(1 - a * a) + 1) / 2; + } + }; +} + +Interpolation::~Interpolation() { +} + +float Interpolation::apply(float a) { + return a; +} + +float Interpolation::apply(float start, float end, float a) { + return start + (end - start) * apply(a); +} + +Interpolation &Interpolation::linear() { + static LinearInterpolation interpolation; + return interpolation; +} + +Interpolation &Interpolation::smooth() { + static SmoothInterpolation interpolation; + return interpolation; +} + +Interpolation &Interpolation::slowFast() { + static SlowFastInterpolation interpolation; + return interpolation; +} + +Interpolation &Interpolation::fastSlow() { + static FastSlowInterpolation interpolation; + return interpolation; +} + +Interpolation &Interpolation::circle() { + static CircleInterpolation interpolation; + return interpolation; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Json.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Json.cpp new file mode 100644 index 0000000..5f14718 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Json.cpp @@ -0,0 +1,555 @@ +/* +Copyright (c) 2009, Dave Gamble +Copyright (c) 2013, Esoteric Software + +Permission is hereby granted, dispose of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* Json */ +/* JSON parser in CPP, from json.c in the spine-c runtime */ + +#ifndef _DEFAULT_SOURCE +/* Bring strings.h definitions into string.h, where appropriate */ +#define _DEFAULT_SOURCE +#endif + +#ifndef _BSD_SOURCE +/* Bring strings.h definitions into string.h, where appropriate */ +#define _BSD_SOURCE +#endif + +#include +#include +#include +#include + +#include +#include + +using namespace spine; + +const int Json::JSON_FALSE = 0; +const int Json::JSON_TRUE = 1; +const int Json::JSON_NULL = 2; +const int Json::JSON_NUMBER = 3; +const int Json::JSON_STRING = 4; +const int Json::JSON_ARRAY = 5; +const int Json::JSON_OBJECT = 6; + +const char *Json::_error = NULL; + +Json *Json::getItem(Json *object, const char *string) { + Json *c = object->_child; + while (c && json_strcasecmp(c->_name, string)) { + c = c->_next; + } + return c; +} + +Json *Json::getItem(Json *object, int childIndex) { + Json *current = object->_child; + while (current != NULL && childIndex > 0) { + childIndex--; + current = current->_next; + } + return current; +} + +const char *Json::getString(Json *object, const char *name, const char *defaultValue) { + object = getItem(object, name); + if (object) { + return object->_valueString; + } + + return defaultValue; +} + +float Json::getFloat(Json *value, const char *name, float defaultValue) { + value = getItem(value, name); + return value ? value->_valueFloat : defaultValue; +} + +int Json::getInt(Json *value, const char *name, int defaultValue) { + value = getItem(value, name); + return value ? value->_valueInt : defaultValue; +} + +bool Json::getBoolean(Json *value, const char *name, bool defaultValue) { + value = getItem(value, name); + if (value) { + if (value->_valueString) return strcmp(value->_valueString, "true") == 0; + if (value->_type == JSON_NULL) return false; + if (value->_type == JSON_NUMBER) return value->_valueFloat != 0; + if (value->_type == JSON_FALSE) return false; + if (value->_type == JSON_TRUE) return true; + return defaultValue; + } else { + return defaultValue; + } +} + +const char *Json::getError() { + return _error; +} + +Json::Json(const char *value) + : _next(NULL), +#if SPINE_JSON_HAVE_PREV + _prev(NULL), +#endif + _child(NULL), _type(0), _size(0), _valueString(NULL), _valueInt(0), _valueFloat(0), _name(NULL) { + if (value) { + value = parseValue(this, skip(value)); + + assert(value); + } +} + +Json::~Json() { + Json *curr = NULL; + Json *next = _child; + do { + curr = next; + if (curr) { + next = curr->_next; + } + delete curr; + } while (next); + + if (_valueString) { + SpineExtension::free(_valueString, __FILE__, __LINE__); + } + + if (_name) { + SpineExtension::free(_name, __FILE__, __LINE__); + } +} + +const char *Json::skip(const char *inValue) { + if (!inValue) { + /* must propagate NULL since it's often called in skip(f(...)) form */ + return NULL; + } + + while (*inValue && (unsigned char) *inValue <= 32) { + inValue++; + } + + return inValue; +} + +const char *Json::parseValue(Json *item, const char *value) { + /* Referenced by constructor, parseArray(), and parseObject(). */ + /* Always called with the result of skip(). */ +#ifdef SPINE_JSON_DEBUG /* Checked at entry to graph, constructor, and after every parse call. */ + if (!value) { + /* Fail on null. */ + return NULL; + } +#endif + + switch (*value) { + case 'n': { + if (!strncmp(value + 1, "ull", 3)) { + item->_type = JSON_NULL; + return value + 4; + } + break; + } + case 'f': { + if (!strncmp(value + 1, "alse", 4)) { + item->_type = JSON_FALSE; + /* calloc prevents us needing item->_type = JSON_FALSE or valueInt = 0 here */ + return value + 5; + } + break; + } + case 't': { + if (!strncmp(value + 1, "rue", 3)) { + item->_type = JSON_TRUE; + item->_valueInt = 1; + return value + 4; + } + break; + } + case '\"': + return parseString(item, value); + case '[': + return parseArray(item, value); + case '{': + return parseObject(item, value); + case '-': /* fallthrough */ + case '0': /* fallthrough */ + case '1': /* fallthrough */ + case '2': /* fallthrough */ + case '3': /* fallthrough */ + case '4': /* fallthrough */ + case '5': /* fallthrough */ + case '6': /* fallthrough */ + case '7': /* fallthrough */ + case '8': /* fallthrough */ + case '9': + return parseNumber(item, value); + default: + break; + } + + _error = value; + return NULL; /* failure. */ +} + +static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC}; + +const char *Json::parseString(Json *item, const char *str) { + const char *ptr = str + 1; + char *ptr2; + char *out; + int len = 0; + unsigned uc, uc2; + if (*str != '\"') { + /* TODO: don't need this check when called from parseValue, but do need from parseObject */ + _error = str; + return 0; + } /* not a string! */ + + while (*ptr != '\"' && *ptr && ++len) { + if (*ptr++ == '\\') { + ptr++; /* Skip escaped quotes. */ + } + } + + out = SpineExtension::alloc(len + 1, __FILE__, __LINE__); /* The length needed for the string, roughly. */ + if (!out) { + return 0; + } + + ptr = str + 1; + ptr2 = out; + while (*ptr != '\"' && *ptr) { + if (*ptr != '\\') { + *ptr2++ = *ptr++; + } else { + ptr++; + switch (*ptr) { + case 'b': + *ptr2++ = '\b'; + break; + case 'f': + *ptr2++ = '\f'; + break; + case 'n': + *ptr2++ = '\n'; + break; + case 'r': + *ptr2++ = '\r'; + break; + case 't': + *ptr2++ = '\t'; + break; + case 'u': { + /* transcode utf16 to utf8. */ + sscanf(ptr + 1, "%4x", &uc); + ptr += 4; /* get the unicode char. */ + + if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) { + break; /* check for invalid. */ + } + + /* TODO provide an option to ignore surrogates, use unicode replacement character? */ + if (uc >= 0xD800 && uc <= 0xDBFF) /* UTF16 surrogate pairs. */ { + if (ptr[1] != '\\' || ptr[2] != 'u') { + break; /* missing second-half of surrogate. */ + } + sscanf(ptr + 3, "%4x", &uc2); + ptr += 6; + if (uc2 < 0xDC00 || uc2 > 0xDFFF) { + break; /* invalid second-half of surrogate. */ + } + uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF)); + } + + len = 4; + if (uc < 0x80) { + len = 1; + } else if (uc < 0x800) { + len = 2; + } else if (uc < 0x10000) { + len = 3; + } + ptr2 += len; + + switch (len) { + case 4: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 3: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 2: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + /* fallthrough */ + case 1: + *--ptr2 = (uc | firstByteMark[len]); + } + ptr2 += len; + break; + } + default: + *ptr2++ = *ptr; + break; + } + ptr++; + } + } + + *ptr2 = 0; + + if (*ptr == '\"') { + ptr++; /* TODO error handling if not \" or \0 ? */ + } + + item->_valueString = out; + item->_type = JSON_STRING; + + return ptr; +} + +const char *Json::parseNumber(Json *item, const char *num) { + double result = 0.0; + int negative = 0; + char *ptr = (char *) num; + + if (*ptr == '-') { + negative = -1; + ++ptr; + } + + while (*ptr >= '0' && *ptr <= '9') { + result = result * 10.0 + (*ptr - '0'); + ++ptr; + } + + if (*ptr == '.') { + double fraction = 0.0; + int n = 0; + ++ptr; + + while (*ptr >= '0' && *ptr <= '9') { + fraction = (fraction * 10.0) + (*ptr - '0'); + ++ptr; + ++n; + } + result += fraction / pow(10.0, n); + } + + if (negative) { + result = -result; + } + + if (*ptr == 'e' || *ptr == 'E') { + double exponent = 0; + int expNegative = 0; + ++ptr; + + if (*ptr == '-') { + expNegative = -1; + ++ptr; + } else if (*ptr == '+') { + ++ptr; + } + + while (*ptr >= '0' && *ptr <= '9') { + exponent = (exponent * 10.0) + (*ptr - '0'); + ++ptr; + } + + if (expNegative) { + result = result / pow(10, exponent); + } else { + result = result * pow(10, exponent); + } + } + + if (ptr != num) { + /* Parse success, number found. */ + item->_valueFloat = (float) result; + item->_valueInt = (int) result; + item->_type = JSON_NUMBER; + return ptr; + } else { + /* Parse failure, _error is set. */ + _error = num; + return NULL; + } +} + +const char *Json::parseArray(Json *item, const char *value) { + Json *child; + +#ifdef SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */ + if (*value != '[') { + ep = value; + return 0; + } /* not an array! */ +#endif + + item->_type = JSON_ARRAY; + value = skip(value + 1); + if (*value == ']') { + return value + 1; /* empty array. */ + } + + item->_child = child = new (__FILE__, __LINE__) Json(NULL); + if (!item->_child) { + return NULL; /* memory fail */ + } + + value = skip(parseValue(child, skip(value))); /* skip any spacing, get the value. */ + + if (!value) { + return NULL; + } + + item->_size = 1; + + while (*value == ',') { + Json *new_item = new (__FILE__, __LINE__) Json(NULL); + if (!new_item) { + return NULL; /* memory fail */ + } + child->_next = new_item; +#if SPINE_JSON_HAVE_PREV + new_item->prev = child; +#endif + child = new_item; + value = skip(parseValue(child, skip(value + 1))); + if (!value) { + return NULL; /* parse fail */ + } + item->_size++; + } + + if (*value == ']') { + return value + 1; /* end of array */ + } + + _error = value; + + return NULL; /* malformed. */ +} + +/* Build an object from the text. */ +const char *Json::parseObject(Json *item, const char *value) { + Json *child; + +#ifdef SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */ + if (*value != '{') { + ep = value; + return 0; + } /* not an object! */ +#endif + + item->_type = JSON_OBJECT; + value = skip(value + 1); + if (*value == '}') { + return value + 1; /* empty array. */ + } + + item->_child = child = new (__FILE__, __LINE__) Json(NULL); + if (!item->_child) { + return NULL; + } + value = skip(parseString(child, skip(value))); + if (!value) { + return NULL; + } + child->_name = child->_valueString; + child->_valueString = 0; + if (*value != ':') { + _error = value; + return NULL; + } /* fail! */ + + value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return NULL; + } + + item->_size = 1; + + while (*value == ',') { + Json *new_item = new (__FILE__, __LINE__) Json(NULL); + if (!new_item) { + return NULL; /* memory fail */ + } + child->_next = new_item; +#if SPINE_JSON_HAVE_PREV + new_item->prev = child; +#endif + child = new_item; + value = skip(parseString(child, skip(value + 1))); + if (!value) { + return NULL; + } + child->_name = child->_valueString; + child->_valueString = 0; + if (*value != ':') { + _error = value; + return NULL; + } /* fail! */ + + value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return NULL; + } + item->_size++; + } + + if (*value == '}') { + return value + 1; /* end of array */ + } + + _error = value; + + return NULL; /* malformed. */ +} + +int Json::json_strcasecmp(const char *s1, const char *s2) { + /* TODO we may be able to elide these NULL checks if we can prove + * the graph and input (only callsite is Json_getItem) should not have NULLs + */ + if (s1 && s2) { +#if defined(_WIN32) + return _stricmp(s1, s2); +#else + return strcasecmp(s1, s2); +#endif + } else { + if (s1 < s2) { + return -1; /* s1 is null, s2 is not */ + } else if (s1 == s2) { + return 0; /* both are null */ + } else { + return 1; /* s2 is nul s1 is not */ + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/LinkedMesh.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/LinkedMesh.cpp new file mode 100644 index 0000000..68fdd4f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/LinkedMesh.cpp @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +LinkedMesh::LinkedMesh(MeshAttachment &mesh, const int skinIndex, size_t slotIndex, size_t sourceIndex, const String &source, bool inheritTimelines) + : _mesh(&mesh), _skinIndex(skinIndex), _skin(""), _slotIndex(slotIndex), _sourceIndex(sourceIndex), _source(source), + _inheritTimelines(inheritTimelines) { +} + +LinkedMesh::LinkedMesh(MeshAttachment &mesh, const String &skin, size_t slotIndex, size_t sourceIndex, const String &source, bool inheritTimelines) + : _mesh(&mesh), _skinIndex(-1), _skin(skin), _slotIndex(slotIndex), _sourceIndex(sourceIndex), _source(source), + _inheritTimelines(inheritTimelines) { +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/MathUtil.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/MathUtil.cpp new file mode 100644 index 0000000..5782a87 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/MathUtil.cpp @@ -0,0 +1,133 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include + +// Required for division by 0 in _isNaN on MSVC +#ifdef _MSC_VER +#pragma warning(disable : 4723) +#endif + +using namespace spine; + +const float MathUtil::Epsilon = 0.00001f; +const float MathUtil::EpsilonSq = MathUtil::Epsilon * MathUtil::Epsilon; +const float MathUtil::Pi = 3.1415926535897932385f; +const float MathUtil::Pi_2 = 3.1415926535897932385f * 2; +const float MathUtil::InvPi_2 = 1 / MathUtil::Pi_2; +const float MathUtil::Deg_Rad = (3.1415926535897932385f / 180.0f); +const float MathUtil::Rad_Deg = (180.0f / 3.1415926535897932385f); + +float MathUtil::abs(float v) { + return ((v) < 0 ? -(v) : (v)); +} + +float MathUtil::sign(float v) { + return ((v) < 0 ? -1.0f : (v) > 0 ? 1.0f : 0.0f); +} + +float MathUtil::clamp(float x, float min, float max) { + return ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))); +} + +float MathUtil::fmod(float a, float b) { + return (float) ::fmod(a, b); +} + +/// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 +/// degrees), largest error of 0.00488 radians (0.2796 degrees). +float MathUtil::atan2(float y, float x) { + return (float) ::atan2(y, x); +} + +float MathUtil::atan2Deg(float y, float x) { + return MathUtil::atan2(y, x) * MathUtil::Rad_Deg; +} + +/// Returns the cosine in radians from a lookup table. +float MathUtil::cos(float radians) { + return (float) ::cos(radians); +} + +/// Returns the sine in radians from a lookup table. +float MathUtil::sin(float radians) { + return (float) ::sin(radians); +} + +float MathUtil::sqrt(float v) { + return (float) ::sqrt(v); +} + +float MathUtil::acos(float v) { + return (float) ::acos(v); +} + +/// Returns the sine in radians from a lookup table. +float MathUtil::sinDeg(float degrees) { + return (float) ::sin(degrees * MathUtil::Deg_Rad); +} + +/// Returns the cosine in radians from a lookup table. +float MathUtil::cosDeg(float degrees) { + return (float) ::cos(degrees * MathUtil::Deg_Rad); +} + +bool MathUtil::isNan(float v) { + return std::isnan(v); +} + +float MathUtil::quietNan() { + return std::nan(""); +} + +float MathUtil::random() { + return ::rand() / (float) RAND_MAX; +} + +float MathUtil::randomTriangular(float min, float max) { + return randomTriangular(min, max, (min + max) * 0.5f); +} + +float MathUtil::randomTriangular(float min, float max, float mode) { + float u = random(); + float d = max - min; + if (u <= (mode - min) / d) return min + sqrt(u * d * (mode - min)); + return max - sqrt((1 - u) * d * (max - mode)); +} + +float MathUtil::pow(float a, float b) { + return (float) ::pow(a, b); +} + +float MathUtil::ceil(float v) { + return ::ceil(v); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/MeshAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/MeshAttachment.cpp new file mode 100644 index 0000000..f4a107c --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/MeshAttachment.cpp @@ -0,0 +1,230 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(MeshAttachment, VertexAttachment) + +MeshAttachment::MeshAttachment(const String &name, Sequence *sequence) + : VertexAttachment(name), _sequence(sequence), _regionUVs(), _triangles(), _hullLength(0), _path(), _color(1, 1, 1, 1), _sourceMesh(NULL), + _edges(), _width(0), _height(0) { + assert(sequence); +} + +MeshAttachment::~MeshAttachment() { + delete _sequence; +} + +void MeshAttachment::computeWorldVertices(Skeleton &skeleton, Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride) { + VertexAttachment::computeWorldVertices(skeleton, slot, start, count, worldVertices, offset, stride); +} + +Array &MeshAttachment::getRegionUVs() { + return _regionUVs; +} + +void MeshAttachment::setRegionUVs(Array &inValue) { + _regionUVs.clearAndAddAll(inValue); +} + +Array &MeshAttachment::getTriangles() { + return _triangles; +} + +void MeshAttachment::setTriangles(Array &inValue) { + _triangles.clearAndAddAll(inValue); +} + +int MeshAttachment::getHullLength() { + return _hullLength; +} + +void MeshAttachment::setHullLength(int inValue) { + _hullLength = inValue; +} + +Sequence &MeshAttachment::getSequence() { + return *_sequence; +} + +void MeshAttachment::updateSequence() { + _sequence->update(*this); +} + +const String &MeshAttachment::getPath() { + return _path; +} + +void MeshAttachment::setPath(const String &inValue) { + _path = inValue; +} + +Color &MeshAttachment::getColor() { + return _color; +} + +MeshAttachment *MeshAttachment::getSourceMesh() { + return _sourceMesh; +} + +void MeshAttachment::setSourceMesh(MeshAttachment *inValue) { + _sourceMesh = inValue; + if (inValue != NULL) { + _bones.clearAndAddAll(inValue->_bones); + _vertices.clearAndAddAll(inValue->_vertices); + _regionUVs.clearAndAddAll(inValue->_regionUVs); + _triangles.clearAndAddAll(inValue->_triangles); + _hullLength = inValue->_hullLength; + _worldVerticesLength = inValue->_worldVerticesLength; + _edges.clearAndAddAll(inValue->_edges); + _width = inValue->_width; + _height = inValue->_height; + } +} + +Array &MeshAttachment::getEdges() { + return _edges; +} + +void MeshAttachment::setEdges(Array &inValue) { + _edges.clearAndAddAll(inValue); +} + +float MeshAttachment::getWidth() { + return _width; +} + +void MeshAttachment::setWidth(float inValue) { + _width = inValue; +} + +float MeshAttachment::getHeight() { + return _height; +} + +void MeshAttachment::setHeight(float inValue) { + _height = inValue; +} + +Attachment &MeshAttachment::copy() { + if (_sourceMesh) return newLinkedMesh(); + + MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName(), new (__FILE__, __LINE__) Sequence(*_sequence)); + copy->_path = _path; + copy->_color.set(_color); + copyTo(*copy); + copy->_regionUVs.clearAndAddAll(_regionUVs); + copy->_triangles.clearAndAddAll(_triangles); + copy->_hullLength = _hullLength; + copy->_edges.clearAndAddAll(_edges); + copy->_width = _width; + copy->_height = _height; + return *copy; +} + +MeshAttachment &MeshAttachment::newLinkedMesh() { + MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName(), new (__FILE__, __LINE__) Sequence(*_sequence)); + copy->setTimelineAttachment(getTimelineAttachment()); + copy->_path = _path; + copy->_color.set(_color); + copy->setSourceMesh(_sourceMesh != NULL ? _sourceMesh : this); + copy->updateSequence(); + return *copy; +} + +void MeshAttachment::computeUVs(TextureRegion *region, Array ®ionUVs, Array &uvs) { + int n = (int) uvs.size(); + float u, v, width, height; + if (region != NULL && region->getRTTI().instanceOf(AtlasRegion::rtti)) { + AtlasRegion *r = static_cast(region); + u = r->_u; + v = r->_v; + float textureWidth = r->getPage()->width; + float textureHeight = r->getPage()->height; + switch (r->_degrees) { + case 90: { + u -= (r->_originalHeight - r->_offsetY - r->_packedWidth) / textureWidth; + v -= (r->_originalWidth - r->_offsetX - r->_packedHeight) / textureHeight; + width = r->_originalHeight / textureWidth; + height = r->_originalWidth / textureHeight; + for (int i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i + 1] * width; + uvs[i + 1] = v + (1 - regionUVs[i]) * height; + } + return; + } + case 180: { + u -= (r->_originalWidth - r->_offsetX - r->_packedWidth) / textureWidth; + v -= r->_offsetY / textureHeight; + width = r->_originalWidth / textureWidth; + height = r->_originalHeight / textureHeight; + for (int i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i]) * width; + uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height; + } + return; + } + case 270: { + u -= r->_offsetY / textureWidth; + v -= r->_offsetX / textureHeight; + width = r->_originalHeight / textureWidth; + height = r->_originalWidth / textureHeight; + for (int i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i + 1]) * width; + uvs[i + 1] = v + regionUVs[i] * height; + } + return; + } + default: { + u -= r->_offsetX / textureWidth; + v -= (r->_originalHeight - r->_offsetY - r->_packedHeight) / textureHeight; + width = r->_originalWidth / textureWidth; + height = r->_originalHeight / textureHeight; + } + } + } else if (region == NULL) { + u = v = 0; + width = height = 1; + } else { + u = region->_u; + v = region->_v; + width = region->_u2 - u; + height = region->_v2 - v; + } + for (int i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i] * width; + uvs[i + 1] = v + regionUVs[i + 1] * height; + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathAttachment.cpp new file mode 100644 index 0000000..76d9804 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathAttachment.cpp @@ -0,0 +1,74 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL(PathAttachment, VertexAttachment) + +PathAttachment::PathAttachment(const String &name) : VertexAttachment(name), _closed(false), _constantSpeed(false), _color() { +} + +Array &PathAttachment::getLengths() { + return _lengths; +} + +void PathAttachment::setLengths(Array &inValue) { + _lengths.clearAndAddAll(inValue); +} + +bool PathAttachment::getClosed() { + return _closed; +} + +void PathAttachment::setClosed(bool inValue) { + _closed = inValue; +} + +bool PathAttachment::getConstantSpeed() { + return _constantSpeed; +} + +void PathAttachment::setConstantSpeed(bool inValue) { + _constantSpeed = inValue; +} + +Color &PathAttachment::getColor() { + return _color; +} + +Attachment &PathAttachment::copy() { + PathAttachment *copy = new (__FILE__, __LINE__) PathAttachment(getName()); + copyTo(*copy); + copy->_lengths.clearAndAddAll(_lengths); + copy->_closed = _closed; + copy->_constantSpeed = _constantSpeed; + return *copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraint.cpp new file mode 100644 index 0000000..349c6b2 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraint.cpp @@ -0,0 +1,552 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraint, Constraint) + +const float PathConstraint::epsilon = 0.00001f; +const int PathConstraint::NONE = -1; +const int PathConstraint::BEFORE = -2; +const int PathConstraint::AFTER = -3; + +PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : PathConstraintBase(data) { + + _bones.ensureCapacity(data.getBones().size()); + for (size_t i = 0; i < data.getBones().size(); i++) { + BoneData *boneData = data.getBones()[i]; + _bones.add(&skeleton._bones[boneData->getIndex()]->_constrainedPose); + } + + _slot = skeleton._slots[data._slot->_index]; + _segments.setSize(10, 0); +} + +PathConstraint &PathConstraint::copy(Skeleton &skeleton) { + PathConstraint *copy = new (__FILE__, __LINE__) PathConstraint(_data, skeleton); + copy->_pose.set(_pose); + return *copy; +} + +void PathConstraint::update(Skeleton &skeleton, Physics physics) { + Attachment *baseAttachment = _slot->_appliedPose->_attachment; + if (baseAttachment == NULL || !baseAttachment->getRTTI().instanceOf(PathAttachment::rtti)) { + return; + } + PathAttachment *pathAttachment = static_cast(baseAttachment); + + PathConstraintPose &p = *_appliedPose; + float mixRotate = p._mixRotate, mixX = p._mixX, mixY = p._mixY; + if (mixRotate == 0 && mixX == 0 && mixY == 0) return; + + PathConstraintData &data = _data; + bool tangents = data._rotateMode == RotateMode_Tangent, scale = data._rotateMode == RotateMode_ChainScale; + size_t boneCount = _bones.size(); + size_t spacesCount = tangents ? boneCount : boneCount + 1; + BonePose **bones = _bones.buffer(); + _spaces.setSize(spacesCount, 0); + float *spaces = _spaces.buffer(); + float *lengths = NULL; + if (scale) { + _lengths.setSize(boneCount, 0); + lengths = _lengths.buffer(); + } + float spacing = p._spacing; + + switch (data._spacingMode) { + case SpacingMode_Percent: { + if (scale) { + for (size_t i = 0, n = spacesCount - 1; i < n; i++) { + BonePose *bone = bones[i]; + float setupLength = bone->_bone->getData().getLength(); + float x = setupLength * bone->_a; + float y = setupLength * bone->_c; + lengths[i] = MathUtil::sqrt(x * x + y * y); + } + } + for (size_t i = 1; i < spacesCount; i++) { + spaces[i] = spacing; + } + break; + } + case SpacingMode_Proportional: { + float sum = 0; + for (size_t i = 0, n = spacesCount - 1; i < n;) { + BonePose *bone = bones[i]; + float setupLength = bone->_bone->getData().getLength(); + if (setupLength < epsilon) { + if (scale) lengths[i] = 0; + spaces[++i] = spacing; + } else { + float x = setupLength * bone->_a, y = setupLength * bone->_c; + float length = MathUtil::sqrt(x * x + y * y); + if (scale) lengths[i] = length; + spaces[++i] = length; + sum += length; + } + } + if (sum > 0) { + sum = spacesCount / sum * spacing; + for (size_t i = 1; i < spacesCount; i++) { + spaces[i] *= sum; + } + } + break; + } + default: { + bool lengthSpacing = data._spacingMode == SpacingMode_Length; + for (size_t i = 0, n = spacesCount - 1; i < n;) { + BonePose *bone = bones[i]; + float setupLength = bone->_bone->getData().getLength(); + if (setupLength < epsilon) { + if (scale) lengths[i] = 0; + spaces[++i] = spacing; + } else { + float x = setupLength * bone->_a, y = setupLength * bone->_c; + float length = MathUtil::sqrt(x * x + y * y); + if (scale) lengths[i] = length; + spaces[++i] = (lengthSpacing ? MathUtil::max(0.0f, setupLength + spacing) : spacing) * length / setupLength; + } + } + } + } + + Array &positions = computeWorldPositions(skeleton, *pathAttachment, (int) spacesCount, tangents); + float *positionsBuffer = positions.buffer(); + float boneX = positionsBuffer[0], boneY = positionsBuffer[1], offsetRotation = data._offsetRotation; + bool tip; + if (offsetRotation == 0) + tip = data._rotateMode == RotateMode_Chain; + else { + tip = false; + BonePose &bone = _slot->getBone().getAppliedPose(); + offsetRotation *= bone._a * bone._d - bone._b * bone._c > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; + } + for (size_t i = 0, ip = 3; i < boneCount; i++, ip += 3) { + BonePose *bone = bones[i]; + bone->modifyWorld(skeleton); + bone->_worldX += (boneX - bone->_worldX) * mixX; + bone->_worldY += (boneY - bone->_worldY) * mixY; + float x = positionsBuffer[ip], y = positionsBuffer[ip + 1], dx = x - boneX, dy = y - boneY; + if (scale) { + float length = lengths[i]; + if (length >= epsilon) { + float s = (MathUtil::sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1; + bone->_a *= s; + bone->_c *= s; + } + } + boneX = x; + boneY = y; + if (mixRotate > 0) { + float a = bone->_a, b = bone->_b, c = bone->_c, d = bone->_d, r, cos, sin; + if (tangents) + r = positionsBuffer[ip - 1]; + else if (spaces[i + 1] < epsilon) + r = positionsBuffer[ip + 2]; + else + r = MathUtil::atan2(dy, dx); + r -= MathUtil::atan2(c, a); + if (tip) { + cos = MathUtil::cos(r); + sin = MathUtil::sin(r); + float length = bone->_bone->getData().getLength(); + boneX += (length * (cos * a - sin * c) - dx) * mixRotate; + boneY += (length * (sin * a + cos * c) - dy) * mixRotate; + } else + r += offsetRotation; + if (r > MathUtil::Pi) + r -= MathUtil::Pi_2; + else if (r < -MathUtil::Pi) + r += MathUtil::Pi_2; + r *= mixRotate; + cos = MathUtil::cos(r); + sin = MathUtil::sin(r); + bone->_a = cos * a - sin * c; + bone->_b = cos * b - sin * d; + bone->_c = sin * a + cos * c; + bone->_d = sin * b + cos * d; + } + } +} + + +void PathConstraint::sort(Skeleton &skeleton) { + int slotIndex = _slot->getData().getIndex(); + Bone &slotBone = _slot->getBone(); + if (skeleton.getSkin() != NULL) sortPathSlot(skeleton, *skeleton.getSkin(), slotIndex, slotBone); + if (skeleton.getData().getDefaultSkin() != NULL && skeleton.getData().getDefaultSkin() != skeleton.getSkin()) + sortPathSlot(skeleton, *skeleton.getData().getDefaultSkin(), slotIndex, slotBone); + sortPath(skeleton, _slot->_pose._attachment, slotBone); + BonePose **bones = _bones.buffer(); + size_t boneCount = _bones.size(); + for (size_t i = 0; i < boneCount; i++) { + Bone *bone = bones[i]->_bone; + skeleton.sortBone(bone); + skeleton.constrained(*bone); + } + skeleton._updateCache.add(this); + for (size_t i = 0; i < boneCount; i++) skeleton.sortReset(bones[i]->_bone->getChildren()); + for (size_t i = 0; i < boneCount; i++) bones[i]->_bone->_sorted = true; +} + +bool PathConstraint::isSourceActive() { + return _slot->getBone().isActive(); +} + +Array &PathConstraint::getBones() { + return _bones; +} + +Slot &PathConstraint::getSlot() { + return *_slot; +} + +void PathConstraint::setSlot(Slot &slot) { + _slot = &slot; +} + +Array &PathConstraint::computeWorldPositions(Skeleton &skeleton, PathAttachment &path, int spacesCount, bool tangents) { + float position = _appliedPose->_position; + float *spaces = _spaces.buffer(); + _positions.setSize(spacesCount * 3 + 2, 0); + Array &out = _positions; + Array &world = _world; + bool closed = path.getClosed(); + int verticesLength = (int) path.getWorldVerticesLength(); + int curveCount = verticesLength / 6; + int prevCurve = NONE; + + float pathLength; + if (!path.getConstantSpeed()) { + Array &lengths = path.getLengths(); + float *lengthsBuffer = lengths.buffer(); + curveCount -= closed ? 1 : 2; + pathLength = lengthsBuffer[curveCount]; + if (_data._positionMode == PositionMode_Percent) position *= pathLength; + + float multiplier = 0; + switch (_data._spacingMode) { + case SpacingMode_Percent: + multiplier = pathLength; + break; + case SpacingMode_Proportional: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + + world.setSize(8, 0); + float *worldBuffer = world.buffer(); + for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + float space = spaces[i] * multiplier; + position += space; + float p = position; + + if (closed) { + p = MathUtil::fmod(p, pathLength); + if (p < 0) p += pathLength; + curve = 0; + } else if (p < 0) { + if (prevCurve != BEFORE) { + prevCurve = BEFORE; + path.computeWorldVertices(skeleton, *_slot, 2, 4, world, 0, 2); + } + addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength) { + if (prevCurve != AFTER) { + prevCurve = AFTER; + path.computeWorldVertices(skeleton, *_slot, verticesLength - 6, 4, world, 0, 2); + } + addAfterPosition(p - pathLength, world, 0, out, o); + continue; + } + + // Determine curve containing position. + for (;; curve++) { + float length = lengthsBuffer[curve]; + if (p > length) continue; + if (curve == 0) + p /= length; + else { + float prev = lengthsBuffer[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + if (closed && curve == curveCount) { + path.computeWorldVertices(skeleton, *_slot, verticesLength - 4, 4, world, 0, 2); + path.computeWorldVertices(skeleton, *_slot, 0, 4, world, 4, 2); + } else + path.computeWorldVertices(skeleton, *_slot, curve * 6 + 2, 8, world, 0, 2); + } + addCurvePosition(p, worldBuffer[0], worldBuffer[1], worldBuffer[2], worldBuffer[3], worldBuffer[4], worldBuffer[5], worldBuffer[6], + worldBuffer[7], out, o, tangents || (i > 0 && space < epsilon)); + } + return out; + } + + // World vertices. + if (closed) { + verticesLength += 2; + world.setSize(verticesLength, 0); + float *worldBuffer = world.buffer(); + path.computeWorldVertices(skeleton, *_slot, 2, verticesLength - 4, world, 0, 2); + path.computeWorldVertices(skeleton, *_slot, 0, 2, world, verticesLength - 4, 2); + worldBuffer[verticesLength - 2] = worldBuffer[0]; + worldBuffer[verticesLength - 1] = worldBuffer[1]; + } else { + curveCount--; + verticesLength -= 4; + world.setSize(verticesLength, 0); + path.computeWorldVertices(skeleton, *_slot, 2, verticesLength, world, 0, 2); + } + float *worldBuffer = world.buffer(); + + // Curve lengths. + _curves.setSize(curveCount, 0); + float *curvesBuffer = _curves.buffer(); + pathLength = 0; + float x1 = worldBuffer[0], y1 = worldBuffer[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy; + for (int i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = worldBuffer[w]; + cy1 = worldBuffer[w + 1]; + cx2 = worldBuffer[w + 2]; + cy2 = worldBuffer[w + 3]; + x2 = worldBuffer[w + 4]; + y2 = worldBuffer[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875f; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875f; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375f; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375f; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f; + dfy = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + curvesBuffer[i] = pathLength; + x1 = x2; + y1 = y2; + } + + if (_data._positionMode == PositionMode_Percent) position *= pathLength; + + float multiplier = 0; + switch (_data._spacingMode) { + case SpacingMode_Percent: + multiplier = pathLength; + break; + case SpacingMode_Proportional: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + + float curveLength = 0; + for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + float space = spaces[i] * multiplier; + position += space; + float p = position; + + if (closed) { + p = MathUtil::fmod(p, pathLength); + if (p < 0) p += pathLength; + curve = 0; + segment = 0; + } else if (p < 0) { + addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength) { + addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + + // Determine curve containing position. + for (;; curve++) { + float length = curvesBuffer[curve]; + if (p > length) continue; + if (curve == 0) + p /= length; + else { + float prev = curvesBuffer[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + + // Curve segment lengths. + if (curve != prevCurve) { + prevCurve = curve; + int ii = curve * 6; + x1 = worldBuffer[ii]; + y1 = worldBuffer[ii + 1]; + cx1 = worldBuffer[ii + 2]; + cy1 = worldBuffer[ii + 3]; + cx2 = worldBuffer[ii + 4]; + cy2 = worldBuffer[ii + 5]; + x2 = worldBuffer[ii + 6]; + y2 = worldBuffer[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03f; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03f; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006f; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006f; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f; + dfy = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f; + curveLength = MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy); + _segments[9] = curveLength; + segment = 0; + } + + // Weight by segment length. + p *= curveLength; + for (;; segment++) { + float length = _segments[segment]; + if (p > length) continue; + if (segment == 0) + p /= length; + else { + float prev = _segments[segment - 1]; + p = segment + (p - prev) / (length - prev); + } + break; + } + addCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space < epsilon)); + } + + return out; +} + +void PathConstraint::addBeforePosition(float p, Array &temp, int i, Array &output, int o) { + float x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = MathUtil::atan2(dy, dx); + output[o] = x1 + p * MathUtil::cos(r); + output[o + 1] = y1 + p * MathUtil::sin(r); + output[o + 2] = r; +} + +void PathConstraint::addAfterPosition(float p, Array &temp, int i, Array &output, int o) { + float x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = MathUtil::atan2(dy, dx); + output[o] = x1 + p * MathUtil::cos(r); + output[o + 1] = y1 + p * MathUtil::sin(r); + output[o + 2] = r; +} + +void PathConstraint::addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, + Array &output, int o, bool tangents) { + if (p < epsilon || MathUtil::isNan(p)) { + output[o] = x1; + output[o + 1] = y1; + output[o + 2] = MathUtil::atan2(cy1 - y1, cx1 - x1); + return; + } + float tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + float ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + float x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + output[o] = x; + output[o + 1] = y; + if (tangents) { + if (p < 0.001f) + output[o + 2] = MathUtil::atan2(cy1 - y1, cx1 - x1); + else + output[o + 2] = MathUtil::atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } +} + +void PathConstraint::sortPathSlot(Skeleton &skeleton, Skin &skin, int slotIndex, Bone &slotBone) { + Skin::AttachmentMap::Entries entries = skin.getAttachments(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == (size_t) slotIndex) sortPath(skeleton, entry._attachment, slotBone); + } +} + +void PathConstraint::sortPath(Skeleton &skeleton, Attachment *attachment, Bone &slotBone) { + if (attachment == NULL || !attachment->getRTTI().instanceOf(PathAttachment::rtti)) return; + PathAttachment *pathAttachment = static_cast(attachment); + Array &pathBones = pathAttachment->getBones(); + if (pathBones.size() == 0) + skeleton.sortBone(&slotBone); + else { + Array &bones = skeleton._bones; + for (size_t i = 0, n = pathBones.size(); i < n;) { + int nn = pathBones[i++]; + nn += i; + while (i < (size_t) nn) skeleton.sortBone(bones[pathBones[i++]]); + } + } +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintData.cpp new file mode 100644 index 0000000..6dfb444 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintData.cpp @@ -0,0 +1,92 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintData, ConstraintData) + +PathConstraintData::PathConstraintData(const String &name) + : ConstraintDataGeneric(name), _slot(NULL), _positionMode(PositionMode_Fixed), + _spacingMode(SpacingMode_Length), _rotateMode(RotateMode_Tangent), _offsetRotation(0) { +} + + +Array &PathConstraintData::getBones() { + return _bones; +} + +SlotData &PathConstraintData::getSlot() { + return *_slot; +} + +void PathConstraintData::setSlot(SlotData &slot) { + _slot = &slot; +} + +PositionMode PathConstraintData::getPositionMode() { + return _positionMode; +} + +void PathConstraintData::setPositionMode(PositionMode positionMode) { + _positionMode = positionMode; +} + +SpacingMode PathConstraintData::getSpacingMode() { + return _spacingMode; +} + +void PathConstraintData::setSpacingMode(SpacingMode spacingMode) { + _spacingMode = spacingMode; +} + +RotateMode PathConstraintData::getRotateMode() { + return _rotateMode; +} + +void PathConstraintData::setRotateMode(RotateMode rotateMode) { + _rotateMode = rotateMode; +} + +float PathConstraintData::getOffsetRotation() { + return _offsetRotation; +} + +void PathConstraintData::setOffsetRotation(float offsetRotation) { + _offsetRotation = offsetRotation; +} + +Constraint &PathConstraintData::create(Skeleton &skeleton) { + return *(new (__FILE__, __LINE__) PathConstraint(*this, skeleton)); +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintMixTimeline.cpp new file mode 100644 index 0000000..274465f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -0,0 +1,131 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL_MULTI(PathConstraintMixTimeline, CurveTimeline, ConstraintTimeline) + +PathConstraintMixTimeline::PathConstraintMixTimeline(size_t frameCount, size_t bezierCount, int constraintIndex) + : CurveTimeline(frameCount, PathConstraintMixTimeline::ENTRIES, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex) { + PropertyId ids[] = {((PropertyId) Property_PathConstraintMix << 32) | constraintIndex}; + setPropertyIds(ids, 1); +} + +PathConstraintMixTimeline::~PathConstraintMixTimeline() { +} + +void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, + bool out, bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(out); + + PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex]; + if (!constraint->isActive()) return; + PathConstraintPose &pose = appliedPose ? *constraint->_appliedPose : constraint->_pose; + + if (time < _frames[0]) { + PathConstraintPose &setup = constraint->_data._setupPose; + switch (from) { + case MixFrom_Setup: + pose._mixRotate = setup._mixRotate; + pose._mixX = setup._mixX; + pose._mixY = setup._mixY; + break; + case MixFrom_First: + pose._mixRotate += (setup._mixRotate - pose._mixRotate) * alpha; + pose._mixX += (setup._mixX - pose._mixX) * alpha; + pose._mixY += (setup._mixY - pose._mixY) * alpha; + break; + case MixFrom_Current: + break; + } + return; + } + + float rotate, x, y; + int i = Animation::search(_frames, time, PathConstraintMixTimeline::ENTRIES); + int curveType = (int) _curves[i >> 2]; + switch (curveType) { + case LINEAR: { + float before = _frames[i]; + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + float t = (time - before) / (_frames[i + ENTRIES] - before); + rotate += (_frames[i + ENTRIES + ROTATE] - rotate) * t; + x += (_frames[i + ENTRIES + X] - x) * t; + y += (_frames[i + ENTRIES + Y] - y) * t; + break; + } + case STEPPED: { + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + break; + } + default: { + rotate = getBezierValue(time, i, ROTATE, curveType - BEZIER); + x = getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER); + y = getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER); + } + } + + PathConstraintPose &base = from == MixFrom_Setup ? constraint->_data._setupPose : pose; + if (add) { + pose._mixRotate = base._mixRotate + rotate * alpha; + pose._mixX = base._mixX + x * alpha; + pose._mixY = base._mixY + y * alpha; + } else { + pose._mixRotate = base._mixRotate + (rotate - base._mixRotate) * alpha; + pose._mixX = base._mixX + (x - base._mixX) * alpha; + pose._mixY = base._mixY + (y - base._mixY) * alpha; + } +} + +void PathConstraintMixTimeline::setFrame(int frame, float time, float mixRotate, float mixX, float mixY) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + ROTATE] = mixRotate; + _frames[frame + X] = mixX; + _frames[frame + Y] = mixY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintPose.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintPose.cpp new file mode 100644 index 0000000..9a7f94e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintPose.cpp @@ -0,0 +1,86 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +PathConstraintPose::PathConstraintPose() : Pose(), _position(0), _spacing(0), _mixRotate(0), _mixX(0), _mixY(0) { +} + +PathConstraintPose::~PathConstraintPose() { +} + +void PathConstraintPose::set(PathConstraintPose &pose) { + _position = pose._position; + _spacing = pose._spacing; + _mixRotate = pose._mixRotate; + _mixX = pose._mixX; + _mixY = pose._mixY; +} + +float PathConstraintPose::getPosition() { + return _position; +} + +void PathConstraintPose::setPosition(float position) { + _position = position; +} + +float PathConstraintPose::getSpacing() { + return _spacing; +} + +void PathConstraintPose::setSpacing(float spacing) { + _spacing = spacing; +} + +float PathConstraintPose::getMixRotate() { + return _mixRotate; +} + +void PathConstraintPose::setMixRotate(float mixRotate) { + _mixRotate = mixRotate; +} + +float PathConstraintPose::getMixX() { + return _mixX; +} + +void PathConstraintPose::setMixX(float mixX) { + _mixX = mixX; +} + +float PathConstraintPose::getMixY() { + return _mixY; +} + +void PathConstraintPose::setMixY(float mixY) { + _mixY = mixY; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp new file mode 100644 index 0000000..ce56620 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -0,0 +1,66 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintPositionTimeline, ConstraintTimeline1) + +PathConstraintPositionTimeline::PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, int constraintIndex) + : ConstraintTimeline1(frameCount, bezierCount, constraintIndex, Property_PathConstraintPosition) { + _additive = true; +} + +PathConstraintPositionTimeline::~PathConstraintPositionTimeline() { +} + +void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, + bool add, bool out, bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(out); + + PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex]; + if (constraint->isActive()) { + PathConstraintPose &pose = appliedPose ? *constraint->_appliedPose : constraint->_pose; + PathConstraintData &data = constraint->_data; + pose._position = getAbsoluteValue(time, alpha, from, add, pose._position, data._setupPose._position); + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp new file mode 100644 index 0000000..6ff93d9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -0,0 +1,65 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PathConstraintSpacingTimeline, ConstraintTimeline1) + +PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(size_t frameCount, size_t bezierCount, int constraintIndex) + : ConstraintTimeline1(frameCount, bezierCount, constraintIndex, Property_PathConstraintSpacing) { +} + +PathConstraintSpacingTimeline::~PathConstraintSpacingTimeline() { +} + +void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, + bool out, bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(out); + + PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex]; + if (constraint->isActive()) { + PathConstraintPose &pose = appliedPose ? *constraint->_appliedPose : constraint->_pose; + PathConstraintData &data = constraint->_data; + pose._spacing = getAbsoluteValue(time, alpha, from, false, pose._spacing, data._setupPose._spacing); + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PhysicsConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PhysicsConstraint.cpp new file mode 100644 index 0000000..7353f36 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PhysicsConstraint.cpp @@ -0,0 +1,305 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PhysicsConstraint, Constraint) + +PhysicsConstraint::PhysicsConstraint(PhysicsConstraintData &data, Skeleton &skeleton) + : PhysicsConstraintBase(data), _reset(true), _ux(0), _uy(0), _cx(0), _cy(0), _tx(0), _ty(0), _xOffset(0), _xLag(0), _xVelocity(0), _yOffset(0), + _yLag(0), _yVelocity(0), _rotateOffset(0), _rotateLag(0), _rotateVelocity(0), _scaleOffset(0), _scaleLag(0), _scaleVelocity(0), _remaining(0), + _lastTime(0) { + + _bone = &skeleton._bones[(size_t) data._bone->getIndex()]->_constrainedPose; +} + +PhysicsConstraint &PhysicsConstraint::copy(Skeleton &skeleton) { + PhysicsConstraint *copy = new (__FILE__, __LINE__) PhysicsConstraint(_data, skeleton); + copy->_pose.set(_pose); + return *copy; +} + +void PhysicsConstraint::reset(Skeleton &skeleton) { + _remaining = 0; + _lastTime = skeleton.getTime(); + _reset = true; + _xOffset = 0; + _xLag = 0; + _xVelocity = 0; + _yOffset = 0; + _yLag = 0; + _yVelocity = 0; + _rotateOffset = 0; + _rotateLag = 0; + _rotateVelocity = 0; + _scaleOffset = 0; + _scaleLag = 0; + _scaleVelocity = 0; +} + +void PhysicsConstraint::translate(float x, float y) { + _ux -= x; + _uy -= y; + _cx -= x; + _cy -= y; +} + +void PhysicsConstraint::rotate(float x, float y, float degrees) { + float r = degrees * MathUtil::Deg_Rad, cosVal = MathUtil::cos(r), sinVal = MathUtil::sin(r); + float dx = _cx - x, dy = _cy - y; + translate(dx * cosVal - dy * sinVal - dx, dx * sinVal + dy * cosVal - dy); +} + +void PhysicsConstraint::update(Skeleton &skeleton, Physics physics) { + PhysicsConstraintPose &p = *_appliedPose; + float mix = p._mix; + if (mix == 0) return; + + bool x = _data._x > 0, y = _data._y > 0, rotateOrShearX = _data._rotate > 0 || _data._shearX > 0, scaleX = _data._scaleX > 0; + BonePose *bone = _bone; + float l = bone->_bone->_data.getLength(), t = _data._step, z = 0; + if (physics == Physics_None) return; + bone->modifyWorld(skeleton); + + switch (physics) { + case Physics_Reset: + reset(skeleton); + // Fall through. + case Physics_Update: { + float delta = MathUtil::max(skeleton._time - _lastTime, 0.0f), aa = _remaining; + _remaining += delta; + _lastTime = skeleton._time; + + float bx = bone->_worldX, by = bone->_worldY; + if (_reset) { + _reset = false; + _ux = bx; + _uy = by; + } else { + float a = _remaining, i = p._inertia, f = skeleton._data.getReferenceScale(), d = -1, m = 0, e = 0, qx = _data._limit * delta, + qy = qx * MathUtil::abs(skeleton.getScaleY()); + qx *= MathUtil::abs(skeleton._scaleX); + if (x || y) { + if (x) { + float u = (_ux - bx) * i; + _xOffset += u > qx ? qx : u < -qx ? -qx : u; + _ux = bx; + } + if (y) { + float u = (_uy - by) * i; + _yOffset += u > qy ? qy : u < -qy ? -qy : u; + _uy = by; + } + if (a >= t) { + float xs = _xOffset, ys = _yOffset; + d = MathUtil::pow(p._damping, 60 * t); + m = t * p._massInverse; + e = p._strength; + float w = f * p._wind, g = f * p._gravity; + float ax = (w * skeleton._windX + g * skeleton._gravityX) * skeleton._scaleX; + float ay = (w * skeleton._windY + g * skeleton._gravityY) * skeleton.getScaleY(); + do { + if (x) { + _xVelocity += (ax - _xOffset * e) * m; + _xOffset += _xVelocity * t; + _xVelocity *= d; + } + if (y) { + _yVelocity -= (ay + _yOffset * e) * m; + _yOffset += _yVelocity * t; + _yVelocity *= d; + } + a -= t; + } while (a >= t); + _xLag = _xOffset - xs; + _yLag = _yOffset - ys; + } + z = MathUtil::max(0.0f, 1 - a / t); + if (x) bone->_worldX += (_xOffset - _xLag * z) * mix * _data._x; + if (y) bone->_worldY += (_yOffset - _yLag * z) * mix * _data._y; + } + if (rotateOrShearX || scaleX) { + float ca = MathUtil::atan2(bone->_c, bone->_a), c, s, mr = 0, dx = _cx - bone->_worldX, dy = _cy - bone->_worldY; + if (dx > qx) + dx = qx; + else if (dx < -qx) + dx = -qx; + if (dy > qy) + dy = qy; + else if (dy < -qy) + dy = -qy; + if (rotateOrShearX) { + mr = (_data._rotate + _data._shearX) * mix; + z = _rotateLag * MathUtil::max(0.0f, 1 - aa / t); + float r = MathUtil::atan2(dy + _ty, dx + _tx) - ca - (_rotateOffset - z) * mr; + _rotateOffset += (r - MathUtil::ceil(r * MathUtil::InvPi_2 - 0.5f) * MathUtil::Pi_2) * i; + r = (_rotateOffset - z) * mr + ca; + c = MathUtil::cos(r); + s = MathUtil::sin(r); + if (scaleX) { + r = l * bone->getWorldScaleX(); + if (r > 0) _scaleOffset += (dx * c + dy * s) * i / r; + } + } else { + c = MathUtil::cos(ca); + s = MathUtil::sin(ca); + float r = l * bone->getWorldScaleX() - _scaleLag * MathUtil::max(0.0f, 1 - aa / t); + if (r > 0) _scaleOffset += (dx * c + dy * s) * i / r; + } + a = _remaining; + if (a >= t) { + if (d == -1) { + d = MathUtil::pow(p._damping, 60 * t); + m = t * p._massInverse; + e = p._strength; + } + float ax = p._wind * skeleton._windX + p._gravity * skeleton._gravityX; + float ay = (p._wind * skeleton._windY + p._gravity * skeleton._gravityY) * (Bone::isYDown() ? -1 : 1); + float rs = _rotateOffset, ss = _scaleOffset, h = l / f; + while (true) { + a -= t; + if (scaleX) { + _scaleVelocity += (ax * c - ay * s - _scaleOffset * e) * m; + _scaleOffset += _scaleVelocity * t; + _scaleVelocity *= d; + } + if (rotateOrShearX) { + _rotateVelocity -= ((ax * s + ay * c) * h + _rotateOffset * e) * m; + _rotateOffset += _rotateVelocity * t; + _rotateVelocity *= d; + if (a < t) break; + float r = _rotateOffset * mr + ca; + c = MathUtil::cos(r); + s = MathUtil::sin(r); + } else if (a < t) + break; + } + _rotateLag = _rotateOffset - rs; + _scaleLag = _scaleOffset - ss; + } + z = MathUtil::max(0.0f, 1 - a / t); + } + _remaining = a; + } + _cx = bone->_worldX; + _cy = bone->_worldY; + break; + } + case Physics_Pose: { + z = MathUtil::max(0.0f, 1 - _remaining / t); + if (x) bone->_worldX += (_xOffset - _xLag * z) * mix * _data._x; + if (y) bone->_worldY += (_yOffset - _yLag * z) * mix * _data._y; + break; + } + } + + if (rotateOrShearX) { + float o = (_rotateOffset - _rotateLag * z) * mix, s, c, a; + if (_data._shearX > 0) { + float r = 0; + if (_data._rotate > 0) { + r = o * _data._rotate; + s = MathUtil::sin(r); + c = MathUtil::cos(r); + a = bone->_b; + bone->_b = c * a - s * bone->_d; + bone->_d = s * a + c * bone->_d; + } + r += o * _data._shearX; + s = MathUtil::sin(r); + c = MathUtil::cos(r); + a = bone->_a; + bone->_a = c * a - s * bone->_c; + bone->_c = s * a + c * bone->_c; + } else { + o *= _data._rotate; + s = MathUtil::sin(o); + c = MathUtil::cos(o); + a = bone->_a; + bone->_a = c * a - s * bone->_c; + bone->_c = s * a + c * bone->_c; + a = bone->_b; + bone->_b = c * a - s * bone->_d; + bone->_d = s * a + c * bone->_d; + } + } + if (scaleX) { + float s = 1 + (_scaleOffset - _scaleLag * z) * mix * _data._scaleX; + bone->_a *= s; + bone->_c *= s; + switch (_data._scaleYMode) { + case ScaleYMode_Uniform: + bone->_b *= s; + bone->_d *= s; + break; + case ScaleYMode_Volume: + s = MathUtil::abs(s); + s = s >= 0.7f ? 1 / s : 4 - 3.67347f * s; + bone->_b *= s; + bone->_d *= s; + break; + default: + break; + } + } + if (physics != Physics_Pose) { + _tx = l * bone->_a; + _ty = l * bone->_c; + } +} + +void PhysicsConstraint::sort(Skeleton &skeleton) { + Bone *bone = _bone->_bone; + skeleton.sortBone(bone); + skeleton._updateCache.add(this); + skeleton.sortReset(bone->_children); + skeleton.constrained(*bone); +} + +bool PhysicsConstraint::isSourceActive() { + return _bone->_bone->isActive(); +} + +BonePose &PhysicsConstraint::getBone() { + return *_bone; +} + +void PhysicsConstraint::setBone(BonePose &bone) { + _bone = &bone; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PhysicsConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PhysicsConstraintData.cpp new file mode 100644 index 0000000..c882b59 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PhysicsConstraintData.cpp @@ -0,0 +1,175 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PhysicsConstraintData, ConstraintData) + +PhysicsConstraintData::PhysicsConstraintData(const String &name) + : ConstraintDataGeneric(name), _bone(NULL), _x(0), _y(0), _rotate(0), _scaleX(0), _shearX(0), _limit(0), + _step(0), _scaleYMode(ScaleYMode_None), _inertiaGlobal(false), _strengthGlobal(false), _dampingGlobal(false), _massGlobal(false), + _windGlobal(false), _gravityGlobal(false), _mixGlobal(false) { +} + +BoneData &PhysicsConstraintData::getBone() { + return *_bone; +} + +void PhysicsConstraintData::setBone(BoneData &bone) { + _bone = &bone; +} + +float PhysicsConstraintData::getStep() { + return _step; +} + +void PhysicsConstraintData::setStep(float step) { + _step = step; +} + +float PhysicsConstraintData::getX() { + return _x; +} + +void PhysicsConstraintData::setX(float x) { + _x = x; +} + +float PhysicsConstraintData::getY() { + return _y; +} + +void PhysicsConstraintData::setY(float y) { + _y = y; +} + +float PhysicsConstraintData::getRotate() { + return _rotate; +} + +void PhysicsConstraintData::setRotate(float rotate) { + _rotate = rotate; +} + +float PhysicsConstraintData::getScaleX() { + return _scaleX; +} + +void PhysicsConstraintData::setScaleX(float scaleX) { + _scaleX = scaleX; +} + +float PhysicsConstraintData::getShearX() { + return _shearX; +} + +void PhysicsConstraintData::setShearX(float shearX) { + _shearX = shearX; +} + +float PhysicsConstraintData::getLimit() { + return _limit; +} + +void PhysicsConstraintData::setLimit(float limit) { + _limit = limit; +} + +ScaleYMode PhysicsConstraintData::getScaleYMode() { + return _scaleYMode; +} + +void PhysicsConstraintData::setScaleYMode(ScaleYMode scaleYMode) { + _scaleYMode = scaleYMode; +} + +bool PhysicsConstraintData::getInertiaGlobal() { + return _inertiaGlobal; +} + +void PhysicsConstraintData::setInertiaGlobal(bool inertiaGlobal) { + _inertiaGlobal = inertiaGlobal; +} + +bool PhysicsConstraintData::getStrengthGlobal() { + return _strengthGlobal; +} + +void PhysicsConstraintData::setStrengthGlobal(bool strengthGlobal) { + _strengthGlobal = strengthGlobal; +} + +bool PhysicsConstraintData::getDampingGlobal() { + return _dampingGlobal; +} + +void PhysicsConstraintData::setDampingGlobal(bool dampingGlobal) { + _dampingGlobal = dampingGlobal; +} + +bool PhysicsConstraintData::getMassGlobal() { + return _massGlobal; +} + +void PhysicsConstraintData::setMassGlobal(bool massGlobal) { + _massGlobal = massGlobal; +} + +bool PhysicsConstraintData::getWindGlobal() { + return _windGlobal; +} + +void PhysicsConstraintData::setWindGlobal(bool windGlobal) { + _windGlobal = windGlobal; +} + +bool PhysicsConstraintData::getGravityGlobal() { + return _gravityGlobal; +} + +void PhysicsConstraintData::setGravityGlobal(bool gravityGlobal) { + _gravityGlobal = gravityGlobal; +} + +bool PhysicsConstraintData::getMixGlobal() { + return _mixGlobal; +} + +void PhysicsConstraintData::setMixGlobal(bool mixGlobal) { + _mixGlobal = mixGlobal; +} + +Constraint &PhysicsConstraintData::create(Skeleton &skeleton) { + return *(new (__FILE__, __LINE__) PhysicsConstraint(*this, skeleton)); +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PhysicsConstraintPose.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PhysicsConstraintPose.cpp new file mode 100644 index 0000000..255af11 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PhysicsConstraintPose.cpp @@ -0,0 +1,105 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +PhysicsConstraintPose::PhysicsConstraintPose() + : Pose(), _inertia(0), _strength(0), _damping(0), _massInverse(0), _wind(0), _gravity(0), _mix(0) { +} + +PhysicsConstraintPose::~PhysicsConstraintPose() { +} + +void PhysicsConstraintPose::set(PhysicsConstraintPose &pose) { + _inertia = pose._inertia; + _strength = pose._strength; + _damping = pose._damping; + _massInverse = pose._massInverse; + _wind = pose._wind; + _gravity = pose._gravity; + _mix = pose._mix; +} + +float PhysicsConstraintPose::getInertia() { + return _inertia; +} + +void PhysicsConstraintPose::setInertia(float inertia) { + _inertia = inertia; +} + +float PhysicsConstraintPose::getStrength() { + return _strength; +} + +void PhysicsConstraintPose::setStrength(float strength) { + _strength = strength; +} + +float PhysicsConstraintPose::getDamping() { + return _damping; +} + +void PhysicsConstraintPose::setDamping(float damping) { + _damping = damping; +} + +float PhysicsConstraintPose::getMassInverse() { + return _massInverse; +} + +void PhysicsConstraintPose::setMassInverse(float massInverse) { + _massInverse = massInverse; +} + +float PhysicsConstraintPose::getWind() { + return _wind; +} + +void PhysicsConstraintPose::setWind(float wind) { + _wind = wind; +} + +float PhysicsConstraintPose::getGravity() { + return _gravity; +} + +void PhysicsConstraintPose::setGravity(float gravity) { + _gravity = gravity; +} + +float PhysicsConstraintPose::getMix() { + return _mix; +} + +void PhysicsConstraintPose::setMix(float mix) { + _mix = mix; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PhysicsConstraintTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PhysicsConstraintTimeline.cpp new file mode 100644 index 0000000..6a92453 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PhysicsConstraintTimeline.cpp @@ -0,0 +1,110 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL_MULTI(PhysicsConstraintTimeline, CurveTimeline, ConstraintTimeline) +RTTI_IMPL(PhysicsConstraintInertiaTimeline, PhysicsConstraintTimeline) +RTTI_IMPL(PhysicsConstraintStrengthTimeline, PhysicsConstraintTimeline) +RTTI_IMPL(PhysicsConstraintDampingTimeline, PhysicsConstraintTimeline) +RTTI_IMPL(PhysicsConstraintMassTimeline, PhysicsConstraintTimeline) +RTTI_IMPL(PhysicsConstraintWindTimeline, PhysicsConstraintTimeline) +RTTI_IMPL(PhysicsConstraintGravityTimeline, PhysicsConstraintTimeline) +RTTI_IMPL(PhysicsConstraintMixTimeline, PhysicsConstraintTimeline) +RTTI_IMPL_MULTI(PhysicsConstraintResetTimeline, Timeline, ConstraintTimeline) + +PhysicsConstraintTimeline::PhysicsConstraintTimeline(size_t frameCount, size_t bezierCount, int constraintIndex, Property property) + : CurveTimeline1(frameCount, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex) { + PropertyId ids[] = {((PropertyId) property << 32) | constraintIndex}; + setPropertyIds(ids, 1); +} + +void PhysicsConstraintTimeline::apply(Skeleton &skeleton, float, float time, Array *, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) { + SP_UNUSED(out); + if (add && !_additive) add = false; + if (_constraintIndex == -1) { + float value = time >= _frames[0] ? getCurveValue(time) : 0; + + Array &physicsConstraints = skeleton.getPhysicsConstraints(); + for (size_t i = 0; i < physicsConstraints.size(); i++) { + PhysicsConstraint *constraint = physicsConstraints[i]; + if (constraint->isActive() && global(constraint->_data)) { + PhysicsConstraintPose &pose = appliedPose ? *constraint->_appliedPose : constraint->_pose; + set(pose, getAbsoluteValue(time, alpha, from, add, get(pose), get(constraint->_data._setupPose), value)); + } + } + } else { + PhysicsConstraint *constraint = static_cast(skeleton.getConstraints()[_constraintIndex]); + if (constraint->isActive()) { + PhysicsConstraintPose &pose = appliedPose ? *constraint->_appliedPose : constraint->_pose; + set(pose, getAbsoluteValue(time, alpha, from, add, get(pose), get(constraint->_data._setupPose))); + } + } +} + +void PhysicsConstraintResetTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *, float alpha, MixFrom from, bool add, + bool out, bool appliedPose) { + PhysicsConstraint *constraint = nullptr; + if (_constraintIndex != -1) { + constraint = static_cast(skeleton.getConstraints()[_constraintIndex]); + if (!constraint->isActive()) return; + } + + if (lastTime > time) {// Apply after lastTime for looped animations. + apply(skeleton, lastTime, FLT_MAX, nullptr, alpha, MixFrom_Current, false, false, false); + lastTime = -1; + } else if (lastTime >= _frames[_frames.size() - 1])// Last time is after last frame. + return; + if (time < _frames[0]) return; + + if (lastTime < _frames[0] || time >= _frames[Animation::search(_frames, lastTime) + 1]) { + if (constraint != nullptr) + constraint->reset(skeleton); + else { + Array &physicsConstraints = skeleton.getPhysicsConstraints(); + for (size_t i = 0; i < physicsConstraints.size(); i++) { + constraint = physicsConstraints[i]; + if (constraint->isActive()) constraint->reset(skeleton); + } + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PointAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PointAttachment.cpp new file mode 100644 index 0000000..bc26228 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/PointAttachment.cpp @@ -0,0 +1,92 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +#include + +using namespace spine; + +RTTI_IMPL(PointAttachment, Attachment) + +PointAttachment::PointAttachment(const String &name) : Attachment(name), _x(0), _y(0), _rotation(0), _color(0.9451f, 0.9451f, 0, 1) { +} + +float PointAttachment::getX() { + return _x; +} + +void PointAttachment::setX(float inValue) { + _x = inValue; +} + +float PointAttachment::getY() { + return _y; +} + +void PointAttachment::setY(float inValue) { + _y = inValue; +} + +float PointAttachment::getRotation() { + return _rotation; +} + +void PointAttachment::setRotation(float inValue) { + _rotation = inValue; +} + +Color &PointAttachment::getColor() { + return _color; +} + +void PointAttachment::computeWorldPosition(BonePose &bone, float &ox, float &oy) { + ox = _x * bone.getA() + _y * bone.getB() + bone.getWorldX(); + oy = _x * bone.getC() + _y * bone.getD() + bone.getWorldY(); +} + +float PointAttachment::computeWorldRotation(BonePose &bone) { + float r = _rotation * MathUtil::Deg_Rad, cosine = MathUtil::cos(r), sine = MathUtil::sin(r); + float x = cosine * bone.getA() + sine * bone.getB(); + float y = cosine * bone.getC() + sine * bone.getD(); + return MathUtil::atan2Deg(y, x); +} + +Attachment &PointAttachment::copy() { + PointAttachment *copy = new (__FILE__, __LINE__) PointAttachment(getName()); + copy->setTimelineAttachment(getTimelineAttachment()); + copy->setTimelineSlots(getTimelineSlots()); + copy->_x = _x; + copy->_y = _y; + copy->_rotation = _rotation; + copy->_color.set(_color); + return *copy; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/RTTI.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/RTTI.cpp new file mode 100644 index 0000000..ee996d1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/RTTI.cpp @@ -0,0 +1,83 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +using namespace spine; + +RTTI::RTTI(const char *className) : _className(className), _pBaseRTTI(NULL), _interfaceCount(0) { + _interfaces[0] = NULL; + _interfaces[1] = NULL; + _interfaces[2] = NULL; +} + +RTTI::RTTI(const char *className, const RTTI &baseRTTI) : _className(className), _pBaseRTTI(&baseRTTI), _interfaceCount(0) { + _interfaces[0] = NULL; + _interfaces[1] = NULL; + _interfaces[2] = NULL; +} + +RTTI::RTTI(const char *className, const RTTI &baseRTTI, const RTTI *interface1, const RTTI *interface2, const RTTI *interface3) + : _className(className), _pBaseRTTI(&baseRTTI), _interfaceCount(0) { + _interfaces[0] = interface1; + _interfaces[1] = interface2; + _interfaces[2] = interface3; + + if (interface1) _interfaceCount++; + if (interface2) _interfaceCount++; + if (interface3) _interfaceCount++; +} + +const char *RTTI::getClassName() const { + return _className; +} + +bool RTTI::isExactly(const RTTI &rtti) const { + return !strcmp(this->_className, rtti._className); +} + +bool RTTI::instanceOf(const RTTI &rtti) const { + // Check the main inheritance chain + const RTTI *pCompare = this; + while (pCompare) { + if (!strcmp(pCompare->_className, rtti._className)) return true; + + // Check interfaces at this level of the hierarchy + for (int i = 0; i < pCompare->_interfaceCount; i++) { + if (pCompare->_interfaces[i] && !strcmp(pCompare->_interfaces[i]->_className, rtti._className)) { + return true; + } + } + + pCompare = pCompare->_pBaseRTTI; + } + + return false; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/RegionAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/RegionAttachment.cpp new file mode 100644 index 0000000..0492c67 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/RegionAttachment.cpp @@ -0,0 +1,258 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(RegionAttachment, Attachment) + +const int RegionAttachment::BLX = 0; +const int RegionAttachment::BLY = 1; +const int RegionAttachment::ULX = 2; +const int RegionAttachment::ULY = 3; +const int RegionAttachment::URX = 4; +const int RegionAttachment::URY = 5; +const int RegionAttachment::BRX = 6; +const int RegionAttachment::BRY = 7; + +RegionAttachment::RegionAttachment(const String &name, Sequence *sequence) + : Attachment(name), _sequence(sequence), _x(0), _y(0), _scaleX(1), _scaleY(1), _rotation(0), _width(0), _height(0), _path(), _color(1, 1, 1, 1) { + assert(sequence); +} + +RegionAttachment::~RegionAttachment() { + delete _sequence; +} + +void RegionAttachment::computeWorldVertices(Slot &slot, Array &vertexOffsets, Array &worldVertices, size_t offset, size_t stride) { + assert(worldVertices.size() >= (offset + 8)); + computeWorldVertices(slot, vertexOffsets.buffer(), worldVertices.buffer(), offset, stride); +} + +void RegionAttachment::computeWorldVertices(Slot &slot, float *vertexOffsets, float *worldVertices, size_t offset, size_t stride) { + BonePose &bone = slot.getBone().getAppliedPose(); + float x = bone.getWorldX(), y = bone.getWorldY(); + float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD(); + + float offsetX = vertexOffsets[BRX]; + float offsetY = vertexOffsets[BRY]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = vertexOffsets[BLX]; + offsetY = vertexOffsets[BLY]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = vertexOffsets[ULX]; + offsetY = vertexOffsets[ULY]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = vertexOffsets[URX]; + offsetY = vertexOffsets[URY]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; +} + +Array &RegionAttachment::getOffsets(SlotPose &pose) { + return _sequence->getOffsets(_sequence->resolveIndex(pose)); +} + +float RegionAttachment::getX() { + return _x; +} + +void RegionAttachment::setX(float inValue) { + _x = inValue; +} + +float RegionAttachment::getY() { + return _y; +} + +void RegionAttachment::setY(float inValue) { + _y = inValue; +} + +float RegionAttachment::getScaleX() { + return _scaleX; +} + +void RegionAttachment::setScaleX(float inValue) { + _scaleX = inValue; +} + +float RegionAttachment::getScaleY() { + return _scaleY; +} + +void RegionAttachment::setScaleY(float inValue) { + _scaleY = inValue; +} + +float RegionAttachment::getRotation() { + return _rotation; +} + +void RegionAttachment::setRotation(float inValue) { + _rotation = inValue; +} + +float RegionAttachment::getWidth() { + return _width; +} + +void RegionAttachment::setWidth(float inValue) { + _width = inValue; +} + +float RegionAttachment::getHeight() { + return _height; +} + +void RegionAttachment::setHeight(float inValue) { + _height = inValue; +} + +Sequence &RegionAttachment::getSequence() { + return *_sequence; +} + +void RegionAttachment::updateSequence() { + _sequence->update(*this); +} + +const String &RegionAttachment::getPath() { + return _path; +} + +void RegionAttachment::setPath(const String &inValue) { + _path = inValue; +} + +Color &RegionAttachment::getColor() { + return _color; +} + +Attachment &RegionAttachment::copy() { + RegionAttachment *copy = new (__FILE__, __LINE__) RegionAttachment(getName(), new (__FILE__, __LINE__) Sequence(*_sequence)); + copy->setTimelineAttachment(getTimelineAttachment()); + copy->setTimelineSlots(getTimelineSlots()); + copy->_path = _path; + copy->_x = _x; + copy->_y = _y; + copy->_scaleX = _scaleX; + copy->_scaleY = _scaleY; + copy->_rotation = _rotation; + copy->_width = _width; + copy->_height = _height; + copy->_color.set(_color); + return *copy; +} + +void RegionAttachment::computeUVs(TextureRegion *region, float x, float y, float scaleX, float scaleY, float rotation, float width, float height, + Array &offset, Array &uvs) { + float localX2 = width / 2, localY2 = height / 2; + float localX = -localX2, localY = -localY2; + bool rotated = false; + if (region != NULL && region->getRTTI().instanceOf(AtlasRegion::rtti)) { + AtlasRegion *r = static_cast(region); + localX += r->_offsetX / r->_originalWidth * width; + localY += r->_offsetY / r->_originalHeight * height; + if (r->_degrees == 90) { + rotated = true; + localX2 -= (r->_originalWidth - r->_offsetX - r->_packedHeight) / r->_originalWidth * width; + localY2 -= (r->_originalHeight - r->_offsetY - r->_packedWidth) / r->_originalHeight * height; + } else { + localX2 -= (r->_originalWidth - r->_offsetX - r->_packedWidth) / r->_originalWidth * width; + localY2 -= (r->_originalHeight - r->_offsetY - r->_packedHeight) / r->_originalHeight * height; + } + } + localX *= scaleX; + localY *= scaleY; + localX2 *= scaleX; + localY2 *= scaleY; + float cos = MathUtil::cosDeg(rotation); + float sin = MathUtil::sinDeg(rotation); + float localXCos = localX * cos + x; + float localXSin = localX * sin; + float localYCos = localY * cos + y; + float localYSin = localY * sin; + float localX2Cos = localX2 * cos + x; + float localX2Sin = localX2 * sin; + float localY2Cos = localY2 * cos + y; + float localY2Sin = localY2 * sin; + offset[BLX] = localXCos - localYSin; + offset[BLY] = localYCos + localXSin; + offset[ULX] = localXCos - localY2Sin; + offset[ULY] = localY2Cos + localXSin; + offset[URX] = localX2Cos - localY2Sin; + offset[URY] = localY2Cos + localX2Sin; + offset[BRX] = localX2Cos - localYSin; + offset[BRY] = localYCos + localX2Sin; + if (region == NULL) { + uvs[BLX] = 0; + uvs[BLY] = 0; + uvs[ULX] = 0; + uvs[ULY] = 1; + uvs[URX] = 1; + uvs[URY] = 1; + uvs[BRX] = 1; + uvs[BRY] = 0; + } else { + uvs[BLX] = region->_u2; + uvs[ULY] = region->_v2; + uvs[URX] = region->_u; + uvs[BRY] = region->_v; + if (rotated) { + uvs[BLY] = region->_v; + uvs[ULX] = region->_u2; + uvs[URY] = region->_v2; + uvs[BRX] = region->_u; + } else { + uvs[BLY] = region->_v2; + uvs[ULX] = region->_u; + uvs[URY] = region->_v; + uvs[BRX] = region->_u2; + } + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/RotateTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/RotateTimeline.cpp new file mode 100644 index 0000000..ead49bb --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/RotateTimeline.cpp @@ -0,0 +1,45 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +RTTI_IMPL(RotateTimeline, BoneTimeline1) + +RotateTimeline::RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) + : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Rotate) { +} + +void RotateTimeline::_apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) { + SP_UNUSED(out); + pose._rotation = getRelativeValue(time, alpha, from, add, pose._rotation, setup._rotation); +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ScaleTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ScaleTimeline.cpp new file mode 100644 index 0000000..e620def --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ScaleTimeline.cpp @@ -0,0 +1,137 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(ScaleTimeline, BoneTimeline2) + +ScaleTimeline::ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex) + : BoneTimeline2(frameCount, bezierCount, boneIndex, Property_ScaleX, Property_ScaleY) { +} + +void ScaleTimeline::_apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) { + if (time < _frames[0]) { + switch (from) { + case MixFrom_Setup: + pose._scaleX = setup._scaleX; + pose._scaleY = setup._scaleY; + break; + case MixFrom_First: + pose._scaleX += (setup._scaleX - pose._scaleX) * alpha; + pose._scaleY += (setup._scaleY - pose._scaleY) * alpha; + break; + case MixFrom_Current: + break; + } + return; + } + + float x, y; + int i = Animation::search(_frames, time, BoneTimeline2::ENTRIES); + int curveType = (int) _curves[i / BoneTimeline2::ENTRIES]; + switch (curveType) { + case CurveTimeline::LINEAR: { + float before = _frames[i]; + x = _frames[i + BoneTimeline2::VALUE1]; + y = _frames[i + BoneTimeline2::VALUE2]; + float t = (time - before) / (_frames[i + BoneTimeline2::ENTRIES] - before); + x += (_frames[i + BoneTimeline2::ENTRIES + BoneTimeline2::VALUE1] - x) * t; + y += (_frames[i + BoneTimeline2::ENTRIES + BoneTimeline2::VALUE2] - y) * t; + break; + } + case CurveTimeline::STEPPED: { + x = _frames[i + BoneTimeline2::VALUE1]; + y = _frames[i + BoneTimeline2::VALUE2]; + break; + } + default: { + x = getBezierValue(time, i, BoneTimeline2::VALUE1, curveType - BoneTimeline2::BEZIER); + y = getBezierValue(time, i, BoneTimeline2::VALUE2, curveType + BoneTimeline2::BEZIER_SIZE - BoneTimeline2::BEZIER); + } + } + x *= setup._scaleX; + y *= setup._scaleY; + + if (alpha == 1 && !add) { + pose._scaleX = x; + pose._scaleY = y; + } else { + float bx, by; + if (from == MixFrom_Setup) { + bx = setup._scaleX; + by = setup._scaleY; + } else { + bx = pose._scaleX; + by = pose._scaleY; + } + if (add) { + pose._scaleX = bx + (x - setup._scaleX) * alpha; + pose._scaleY = by + (y - setup._scaleY) * alpha; + } else if (out) { + pose._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; + pose._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; + } else { + bx = MathUtil::abs(bx) * MathUtil::sign(x); + by = MathUtil::abs(by) * MathUtil::sign(y); + pose._scaleX = bx + (x - bx) * alpha; + pose._scaleY = by + (y - by) * alpha; + } + } +} + +RTTI_IMPL(ScaleXTimeline, BoneTimeline1) + +ScaleXTimeline::ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) + : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleX) { +} + +void ScaleXTimeline::_apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) { + pose._scaleX = getScaleValue(time, alpha, from, add, out, pose._scaleX, setup._scaleX); +} + +RTTI_IMPL(ScaleYTimeline, BoneTimeline1) + +ScaleYTimeline::ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) + : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleY) { +} + +void ScaleYTimeline::_apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) { + pose._scaleY = getScaleValue(time, alpha, from, add, out, pose._scaleY, setup._scaleY); +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Sequence.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Sequence.cpp new file mode 100644 index 0000000..f428258 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Sequence.cpp @@ -0,0 +1,110 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include + +using namespace spine; + +int Sequence::_nextID = 0; + +Sequence::Sequence(int count, bool pathSuffix) + : _id(nextID()), _regions(count), _pathSuffix(pathSuffix), _uvs(), _offsets(), _start(0), _digits(0), _setupIndex(0) { + _regions.setSize(count, NULL); +} + +Sequence::Sequence(const Sequence &other) + : _id(nextID()), _regions(other._regions), _pathSuffix(other._pathSuffix), _uvs(other._uvs), _offsets(other._offsets), _start(other._start), + _digits(other._digits), _setupIndex(other._setupIndex) { +} + +Sequence::~Sequence() { +} + +void Sequence::update(RegionAttachment &attachment) { + int regionCount = (int) _regions.size(); + Array empty; + _uvs.setSize(regionCount, empty); + _offsets.setSize(regionCount, empty); + for (int i = 0; i < regionCount; i++) { + _uvs[i].setSize(8, 0); + _offsets[i].setSize(8, 0); + RegionAttachment::computeUVs(_regions[i], attachment.getX(), attachment.getY(), attachment.getScaleX(), attachment.getScaleY(), + attachment.getRotation(), attachment.getWidth(), attachment.getHeight(), _offsets[i], _uvs[i]); + } +} + +void Sequence::update(MeshAttachment &attachment) { + int regionCount = (int) _regions.size(); + Array empty; + _uvs.setSize(regionCount, empty); + _offsets.clear(); + for (int i = 0; i < regionCount; i++) { + _uvs[i].setSize(attachment.getRegionUVs().size(), 0); + MeshAttachment::computeUVs(_regions[i], attachment.getRegionUVs(), _uvs[i]); + } +} + +int Sequence::resolveIndex(SlotPose &pose) { + int index = pose.getSequenceIndex(); + if (index == -1) index = _setupIndex; + if (index >= (int) _regions.size()) index = (int) _regions.size() - 1; + return index; +} + +TextureRegion *Sequence::getRegion(int index) { + return _regions[index]; +} + +Array &Sequence::getUVs(int index) { + return _uvs[index]; +} + +Array &Sequence::getOffsets(int index) { + return _offsets[index]; +} + +String &Sequence::getPath(const String &basePath, int index) { + if (!_pathSuffix) { + _tmpPath = basePath; + return _tmpPath; + } + _tmpPath = basePath; + String frame; + frame.append(_start + index); + for (int i = _digits - (int) frame.length(); i > 0; i--) _tmpPath.append("0"); + _tmpPath.append(frame); + return _tmpPath; +} + +int Sequence::nextID() { + return _nextID++; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SequenceTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SequenceTimeline.cpp new file mode 100644 index 0000000..e12ef7d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SequenceTimeline.cpp @@ -0,0 +1,156 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL_MULTI(SequenceTimeline, Timeline, SlotTimeline) + +SequenceTimeline::SequenceTimeline(size_t frameCount, int slotIndex, Attachment &attachment) + : Timeline(frameCount, ENTRIES), SlotTimeline(), _slotIndex(slotIndex), _attachment(&attachment) { + _instant = true; + int sequenceId = 0; + if (attachment.getRTTI().instanceOf(RegionAttachment::rtti)) sequenceId = ((RegionAttachment *) &attachment)->getSequence().getId(); + if (attachment.getRTTI().instanceOf(MeshAttachment::rtti)) sequenceId = ((MeshAttachment *) &attachment)->getSequence().getId(); + PropertyId ids[] = {((PropertyId) Property_Sequence << 32) | ((slotIndex << 16 | sequenceId) & 0xffffffff)}; + setPropertyIds(ids, 1); +} + +SequenceTimeline::~SequenceTimeline() { +} + +void SequenceTimeline::setFrame(int frame, float time, SequenceMode mode, int index, float delay) { + Array &frames = this->_frames; + frame *= ENTRIES; + frames[frame] = time; + frames[frame + MODE] = mode | (index << 4); + frames[frame + DELAY] = delay; +} + +int SequenceTimeline::getSlotIndex() { + return _slotIndex; +} + +void SequenceTimeline::setSlotIndex(int inValue) { + _slotIndex = inValue; +} + +void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) { + SP_UNUSED(alpha); + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(add); + + Array &slots = skeleton.getSlots(); + if (!_attachment->isTimelineActive(slots, getSlotIndex(), appliedPose)) return; + Array &timelineSlots = _attachment->getTimelineSlots(); + + Sequence *sequence = NULL; + if (_attachment->getRTTI().instanceOf(RegionAttachment::rtti)) sequence = &static_cast(_attachment)->getSequence(); + if (_attachment->getRTTI().instanceOf(MeshAttachment::rtti)) sequence = &static_cast(_attachment)->getSequence(); + if (!sequence) return; + + Array &frames = this->_frames; + if (out || time < frames[0]) { + if (from != MixFrom_Current) { + setupPose(*slots[getSlotIndex()], appliedPose); + for (size_t i = 0; i < timelineSlots.size(); ++i) setupPose(*slots[timelineSlots[i]], appliedPose); + } + return; + } + + int i = Animation::search(frames, time, ENTRIES); + float before = frames[i]; + int modeAndIndex = (int) frames[i + MODE]; + float delay = frames[i + DELAY]; + + applyToSlot(*slots[getSlotIndex()], appliedPose, *sequence, time, before, modeAndIndex, delay); + for (size_t j = 0; j < timelineSlots.size(); ++j) + applyToSlot(*slots[timelineSlots[j]], appliedPose, *sequence, time, before, modeAndIndex, delay); +} + +void SequenceTimeline::setupPose(Slot &slot, bool appliedPose) { + if (!slot.getBone().isActive()) return; + SlotPose &pose = appliedPose ? slot.getAppliedPose() : slot.getPose(); + Attachment *attachment = pose.getAttachment(); + if (attachment == NULL || attachment->getTimelineAttachment() != _attachment) return; + pose.setSequenceIndex(-1); +} + +void SequenceTimeline::applyToSlot(Slot &slot, bool appliedPose, Sequence &sequence, float time, float before, int modeAndIndex, float delay) { + if (!slot.getBone().isActive()) return; + SlotPose &pose = appliedPose ? slot.getAppliedPose() : slot.getPose(); + Attachment *attachment = pose.getAttachment(); + if (attachment == NULL || attachment->getTimelineAttachment() != _attachment) return; + + int index = modeAndIndex >> 4, count = (int) sequence.getRegions().size(); + int mode = modeAndIndex & 0xf; + if (mode != SequenceMode_hold) { + index += (int) (((time - before) / delay + 0.0001)); + switch (mode) { + case SequenceMode_once: + index = MathUtil::min(count - 1, index); + break; + case SequenceMode_loop: + index %= count; + break; + case SequenceMode_pingpong: { + int n = (count << 1) - 2; + index = n == 0 ? 0 : index % n; + if (index >= count) index = n - index; + break; + } + case SequenceMode_onceReverse: + index = MathUtil::max(count - 1 - index, 0); + break; + case SequenceMode_loopReverse: + index = count - 1 - (index % count); + break; + case SequenceMode_pingpongReverse: { + int n = (count << 1) - 2; + index = n == 0 ? 0 : (index + count - 1) % n; + if (index >= count) index = n - index; + break; + } + } + } + pose.setSequenceIndex(index); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ShearTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ShearTimeline.cpp new file mode 100644 index 0000000..1ff0c16 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/ShearTimeline.cpp @@ -0,0 +1,123 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(ShearTimeline, BoneTimeline2) + +ShearTimeline::ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex) + : BoneTimeline2(frameCount, bezierCount, boneIndex, Property_ShearX, Property_ShearY) { +} + +void ShearTimeline::_apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) { + SP_UNUSED(out); + if (time < _frames[0]) { + switch (from) { + case MixFrom_Setup: + pose._shearX = setup._shearX; + pose._shearY = setup._shearY; + break; + case MixFrom_First: + pose._shearX += (setup._shearX - pose._shearX) * alpha; + pose._shearY += (setup._shearY - pose._shearY) * alpha; + break; + case MixFrom_Current: + break; + } + return; + } + + float x, y; + int i = Animation::search(_frames, time, BoneTimeline2::ENTRIES); + int curveType = (int) _curves[i / BoneTimeline2::ENTRIES]; + switch (curveType) { + case CurveTimeline::LINEAR: { + float before = _frames[i]; + x = _frames[i + BoneTimeline2::VALUE1]; + y = _frames[i + BoneTimeline2::VALUE2]; + float t = (time - before) / (_frames[i + BoneTimeline2::ENTRIES] - before); + x += (_frames[i + BoneTimeline2::ENTRIES + BoneTimeline2::VALUE1] - x) * t; + y += (_frames[i + BoneTimeline2::ENTRIES + BoneTimeline2::VALUE2] - y) * t; + break; + } + case CurveTimeline::STEPPED: { + x = _frames[i + BoneTimeline2::VALUE1]; + y = _frames[i + BoneTimeline2::VALUE2]; + break; + } + default: { + x = getBezierValue(time, i, BoneTimeline2::VALUE1, curveType - BoneTimeline2::BEZIER); + y = getBezierValue(time, i, BoneTimeline2::VALUE2, curveType + BoneTimeline2::BEZIER_SIZE - BoneTimeline2::BEZIER); + } + } + + if (from == MixFrom_Setup) { + pose._shearX = setup._shearX + x * alpha; + pose._shearY = setup._shearY + y * alpha; + } else if (add) { + pose._shearX += x * alpha; + pose._shearY += y * alpha; + } else { + pose._shearX += (setup._shearX + x - pose._shearX) * alpha; + pose._shearY += (setup._shearY + y - pose._shearY) * alpha; + } +} + +RTTI_IMPL(ShearXTimeline, BoneTimeline1) + +ShearXTimeline::ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) + : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearX) { +} + +void ShearXTimeline::_apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) { + SP_UNUSED(out); + pose._shearX = getRelativeValue(time, alpha, from, add, pose._shearX, setup._shearX); +} + +RTTI_IMPL(ShearYTimeline, BoneTimeline1) + +ShearYTimeline::ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) + : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearY) { +} + +void ShearYTimeline::_apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) { + SP_UNUSED(out); + pose._shearY = getRelativeValue(time, alpha, from, add, pose._shearY, setup._shearY); +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Skeleton.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Skeleton.cpp new file mode 100644 index 0000000..0f7a4ba --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Skeleton.cpp @@ -0,0 +1,550 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace spine; + +Skeleton::Skeleton(SkeletonData &skeletonData) + : _data(skeletonData), _drawOrder(_slots), _skin(NULL), _color(1, 1, 1, 1), _x(0), _y(0), _scaleX(1), _scaleY(1), _windX(1), _windY(0), + _gravityX(0), _gravityY(1), _time(0), _update(0) { + + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); ++i) { + BoneData *data = _data.getBones()[i]; + + Bone *bone; + if (data->getParent() == NULL) { + bone = new (__FILE__, __LINE__) Bone(*data, NULL); + } else { + Bone *parent = _bones[data->getParent()->getIndex()]; + bone = new (__FILE__, __LINE__) Bone(*data, parent); + parent->getChildren().add(bone); + } + + _bones.add(bone); + } + + _slots.ensureCapacity(_data.getSlots().size()); + for (size_t i = 0; i < _data.getSlots().size(); ++i) { + SlotData *data = _data.getSlots()[i]; + Slot *slot = new (__FILE__, __LINE__) Slot(*data, *this); + _slots.add(slot); + } + _drawOrder.setupPose(); + + _physics.ensureCapacity(8); + _constraints.ensureCapacity(_data.getConstraints().size()); + for (size_t i = 0; i < _data.getConstraints().size(); ++i) { + ConstraintData *constraintData = _data.getConstraints()[i]; + Constraint *constraint = &constraintData->create(*this); + if (constraint->getRTTI().instanceOf(PhysicsConstraint::rtti)) { + _physics.add(static_cast(constraint)); + } + _constraints.add(constraint); + } + + updateCache(); +} + +Skeleton::~Skeleton() { + ArrayUtils::deleteElements(_bones); + ArrayUtils::deleteElements(_slots); + ArrayUtils::deleteElements(_constraints); +} + +void Skeleton::updateCache() { + _updateCache.clear(); + _resetCache.clear(); + + _drawOrder.unconstrained(); + Slot **slots = _slots.buffer(); + for (size_t i = 0, n = _slots.size(); i < n; i++) { + slots[i]->unconstrained(); + } + + size_t boneCount = _bones.size(); + Bone **bones = _bones.buffer(); + for (size_t i = 0; i < boneCount; i++) { + Bone *bone = bones[i]; + bone->_sorted = bone->_data.getSkinRequired(); + bone->_active = !bone->_sorted; + bone->unconstrained(); + } + + if (_skin) { + Array &skinBones = _skin->getBones(); + for (size_t i = 0, n = skinBones.size(); i < n; i++) { + Bone *bone = _bones[skinBones[i]->getIndex()]; + do { + bone->_sorted = false; + bone->_active = true; + bone = bone->_parent; + } while (bone); + } + } + + Constraint **constraints = _constraints.buffer(); + size_t n = _constraints.size(); + for (size_t i = 0; i < n; i++) { + constraints[i]->unconstrained(); + } + for (size_t i = 0; i < n; i++) { + Constraint *constraint = constraints[i]; + constraint->_active = constraint->isSourceActive() && + ((!constraint->getData().getSkinRequired()) || (_skin && _skin->_constraints.contains(&constraint->getData()))); + if (constraint->_active) constraint->sort(*this); + } + + for (size_t i = 0; i < boneCount; i++) { + sortBone(bones[i]); + } + + Update **updateCache = _updateCache.buffer(); + n = _updateCache.size(); + for (size_t i = 0; i < n; i++) { + const RTTI &rtti = updateCache[i]->getRTTI(); + if (rtti.instanceOf(Bone::rtti)) { + Bone *bone = (Bone *) (updateCache[i]); + updateCache[i] = bone->_appliedPose; + } + } +} + +void Skeleton::printUpdateCache() { + for (size_t i = 0; i < _updateCache.size(); i++) { + Update *updatable = _updateCache[i]; + if (updatable->getRTTI().isExactly(Bone::rtti)) { + printf("bone %s\n", ((Bone *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(TransformConstraint::rtti)) { + printf("transform constraint %s\n", ((TransformConstraint *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(IkConstraint::rtti)) { + printf("ik constraint %s\n", ((IkConstraint *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(PathConstraint::rtti)) { + printf("path constraint %s\n", ((PathConstraint *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(PhysicsConstraint::rtti)) { + printf("physics constraint %s\n", ((PhysicsConstraint *) updatable)->getData().getName().buffer()); + } else if (updatable->getRTTI().isExactly(Slider::rtti)) { + printf("slider %s\n", ((Slider *) updatable)->getData().getName().buffer()); + } + } +} + +void Skeleton::constrained(Posed &object) { + if (object.isPoseEqualToApplied()) { + object.constrained(); + _resetCache.add(&object); + } +} + +void Skeleton::sortBone(Bone *bone) { + if (bone->_sorted || !bone->_active) return; + Bone *parent = bone->_parent; + if (parent != NULL) sortBone(parent); + bone->_sorted = true; + _updateCache.add((Update *) bone); +} + +void Skeleton::sortReset(Array &bones) { + Bone **items = bones.buffer(); + for (size_t i = 0, n = bones.size(); i < n; i++) { + Bone *bone = items[i]; + if (bone->_active) { + if (bone->_sorted) sortReset(bone->getChildren()); + bone->_sorted = false; + } + } +} + +void Skeleton::updateWorldTransform(Physics physics) { + _update++; + + if (_drawOrder._appliedPose == &_drawOrder._constrainedPose) _drawOrder.reset(); + Posed **resetCache = _resetCache.buffer(); + for (size_t i = 0, n = _resetCache.size(); i < n; i++) { + resetCache[i]->resetConstrained(); + } + + Update **updateCache = _updateCache.buffer(); + for (size_t i = 0, n = _updateCache.size(); i < n; i++) { + updateCache[i]->update(*this, physics); + } +} + +void Skeleton::setupPose() { + setupPoseBones(); + setupPoseSlots(); +} + +void Skeleton::setupPoseBones() { + Bone **bones = _bones.buffer(); + for (size_t i = 0, n = _bones.size(); i < n; ++i) { + bones[i]->setupPose(); + } + + Constraint **constraints = _constraints.buffer(); + for (size_t i = 0, n = _constraints.size(); i < n; ++i) { + constraints[i]->setupPose(); + } +} + +void Skeleton::setupPoseSlots() { + Slot **slots = _slots.buffer(); + size_t n = _slots.size(); + _drawOrder.setupPose(); + for (size_t i = 0; i < n; ++i) { + slots[i]->setupPose(); + } +} + +SkeletonData &Skeleton::getData() { + return _data; +} + +Array &Skeleton::getBones() { + return _bones; +} + +Array &Skeleton::getUpdateCache() { + return _updateCache; +} + +Bone *Skeleton::getRootBone() { + return _bones.size() == 0 ? NULL : _bones[0]; +} + +Bone *Skeleton::findBone(const String &boneName) { + if (boneName.isEmpty()) return NULL; + Bone **bones = _bones.buffer(); + for (size_t i = 0, n = _bones.size(); i < n; i++) { + if (bones[i]->_data.getName() == boneName) return bones[i]; + } + return NULL; +} + +Array &Skeleton::getSlots() { + return _slots; +} + +Slot *Skeleton::findSlot(const String &slotName) { + if (slotName.isEmpty()) return NULL; + Slot **slots = _slots.buffer(); + for (size_t i = 0, n = _slots.size(); i < n; i++) { + if (slots[i]->_data.getName() == slotName) return slots[i]; + } + return NULL; +} + +DrawOrder &Skeleton::getDrawOrder() { + return _drawOrder; +} + +Skin *Skeleton::getSkin() { + return _skin; +} + +void Skeleton::setSkin(const String &skinName) { + Skin *skin = skinName.isEmpty() ? NULL : _data.findSkin(skinName); + if (skin == NULL) return; + setSkin(skin); +} + +void Skeleton::setSkin(Skin *newSkin) { + if (_skin == newSkin) return; + if (newSkin != NULL) { + if (_skin != NULL) { + newSkin->attachAll(*this, *_skin); + } else { + Slot **slots = _slots.buffer(); + for (size_t i = 0, n = _slots.size(); i < n; ++i) { + Slot *slot = slots[i]; + const String &name = slot->_data.getAttachmentName(); + if (name.length() > 0) { + Attachment *attachment = newSkin->getAttachment(i, name); + if (attachment != NULL) { + slot->_pose.setAttachment(attachment); + } + } + } + } + } + _skin = newSkin; + updateCache(); +} + +Attachment *Skeleton::getAttachment(const String &slotName, const String &placeholder) { + SlotData *slot = _data.findSlot(slotName); + if (slot == NULL) return NULL; + return getAttachment(slot->getIndex(), placeholder); +} + +Attachment *Skeleton::getAttachment(int slotIndex, const String &placeholder) { + if (placeholder.isEmpty()) return NULL; + if (_skin != NULL) { + Attachment *attachment = _skin->getAttachment(slotIndex, placeholder); + if (attachment != NULL) return attachment; + } + if (_data.getDefaultSkin() != NULL) return _data.getDefaultSkin()->getAttachment(slotIndex, placeholder); + return NULL; +} + +void Skeleton::setAttachment(const String &slotName, const String &placeholder) { + if (slotName.isEmpty()) return; + Slot *slot = findSlot(slotName); + if (slot == NULL) return; + Attachment *attachment = NULL; + if (!placeholder.isEmpty()) { + attachment = getAttachment(slot->_data.getIndex(), placeholder); + if (attachment == NULL) return; + } + slot->_pose.setAttachment(attachment); +} + +Array &Skeleton::getConstraints() { + return _constraints; +} + +Array &Skeleton::getPhysicsConstraints() { + return _physics; +} + +void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight) { + Array outVertexBuffer; + getBounds(outX, outY, outWidth, outHeight, outVertexBuffer, NULL); +} + +void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Array &outVertexBuffer, SkeletonClipping *clipper) { + static unsigned short quadIndices[] = {0, 1, 2, 2, 3, 0}; + float minX = FLT_MAX; + float minY = FLT_MAX; + float maxX = -FLT_MAX; + float maxY = -FLT_MAX; + + Array &drawOrder = _drawOrder.getAppliedPose(); + Slot **drawOrderSlots = drawOrder.buffer(); + for (size_t i = 0, n = drawOrder.size(); i < n; ++i) { + Slot *slot = drawOrderSlots[i]; + if (!slot->_bone._active) continue; + size_t verticesLength = 0; + float *vertices = NULL; + unsigned short *triangles = NULL; + size_t trianglesLength = 0; + Attachment *attachment = slot->getAppliedPose().getAttachment(); + + if (attachment != NULL) { + if (attachment->getRTTI().instanceOf(RegionAttachment::rtti)) { + RegionAttachment *regionAttachment = static_cast(attachment); + verticesLength = 8; + outVertexBuffer.setSize(8, 0); + regionAttachment->computeWorldVertices(*slot, regionAttachment->getOffsets(slot->getAppliedPose()), outVertexBuffer, 0, 2); + vertices = outVertexBuffer.buffer(); + triangles = quadIndices; + trianglesLength = 6; + } else if (attachment->getRTTI().instanceOf(MeshAttachment::rtti)) { + MeshAttachment *mesh = static_cast(attachment); + verticesLength = mesh->getWorldVerticesLength(); + outVertexBuffer.setSize(verticesLength, 0); + mesh->computeWorldVertices(*this, *slot, 0, verticesLength, outVertexBuffer.buffer(), 0, 2); + vertices = outVertexBuffer.buffer(); + triangles = mesh->getTriangles().buffer(); + trianglesLength = mesh->getTriangles().size(); + } else if (attachment->getRTTI().instanceOf(ClippingAttachment::rtti) && clipper != NULL) { + clipper->clipEnd(*slot); + clipper->clipStart(*this, *slot, static_cast(attachment)); + continue; + } + + if (vertices != NULL) { + if (clipper != NULL && clipper->isClipping() && clipper->clipTriangles(vertices, triangles, trianglesLength)) { + vertices = clipper->getClippedVertices().buffer(); + verticesLength = clipper->getClippedVertices().size(); + } + for (size_t ii = 0; ii < verticesLength; ii += 2) { + float x = vertices[ii], y = vertices[ii + 1]; + minX = MathUtil::min(minX, x); + minY = MathUtil::min(minY, y); + maxX = MathUtil::max(maxX, x); + maxY = MathUtil::max(maxY, y); + } + } + } + if (clipper != NULL) clipper->clipEnd(*slot); + } + if (clipper != NULL) clipper->clipEnd(); + + outX = minX; + outY = minY; + outWidth = maxX - minX; + outHeight = maxY - minY; +} + +Color &Skeleton::getColor() { + return _color; +} + +void Skeleton::setColor(Color &color) { + _color.set(color.r, color.g, color.b, color.a); +} + +void Skeleton::setColor(float r, float g, float b, float a) { + _color.set(r, g, b, a); +} + +float Skeleton::getScaleX() { + return _scaleX; +} + +void Skeleton::setScaleX(float inValue) { + _scaleX = inValue; +} + +float Skeleton::getScaleY() { + return _scaleY * (Bone::isYDown() ? -1 : 1); +} + +void Skeleton::setScaleY(float inValue) { + _scaleY = inValue; +} + +void Skeleton::setScale(float scaleX, float scaleY) { + _scaleX = scaleX; + _scaleY = scaleY; +} + +float Skeleton::getX() { + return _x; +} + +void Skeleton::setX(float inValue) { + _x = inValue; +} + +float Skeleton::getY() { + return _y; +} + +void Skeleton::setY(float inValue) { + _y = inValue; +} + +void Skeleton::setPosition(float x, float y) { + _x = x; + _y = y; +} + +void Skeleton::getPosition(float &x, float &y) { + x = _x; + y = _y; +} + +float Skeleton::getWindX() { + return _windX; +} + +void Skeleton::setWindX(float windX) { + _windX = windX; +} + +float Skeleton::getWindY() { + return _windY; +} + +void Skeleton::setWindY(float windY) { + _windY = windY; +} + +float Skeleton::getGravityX() { + return _gravityX; +} + +void Skeleton::setGravityX(float gravityX) { + _gravityX = gravityX; +} + +float Skeleton::getGravityY() { + return _gravityY; +} + +void Skeleton::setGravityY(float gravityY) { + _gravityY = gravityY; +} + +void Skeleton::physicsTranslate(float x, float y) { + PhysicsConstraint **constraints = _physics.buffer(); + for (size_t i = 0, n = _physics.size(); i < n; i++) { + constraints[i]->translate(x, y); + } +} + +void Skeleton::physicsRotate(float x, float y, float degrees) { + PhysicsConstraint **constraints = _physics.buffer(); + for (size_t i = 0, n = _physics.size(); i < n; i++) { + constraints[i]->rotate(x, y, degrees); + } +} + +float Skeleton::getTime() { + return _time; +} + +void Skeleton::setTime(float time) { + _time = time; +} + +void Skeleton::update(float delta) { + _time += delta; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonBinary.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonBinary.cpp new file mode 100644 index 0000000..3ac5894 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonBinary.cpp @@ -0,0 +1,1475 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +SkeletonBinary::SkeletonBinary(Atlas &atlas) + : _attachmentLoader(new(__FILE__, __LINE__) AtlasAttachmentLoader(atlas)), _error(), _scale(1), _ownsLoader(true) { +} + +SkeletonBinary::SkeletonBinary(AttachmentLoader &attachmentLoader, bool ownsLoader) + : _attachmentLoader(&attachmentLoader), _error(), _scale(1), _ownsLoader(ownsLoader) { +} + +SkeletonBinary::~SkeletonBinary() { + ArrayUtils::deleteElements(_linkedMeshes); + _linkedMeshes.clear(); + + if (_ownsLoader) delete _attachmentLoader; +} + +SkeletonData *SkeletonBinary::readSkeletonDataFile(const String &path) { + int length; + const char *binary = SpineExtension::readFile(path.buffer(), &length); + if (length == 0 || !binary) { + setError("Unable to read skeleton file: ", path.buffer()); + return NULL; + } + + SkeletonData *skeletonData = readSkeletonData((unsigned char *) binary, length); + SpineExtension::free(binary, __FILE__, __LINE__); + + if (skeletonData) { + // Extract filename without extension + const char *lastSlash = strrchr(path.buffer(), '/'); + const char *lastBackslash = strrchr(path.buffer(), '\\'); + const char *filename = path.buffer(); + if (lastSlash) filename = lastSlash + 1; + if (lastBackslash && lastBackslash > filename) filename = lastBackslash + 1; + + String nameWithoutExtension(filename); + const char *lastDot = strrchr(nameWithoutExtension.buffer(), '.'); + if (lastDot) { + length = (int) (lastDot - nameWithoutExtension.buffer()); + nameWithoutExtension = nameWithoutExtension.substring(0, length); + } + skeletonData->_name = nameWithoutExtension; + } + + return skeletonData; +} + +SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, const int length) { + if (binary == NULL || length == 0) { + setError("Unable to read skeleton file: ", ""); + return NULL; + } + + ArrayUtils::deleteElements(_linkedMeshes); + _linkedMeshes.clear(); + + SkeletonData *skeletonData = new (__FILE__, __LINE__) SkeletonData(); + DataInput input(skeletonData, binary, length); + String version; + {// try block in Java + long long hash = input.readLong(); + if (hash == 0) { + skeletonData->_hash = ""; + } else { + char buffer[32]; + snprintf(buffer, 32, "%lld", hash); + skeletonData->_hash = String(buffer); + } + skeletonData->_version.own(input.readString()); + if (skeletonData->_version.isEmpty()) skeletonData->_version = ""; + version = skeletonData->_version; + if (!skeletonData->_version.startsWith(SPINE_VERSION_STRING)) { + String errorMsg = "Skeleton version "; + errorMsg.append(skeletonData->_version); + errorMsg.append(" does not match runtime version "); + errorMsg.append(SPINE_VERSION_STRING); + setError(errorMsg.buffer(), ""); + delete skeletonData; + return NULL; + } + skeletonData->_x = input.readFloat(); + skeletonData->_y = input.readFloat(); + skeletonData->_width = input.readFloat(); + skeletonData->_height = input.readFloat(); + skeletonData->_referenceScale = input.readFloat() * this->_scale; + + bool nonessential = input.readBoolean(); + if (nonessential) { + skeletonData->_fps = input.readFloat(); + skeletonData->_imagesPath.own(input.readString()); + skeletonData->_audioPath.own(input.readString()); + } + + int n = input.readInt(true); + Array &strings = skeletonData->_strings.setSize(n, NULL); + for (int i = 0; i < n; i++) strings[i] = input.readString(); + + /* Bones. */ + Array &bones = skeletonData->_bones.setSize(input.readInt(true), NULL); + for (int i = 0; i < (int) bones.size(); ++i) { + const char *name = input.readString(); + BoneData *parent = i == 0 ? 0 : bones[input.readInt(true)]; + BoneData *data = new (__FILE__, __LINE__) BoneData(i, String(name, true), parent); + BonePose &setup = data->_setupPose; + setup._rotation = input.readFloat(); + setup._x = input.readFloat() * _scale; + setup._y = input.readFloat() * _scale; + setup._scaleX = input.readFloat(); + setup._scaleY = input.readFloat(); + setup._shearX = input.readFloat(); + setup._shearY = input.readFloat(); + setup._inherit = static_cast(input.readByte()); + data->_length = input.readFloat() * _scale; + data->_skinRequired = input.readBoolean(); + if (nonessential) { + Color::rgba8888ToColor(data->getColor(), input.readInt()); + data->_icon.own(input.readString()); + data->_iconSize = input.readFloat(); + data->_iconRotation = input.readFloat(); + data->_visible = input.readBoolean(); + } + bones[i] = data; + } + + /* Slots. */ + Array &slots = skeletonData->_slots.setSize(input.readInt(true), NULL); + for (int i = 0; i < (int) slots.size(); ++i) { + String slotName = String(input.readString(), true); + BoneData *boneData = bones[input.readInt(true)]; + SlotData *data = new (__FILE__, __LINE__) SlotData(i, slotName, *boneData); + Color::rgba8888ToColor(data->_setupPose._color, input.readInt()); + + int darkColor = input.readInt(); + if (darkColor != -1) { + Color::rgb888ToColor(data->_setupPose._darkColor, darkColor); + data->_setupPose._hasDarkColor = true; + } + + data->_attachmentName = input.readStringRef(); + data->_blendMode = static_cast(input.readInt(true)); + if (nonessential) data->_visible = input.readBoolean(); + slots[i] = data; + } + + /* Constraints. */ + int constraintCount = input.readInt(true); + Array &constraints = skeletonData->_constraints.setSize(constraintCount, NULL); + for (int i = 0; i < constraintCount; i++) { + String name(input.readString(), true); + int nn; + switch (input.readByte()) { + case CONSTRAINT_IK: { + IkConstraintData *data = new (__FILE__, __LINE__) IkConstraintData(name); + Array &constraintBones = data->_bones.setSize(nn = input.readInt(true), NULL); + for (int ii = 0; ii < nn; ii++) constraintBones[ii] = bones[input.readInt(true)]; + data->_target = bones[input.readInt(true)]; + int flags = input.read(); + data->_skinRequired = (flags & 1) != 0; + if ((flags & 2) != 0) data->_scaleYMode = static_cast(input.read()); + IkConstraintPose &setup = data->_setupPose; + setup._bendDirection = (flags & 4) != 0 ? -1 : 1; + setup._compress = (flags & 8) != 0; + setup._stretch = (flags & 16) != 0; + if ((flags & 32) != 0) setup._mix = (flags & 64) != 0 ? input.readFloat() : 1; + if ((flags & 128) != 0) setup._softness = input.readFloat() * _scale; + constraints[i] = data; + break; + } + case CONSTRAINT_TRANSFORM: { + TransformConstraintData *data = new (__FILE__, __LINE__) TransformConstraintData(name); + Array &constraintBones = data->_bones.setSize(nn = input.readInt(true), NULL); + for (int ii = 0; ii < nn; ii++) constraintBones[ii] = bones[input.readInt(true)]; + data->_source = bones[input.readInt(true)]; + int flags = input.read(); + data->_skinRequired = (flags & 1) != 0; + data->_localSource = (flags & 2) != 0; + data->_localTarget = (flags & 4) != 0; + data->_additive = (flags & 8) != 0; + data->_clamp = (flags & 16) != 0; + Array &froms = data->_properties.setSize(nn = flags >> 5, NULL); + for (int ii = 0, tn; ii < nn; ii++) { + float fromScale = 1; + FromProperty *from = NULL; + switch (input.readByte()) { + case 0: + from = new (__FILE__, __LINE__) FromRotate(); + break; + case 1: + fromScale = _scale; + from = new (__FILE__, __LINE__) FromX(); + break; + case 2: + fromScale = _scale; + from = new (__FILE__, __LINE__) FromY(); + break; + case 3: + from = new (__FILE__, __LINE__) FromScaleX(); + break; + case 4: + from = new (__FILE__, __LINE__) FromScaleY(); + break; + case 5: + from = new (__FILE__, __LINE__) FromShearY(); + break; + } + from->_offset = input.readFloat() * fromScale; + Array &tos = from->_to.setSize(tn = input.readByte(), NULL); + for (int t = 0; t < tn; t++) { + float toScale = 1; + ToProperty *to = NULL; + switch (input.readByte()) { + case 0: + to = new (__FILE__, __LINE__) ToRotate(); + break; + case 1: + toScale = _scale; + to = new (__FILE__, __LINE__) ToX(); + break; + case 2: + toScale = _scale; + to = new (__FILE__, __LINE__) ToY(); + break; + case 3: + to = new (__FILE__, __LINE__) ToScaleX(); + break; + case 4: + to = new (__FILE__, __LINE__) ToScaleY(); + break; + case 5: + to = new (__FILE__, __LINE__) ToShearY(); + break; + } + to->_offset = input.readFloat() * toScale; + to->_max = input.readFloat() * toScale; + to->_scale = input.readFloat() * toScale / fromScale; + tos[t] = to; + } + froms[ii] = from; + } + flags = input.read(); + if ((flags & 1) != 0) data->_offsets[TransformConstraintData::ROTATION] = input.readFloat(); + if ((flags & 2) != 0) data->_offsets[TransformConstraintData::X] = input.readFloat() * _scale; + if ((flags & 4) != 0) data->_offsets[TransformConstraintData::Y] = input.readFloat() * _scale; + if ((flags & 8) != 0) data->_offsets[TransformConstraintData::SCALEX] = input.readFloat(); + if ((flags & 16) != 0) data->_offsets[TransformConstraintData::SCALEY] = input.readFloat(); + if ((flags & 32) != 0) data->_offsets[TransformConstraintData::SHEARY] = input.readFloat(); + flags = input.read(); + TransformConstraintPose &setup = data->_setupPose; + if ((flags & 1) != 0) setup._mixRotate = input.readFloat(); + if ((flags & 2) != 0) setup._mixX = input.readFloat(); + if ((flags & 4) != 0) setup._mixY = input.readFloat(); + if ((flags & 8) != 0) setup._mixScaleX = input.readFloat(); + if ((flags & 16) != 0) setup._mixScaleY = input.readFloat(); + if ((flags & 32) != 0) setup._mixShearY = input.readFloat(); + constraints[i] = data; + break; + } + case CONSTRAINT_PATH: { + PathConstraintData *data = new (__FILE__, __LINE__) PathConstraintData(name); + Array &constraintBones = data->_bones.setSize(nn = input.readInt(true), NULL); + for (int ii = 0; ii < nn; ii++) constraintBones[ii] = bones[input.readInt(true)]; + data->_slot = slots[input.readInt(true)]; + int flags = input.read(); + data->_skinRequired = (flags & 1) != 0; + data->_positionMode = (PositionMode) ((flags >> 1) & 1); + data->_spacingMode = (SpacingMode) ((flags >> 2) & 3); + data->_rotateMode = (RotateMode) ((flags >> 4) & 3); + if ((flags & 128) != 0) data->_offsetRotation = input.readFloat(); + PathConstraintPose &setup = data->_setupPose; + setup._position = input.readFloat(); + if (data->_positionMode == PositionMode_Fixed) setup._position *= _scale; + setup._spacing = input.readFloat(); + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) setup._spacing *= _scale; + setup._mixRotate = input.readFloat(); + setup._mixX = input.readFloat(); + setup._mixY = input.readFloat(); + constraints[i] = data; + break; + } + case CONSTRAINT_PHYSICS: { + PhysicsConstraintData *data = new (__FILE__, __LINE__) PhysicsConstraintData(name); + data->_bone = bones[input.readInt(true)]; + int flags = input.read(); + data->_skinRequired = (flags & 1) != 0; + if ((flags & 2) != 0) data->_x = input.readFloat(); + if ((flags & 4) != 0) data->_y = input.readFloat(); + if ((flags & 8) != 0) data->_rotate = input.readFloat(); + if ((flags & 16) != 0) { + float scaleX = input.readFloat(); + if (scaleX < -2) { + data->_scaleYMode = ScaleYMode_Volume; + scaleX = -2 - scaleX; + } else if (scaleX < 0) { + data->_scaleYMode = ScaleYMode_Uniform; + scaleX = -1 - scaleX; + } + data->_scaleX = scaleX; + } + if ((flags & 32) != 0) data->_shearX = input.readFloat(); + data->_limit = ((flags & 64) != 0 ? input.readFloat() : 5000) * _scale; + data->_step = 1.f / input.readUnsignedByte(); + PhysicsConstraintPose &setup = data->getSetupPose(); + setup._inertia = input.readFloat(); + setup._strength = input.readFloat(); + setup._damping = input.readFloat(); + setup._massInverse = (flags & 128) != 0 ? input.readFloat() : 1; + setup._wind = input.readFloat(); + setup._gravity = input.readFloat(); + flags = input.read(); + if ((flags & 1) != 0) data->_inertiaGlobal = true; + if ((flags & 2) != 0) data->_strengthGlobal = true; + if ((flags & 4) != 0) data->_dampingGlobal = true; + if ((flags & 8) != 0) data->_massGlobal = true; + if ((flags & 16) != 0) data->_windGlobal = true; + if ((flags & 32) != 0) data->_gravityGlobal = true; + if ((flags & 64) != 0) data->_mixGlobal = true; + setup._mix = (flags & 128) != 0 ? input.readFloat() : 1; + constraints[i] = data; + break; + } + case CONSTRAINT_SLIDER: { + SliderData *data = new (__FILE__, __LINE__) SliderData(name); + int flags = input.read(); + data->_skinRequired = (flags & 1) != 0; + data->_loop = (flags & 2) != 0; + data->_additive = (flags & 4) != 0; + SliderPose &setup = data->_setupPose; + if ((flags & 8) != 0) { + float value = input.readFloat(); + if (nonessential && (flags & 64) != 0) + data->_max = value; + else + setup._time = value; + } + if ((flags & 16) != 0) setup._mix = (flags & 32) != 0 ? input.readFloat() : 1; + if ((flags & 64) != 0) { + data->_local = (flags & 128) != 0; + data->_bone = bones[input.readInt(true)]; + float offset = input.readFloat(); + float propertyScale = 1; + switch (input.readByte()) { + case 0: + data->_property = new (__FILE__, __LINE__) FromRotate(); + break; + case 1: + propertyScale = _scale; + data->_property = new (__FILE__, __LINE__) FromX(); + break; + case 2: + propertyScale = _scale; + data->_property = new (__FILE__, __LINE__) FromY(); + break; + case 3: + data->_property = new (__FILE__, __LINE__) FromScaleX(); + break; + case 4: + data->_property = new (__FILE__, __LINE__) FromScaleY(); + break; + case 5: + data->_property = new (__FILE__, __LINE__) FromShearY(); + break; + default: + data->_property = NULL; + break; + } + if (data->_property) data->_property->_offset = offset * propertyScale; + data->_offset = input.readFloat(); + data->_scale = input.readFloat() / propertyScale; + } + constraints[i] = data; + break; + } + } + } + + /* Default skin. */ + Skin *defaultSkin = readSkin(input, *skeletonData, true, nonessential); + if (defaultSkin) { + skeletonData->_defaultSkin = defaultSkin; + skeletonData->_skins.add(defaultSkin); + } + + if (!this->getError().isEmpty()) { + delete skeletonData; + return NULL; + } + + /* Skins. */ + { + int i = (int) skeletonData->_skins.size(); + Array &skins = skeletonData->_skins.setSize(n = i + input.readInt(true), NULL); + for (; i < n; i++) { + Skin *skin = readSkin(input, *skeletonData, false, nonessential); + if (skin) + skins[i] = skin; + else { + delete skeletonData; + return NULL; + } + } + } + + /* Linked meshes. */ + Array &items = _linkedMeshes; + n = (int) items.size(); + for (int i = 0; i < n; i++) { + LinkedMesh *linkedMesh = items[i]; + Skin *skin = skeletonData->_skins[linkedMesh->_skinIndex]; + Attachment *source = skin->getAttachment(linkedMesh->_sourceIndex, linkedMesh->_source); + if (source == NULL) { + delete skeletonData; + setError("Source mesh not found: ", linkedMesh->_source.buffer()); + return NULL; + } + linkedMesh->_mesh->setTimelineAttachment(linkedMesh->_inheritTimelines ? source : linkedMesh->_mesh); + linkedMesh->_mesh->setSourceMesh(static_cast(source)); + linkedMesh->_mesh->updateSequence(); + } + ArrayUtils::deleteElements(_linkedMeshes); + _linkedMeshes.clear(); + + /* Events. */ + int eventsCount = input.readInt(true); + Array &events = skeletonData->_events.setSize(eventsCount, NULL); + for (int i = 0; i < eventsCount; ++i) { + EventData *eventData = new (__FILE__, __LINE__) EventData(String(input.readString(), true)); + Event &setup = eventData->_setupPose; + setup._intValue = input.readInt(false); + setup._floatValue = input.readFloat(); + setup._stringValue.own(input.readString()); + eventData->_audioPath.own(input.readString()); + if (!eventData->_audioPath.isEmpty()) { + setup._volume = input.readFloat(); + setup._balance = input.readFloat(); + } + events[i] = eventData; + } + + /* Animations. */ + int animationsCount = input.readInt(true); + Array &animations = skeletonData->_animations.setSize(animationsCount, NULL); + for (int i = 0; i < animationsCount; ++i) { + Animation *animation = readAnimation(input, String(input.readString(), true), *skeletonData, nonessential); + if (!animation) { + delete skeletonData; + setError("Error reading animation: ", input.readString()); + return NULL; + } + animations[i] = animation; + } + + for (int i = 0; i < constraintCount; i++) { + if (constraints[i]->getRTTI().instanceOf(SliderData::rtti)) { + SliderData *data = static_cast(constraints[i]); + data->setAnimation(*animations[input.readInt(true)]); + } + } + } + + return skeletonData; +} + +void SkeletonBinary::setError(const char *value1, const char *value2) { + char message[256]; + int length; + strcpy(message, value1); + length = (int) strlen(value1); + if (value2) strncat(message + length, value2, 255 - length); + _error = String(message); +} + +Skin *SkeletonBinary::readSkin(DataInput &input, SkeletonData &skeletonData, bool defaultSkin, bool nonessential) { + Skin *skin; + int slotCount = 0; + if (defaultSkin) { + slotCount = input.readInt(true); + if (slotCount == 0) return NULL; + skin = new (__FILE__, __LINE__) Skin("default"); + } else { + skin = new (__FILE__, __LINE__) Skin(String(input.readString(), true)); + + if (nonessential) Color::rgba8888ToColor(skin->getColor(), input.readInt()); + + int n; + Array &from = skeletonData._bones; + Array &bones = skin->getBones().setSize(n = input.readInt(true), NULL); + for (int i = 0; i < n; i++) bones[i] = from[input.readInt(true)]; + + Array &fromConstraints = skeletonData._constraints; + Array &constraints = skin->getConstraints().setSize(n = input.readInt(true), NULL); + for (int i = 0; i < n; i++) constraints[i] = fromConstraints[input.readInt(true)]; + + slotCount = input.readInt(true); + } + + for (int i = 0; i < slotCount; ++i) { + int slotIndex = input.readInt(true); + for (int ii = 0, nn = input.readInt(true); ii < nn; ++ii) { + String placeholder(input.readStringRef()); + Attachment *attachment = readAttachment(input, *skin, slotIndex, placeholder, skeletonData, nonessential); + if (attachment) + skin->setAttachment(slotIndex, placeholder, attachment); + else { + setError("Error reading attachment: ", placeholder.buffer()); + delete skin; + return NULL; + } + } + } + return skin; +} + +Attachment *SkeletonBinary::readAttachment(DataInput &input, Skin &skin, int slotIndex, const String &placeholder, SkeletonData &skeletonData, + bool nonessential) { + float scale = _scale; + + int flags = input.readByte(); + String name = (flags & 8) != 0 ? input.readStringRef() : placeholder; + AttachmentType type = static_cast(flags & 0x7); + switch (type) { + case AttachmentType_Region: { + String path = (flags & 16) != 0 ? input.readStringRef() : name; + int color = (flags & 32) != 0 ? input.readInt() : 0xffffffff; + Sequence *sequence = readSequence(input, (flags & 64) != 0); + float rotation = (flags & 128) != 0 ? input.readFloat() : 0; + float x = input.readFloat(); + float y = input.readFloat(); + float scaleX = input.readFloat(); + float scaleY = input.readFloat(); + float width = input.readFloat(); + float height = input.readFloat(); + + RegionAttachment *region = _attachmentLoader->newRegionAttachment(skin, placeholder, name, path, sequence); + if (!region) return NULL; + region->setPath(path); + region->setX(x * scale); + region->setY(y * scale); + region->setScaleX(scaleX); + region->setScaleY(scaleY); + region->setRotation(rotation); + region->setWidth(width * scale); + region->setHeight(height * scale); + Color::rgba8888ToColor(region->getColor(), color); + region->updateSequence(); + return region; + } + case AttachmentType_Boundingbox: { + Array vertices; + Array bones; + int verticesLength = readVertices(input, vertices, bones, (flags & 16) != 0); + int color = nonessential ? input.readInt() : 0; + + BoundingBoxAttachment *box = _attachmentLoader->newBoundingBoxAttachment(skin, placeholder, name); + if (!box) return NULL; + box->setWorldVerticesLength(verticesLength); + box->setVertices(vertices); + box->setBones(bones); + if (nonessential) Color::rgba8888ToColor(box->getColor(), color); + return box; + } + case AttachmentType_Mesh: { + String path = (flags & 16) != 0 ? input.readStringRef() : name; + int color = (flags & 32) != 0 ? input.readInt() : 0xffffffff; + Sequence *sequence = readSequence(input, (flags & 64) != 0); + int hullLength = input.readInt(true); + Array vertices; + Array bones; + int verticesLength = readVertices(input, vertices, bones, (flags & 128) != 0); + Array uvs; + readFloatArray(input, verticesLength, 1, uvs); + Array triangles; + readUnsignedShortArray(input, triangles, (verticesLength - hullLength - 2) * 3); + + Array timelineSlots; + timelineSlots.setSize(input.readInt(true), 0); + for (size_t i = 0; i < timelineSlots.size(); ++i) timelineSlots[i] = input.readInt(true); + + Array edges; + float width = 0, height = 0; + if (nonessential) { + readUnsignedShortArray(input, edges, input.readInt(true)); + width = input.readFloat(); + height = input.readFloat(); + } + + MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(skin, placeholder, name, path, sequence); + if (!mesh) return NULL; + mesh->setPath(path); + Color::rgba8888ToColor(mesh->getColor(), color); + mesh->setHullLength(hullLength << 1); + mesh->setBones(bones); + mesh->setVertices(vertices); + mesh->setWorldVerticesLength(verticesLength); + mesh->setRegionUVs(uvs); + mesh->setTriangles(triangles); + if (timelineSlots.size() > 0) mesh->setTimelineSlots(timelineSlots); + if (nonessential) { + mesh->setEdges(edges); + mesh->setWidth(width * scale); + mesh->setHeight(height * scale); + } + mesh->updateSequence(); + return mesh; + } + case AttachmentType_Linkedmesh: { + String path = (flags & 16) != 0 ? input.readStringRef() : name; + int color = (flags & 32) != 0 ? input.readInt() : 0xffffffff; + Sequence *sequence = readSequence(input, (flags & 64) != 0); + bool inheritTimelines = (flags & 128) != 0; + int sourceIndex = input.readInt(true); + int skinIndex = input.readInt(true); + String source = input.readStringRef(); + float width = 0, height = 0; + if (nonessential) { + width = input.readFloat(); + height = input.readFloat(); + } + + MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(skin, placeholder, name, path, sequence); + if (!mesh) return NULL; + mesh->setPath(path); + Color::rgba8888ToColor(mesh->getColor(), color); + if (nonessential) { + mesh->setWidth(width * scale); + mesh->setHeight(height * scale); + } + _linkedMeshes.add(new (__FILE__, __LINE__) LinkedMesh(*mesh, skinIndex, slotIndex, sourceIndex, source, inheritTimelines)); + return mesh; + } + case AttachmentType_Path: { + bool closed = (flags & 16) != 0; + bool constantSpeed = (flags & 32) != 0; + Array vertices; + Array bones; + int verticesLength = readVertices(input, vertices, bones, (flags & 64) != 0); + Array lengths; + readFloatArray(input, verticesLength / 6, scale, lengths); + int color = nonessential ? input.readInt() : 0; + + PathAttachment *path = _attachmentLoader->newPathAttachment(skin, placeholder, name); + if (!path) return NULL; + path->setClosed(closed); + path->setConstantSpeed(constantSpeed); + path->setWorldVerticesLength(verticesLength); + path->setVertices(vertices); + path->setBones(bones); + path->setLengths(lengths); + if (nonessential) Color::rgba8888ToColor(path->getColor(), color); + return path; + } + case AttachmentType_Point: { + float rotation = input.readFloat(); + float x = input.readFloat(); + float y = input.readFloat(); + int color = nonessential ? input.readInt() : 0; + + PointAttachment *point = _attachmentLoader->newPointAttachment(skin, placeholder, name); + if (!point) return NULL; + point->setX(x * scale); + point->setY(y * scale); + point->setRotation(rotation); + if (nonessential) Color::rgba8888ToColor(point->getColor(), color); + return point; + } + case AttachmentType_Clipping: { + int endSlotIndex = input.readInt(true); + Array vertices; + Array bones; + int verticesLength = readVertices(input, vertices, bones, (flags & 16) != 0); + int color = nonessential ? input.readInt() : 0; + + ClippingAttachment *clip = _attachmentLoader->newClippingAttachment(skin, placeholder, name); + if (!clip) return NULL; + clip->setEndSlot(skeletonData._slots[endSlotIndex]); + clip->setConvex((flags & 32) != 0); + clip->setInverse((flags & 64) != 0); + clip->setWorldVerticesLength(verticesLength); + clip->setVertices(vertices); + clip->setBones(bones); + if (nonessential) Color::rgba8888ToColor(clip->getColor(), color); + return clip; + } + } + return NULL; +} + +Sequence *SkeletonBinary::readSequence(DataInput &input, bool hasPathSuffix) { + if (!hasPathSuffix) return new (__FILE__, __LINE__) Sequence(1, false); + Sequence *sequence = new (__FILE__, __LINE__) Sequence(input.readInt(true), true); + sequence->setStart(input.readInt(true)); + sequence->setDigits(input.readInt(true)); + sequence->setSetupIndex(input.readInt(true)); + return sequence; +} + +int SkeletonBinary::readVertices(DataInput &input, Array &vertices, Array &bones, bool weighted) { + float scale = _scale; + int vertexCount = input.readInt(true); + int verticesLength = vertexCount << 1; + if (!weighted) { + readFloatArray(input, verticesLength, scale, vertices.setSize(verticesLength, 0)); + return verticesLength; + } + int n = input.readInt(true); + bones.setSize(n, 0); + vertices.setSize((n - vertexCount) * 3, 0); + for (int b = 0, w = 0; b < n;) { + int boneCount = input.readInt(true); + bones[b++] = boneCount; + for (int ii = 0; ii < boneCount; ++ii, w += 3) { + bones[b++] = input.readInt(true); + vertices[w] = input.readFloat() * scale; + vertices[w + 1] = input.readFloat() * scale; + vertices[w + 2] = input.readFloat(); + } + } + return verticesLength; +} + +void SkeletonBinary::readFloatArray(DataInput &input, int n, float scale, Array &array) { + array.setSize(n, 0); + int i; + if (scale == 1) { + for (i = 0; i < n; ++i) { + array[i] = input.readFloat(); + } + } else { + for (i = 0; i < n; ++i) { + array[i] = input.readFloat() * scale; + } + } +} + +void SkeletonBinary::readUnsignedShortArray(DataInput &input, Array &array, int n) { + array.setSize(n, 0); + for (int i = 0; i < n; ++i) { + array[i] = (unsigned short) input.readInt(true); + } +} + +Animation *SkeletonBinary::readAnimation(DataInput &input, const String &name, SkeletonData &skeletonData, bool nonessential) { + Array timelines; + Array bones; + timelines.ensureCapacity(input.readInt(true)); + float scale = _scale; + + // Slot timelines. + for (int i = 0, n = input.readInt(true); i < n; ++i) { + int slotIndex = input.readInt(true); + for (int ii = 0, nn = input.readInt(true); ii < nn; ++ii) { + int timelineType = input.readByte(), frameCount = input.readInt(true), frameLast = frameCount - 1; + switch (timelineType) { + case SLOT_ATTACHMENT: { + AttachmentTimeline *timeline = new (__FILE__, __LINE__) AttachmentTimeline(frameCount, slotIndex); + for (int frame = 0; frame < frameCount; ++frame) { + float time = input.readFloat(); + char *attachmentName = input.readStringRef(); + timeline->setFrame(frame, time, attachmentName); + } + timelines.add(timeline); + break; + } + case SLOT_RGBA: { + RGBATimeline *timeline = new (__FILE__, __LINE__) RGBATimeline(frameCount, input.readInt(true), slotIndex); + float time = input.readFloat(); + float r = input.read() / 255.0f, g = input.read() / 255.0f; + float b = input.read() / 255.0f, a = input.read() / 255.0f; + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b, a); + if (frame == frameLast) break; + float time2 = input.readFloat(); + float r2 = input.read() / 255.0f, g2 = input.read() / 255.0f; + float b2 = input.read() / 255.0f, a2 = input.read() / 255.0f; + int curveType = input.readByte(); + switch (curveType) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, *timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, *timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, *timeline, bezier++, frame, 2, time, time2, b, b2, 1); + setBezier(input, *timeline, bezier++, frame, 3, time, time2, a, a2, 1); + break; + } + time = time2; + r = r2; + g = g2; + b = b2; + a = a2; + } + timelines.add(timeline); + break; + } + case SLOT_RGB: { + RGBTimeline *timeline = new (__FILE__, __LINE__) RGBTimeline(frameCount, input.readInt(true), slotIndex); + float time = input.readFloat(); + float r = input.read() / 255.0f, g = input.read() / 255.0f, b = input.read() / 255.0f; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b); + if (frame == frameLast) break; + float time2 = input.readFloat(); + float r2 = input.read() / 255.0f, g2 = input.read() / 255.0f, b2 = input.read() / 255.0f; + int curveType = input.readByte(); + switch (curveType) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, *timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, *timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, *timeline, bezier++, frame, 2, time, time2, b, b2, 1); + break; + } + time = time2; + r = r2; + g = g2; + b = b2; + } + timelines.add(timeline); + break; + } + case SLOT_RGBA2: { + RGBA2Timeline *timeline = new (__FILE__, __LINE__) RGBA2Timeline(frameCount, input.readInt(true), slotIndex); + float time = input.readFloat(); + float r = input.read() / 255.0f, g = input.read() / 255.0f; + float b = input.read() / 255.0f, a = input.read() / 255.0f; + float r2 = input.read() / 255.0f, g2 = input.read() / 255.0f, b2 = input.read() / 255.0f; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b, a, r2, g2, b2); + if (frame == frameLast) break; + float time2 = input.readFloat(); + float nr = input.read() / 255.0f, ng = input.read() / 255.0f; + float nb = input.read() / 255.0f, na = input.read() / 255.0f; + float nr2 = input.read() / 255.0f, ng2 = input.read() / 255.0f, nb2 = input.read() / 255.0f; + int curveType = input.readByte(); + switch (curveType) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, *timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, *timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, *timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, *timeline, bezier++, frame, 3, time, time2, a, na, 1); + setBezier(input, *timeline, bezier++, frame, 4, time, time2, r2, nr2, 1); + setBezier(input, *timeline, bezier++, frame, 5, time, time2, g2, ng2, 1); + setBezier(input, *timeline, bezier++, frame, 6, time, time2, b2, nb2, 1); + break; + } + time = time2; + r = nr; + g = ng; + b = nb; + a = na; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.add(timeline); + break; + } + case SLOT_RGB2: { + RGB2Timeline *timeline = new (__FILE__, __LINE__) RGB2Timeline(frameCount, input.readInt(true), slotIndex); + float time = input.readFloat(); + float r = input.read() / 255.0f, g = input.read() / 255.0f, b = input.read() / 255.0f; + float r2 = input.read() / 255.0f, g2 = input.read() / 255.0f, b2 = input.read() / 255.0f; + + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, r, g, b, r2, g2, b2); + if (frame == frameLast) break; + float time2 = input.readFloat(); + float nr = input.read() / 255.0f, ng = input.read() / 255.0f, nb = input.read() / 255.0f; + float nr2 = input.read() / 255.0f, ng2 = input.read() / 255.0f, nb2 = input.read() / 255.0f; + int curveType = input.readByte(); + switch (curveType) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, *timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, *timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, *timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, *timeline, bezier++, frame, 3, time, time2, r2, nr2, 1); + setBezier(input, *timeline, bezier++, frame, 4, time, time2, g2, ng2, 1); + setBezier(input, *timeline, bezier++, frame, 5, time, time2, b2, nb2, 1); + break; + } + time = time2; + r = nr; + g = ng; + b = nb; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.add(timeline); + break; + } + case SLOT_ALPHA: { + AlphaTimeline *timeline = new (__FILE__, __LINE__) AlphaTimeline(frameCount, input.readInt(true), slotIndex); + float time = input.readFloat(), a = input.read() / 255.0f; + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, a); + if (frame == frameLast) break; + float time2 = input.readFloat(); + float a2 = input.read() / 255.0f; + int curveType = input.readByte(); + switch (curveType) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, *timeline, bezier++, frame, 0, time, time2, a, a2, 1); + break; + } + time = time2; + a = a2; + } + timelines.add(timeline); + break; + } + default: { + ArrayUtils::deleteElements(timelines); + setError("Invalid slot timeline type: ", String().append(timelineType).buffer()); + return NULL; + } + } + } + } + + // Bone timelines. + int boneCount = input.readInt(true); + bones.ensureCapacity(boneCount); + for (int i = 0; i < boneCount; ++i) { + int boneIndex = input.readInt(true); + bones.add(boneIndex); + for (int ii = 0, nn = input.readInt(true); ii < nn; ++ii) { + int timelineType = input.readByte(), frameCount = input.readInt(true); + if (timelineType == BONE_INHERIT) { + InheritTimeline *timeline = new (__FILE__, __LINE__) InheritTimeline(frameCount, boneIndex); + for (int frame = 0; frame < frameCount; frame++) { + float time = input.readFloat(); + Inherit inherit = (Inherit) input.readByte(); + timeline->setFrame(frame, time, inherit); + } + timelines.add(timeline); + continue; + } + int bezierCount = input.readInt(true); + switch (timelineType) { + case BONE_ROTATE: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) RotateTimeline(frameCount, bezierCount, boneIndex)), 1); + break; + case BONE_TRANSLATE: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) TranslateTimeline(frameCount, bezierCount, boneIndex)), scale); + break; + case BONE_TRANSLATEX: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) TranslateXTimeline(frameCount, bezierCount, boneIndex)), scale); + break; + case BONE_TRANSLATEY: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) TranslateYTimeline(frameCount, bezierCount, boneIndex)), scale); + break; + case BONE_SCALE: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) ScaleTimeline(frameCount, bezierCount, boneIndex)), 1); + break; + case BONE_SCALEX: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) ScaleXTimeline(frameCount, bezierCount, boneIndex)), 1); + break; + case BONE_SCALEY: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) ScaleYTimeline(frameCount, bezierCount, boneIndex)), 1); + break; + case BONE_SHEAR: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) ShearTimeline(frameCount, bezierCount, boneIndex)), 1); + break; + case BONE_SHEARX: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) ShearXTimeline(frameCount, bezierCount, boneIndex)), 1); + break; + case BONE_SHEARY: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) ShearYTimeline(frameCount, bezierCount, boneIndex)), 1); + break; + default: { + ArrayUtils::deleteElements(timelines); + setError("Invalid bone timeline type: ", String().append(timelineType).buffer()); + return NULL; + } + } + } + } + + // IK constraint timelines. + for (int i = 0, n = input.readInt(true); i < n; i++) { + int index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + IkConstraintTimeline *timeline = new (__FILE__, __LINE__) IkConstraintTimeline(frameCount, input.readInt(true), index); + int flags = input.read(); + float time = input.readFloat(), mix = (flags & 1) != 0 ? ((flags & 2) != 0 ? input.readFloat() : 1) : 0; + float softness = (flags & 4) != 0 ? input.readFloat() * scale : 0; + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mix, softness, (flags & 8) != 0 ? 1 : -1, (flags & 16) != 0, (flags & 32) != 0); + if (frame == frameLast) break; + flags = input.read(); + float time2 = input.readFloat(), mix2 = (flags & 1) != 0 ? ((flags & 2) != 0 ? input.readFloat() : 1) : 0; + float softness2 = (flags & 4) != 0 ? input.readFloat() * scale : 0; + if ((flags & 64) != 0) + timeline->setStepped(frame); + else if ((flags & 128) != 0) { + setBezier(input, *timeline, bezier++, frame, 0, time, time2, mix, mix2, 1); + setBezier(input, *timeline, bezier++, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + } + timelines.add(timeline); + } + + // Transform constraint timelines. + for (int i = 0, n = input.readInt(true); i < n; ++i) { + int index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + TransformConstraintTimeline *timeline = new (__FILE__, __LINE__) TransformConstraintTimeline(frameCount, input.readInt(true), index); + float time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(), + mixScaleX = input.readFloat(), mixScaleY = input.readFloat(), mixShearY = input.readFloat(); + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + if (frame == frameLast) break; + float time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(), + mixScaleX2 = input.readFloat(), mixScaleY2 = input.readFloat(), mixShearY2 = input.readFloat(); + int curveType = input.readByte(); + switch (curveType) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, *timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, *timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, *timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + setBezier(input, *timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + setBezier(input, *timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + setBezier(input, *timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1); + break; + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + } + timelines.add(timeline); + } + + // Path constraint timelines. + for (int i = 0, n = input.readInt(true); i < n; ++i) { + int index = input.readInt(true); + PathConstraintData *data = static_cast(skeletonData._constraints[index]); + for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { + int type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true); + switch (type) { + case PATH_POSITION: { + readTimeline(input, timelines, *(new (__FILE__, __LINE__) PathConstraintPositionTimeline(frameCount, bezierCount, index)), + data->_positionMode == PositionMode_Fixed ? scale : 1); + break; + } + case PATH_SPACING: { + readTimeline(input, timelines, *(new (__FILE__, __LINE__) PathConstraintSpacingTimeline(frameCount, bezierCount, index)), + data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed ? scale : 1); + break; + } + case PATH_MIX: { + PathConstraintMixTimeline *timeline = new (__FILE__, __LINE__) PathConstraintMixTimeline(frameCount, bezierCount, index); + float time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(); + for (int frame = 0, bezier = 0, frameLast = (int) timeline->getFrameCount() - 1;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY); + if (frame == frameLast) break; + float time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, *timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, *timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, *timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + break; + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + } + timelines.add(timeline); + break; + } + default: { + ArrayUtils::deleteElements(timelines); + setError("Invalid path constraint timeline type: ", String().append(type).buffer()); + return NULL; + } + } + } + } + + // Physics timelines. + for (int i = 0, n = input.readInt(true); i < n; i++) { + int index = input.readInt(true) - 1; + for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { + int type = input.readByte(), frameCount = input.readInt(true); + if (type == PHYSICS_RESET) { + PhysicsConstraintResetTimeline *timeline = new (__FILE__, __LINE__) PhysicsConstraintResetTimeline(frameCount, index); + for (int frame = 0; frame < frameCount; frame++) timeline->setFrame(frame, input.readFloat()); + timelines.add(timeline); + continue; + } + int bezierCount = input.readInt(true); + switch (type) { + case PHYSICS_INERTIA: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index)), 1); + break; + case PHYSICS_STRENGTH: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) PhysicsConstraintStrengthTimeline(frameCount, bezierCount, index)), 1); + break; + case PHYSICS_DAMPING: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) PhysicsConstraintDampingTimeline(frameCount, bezierCount, index)), 1); + break; + case PHYSICS_MASS: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) PhysicsConstraintMassTimeline(frameCount, bezierCount, index)), 1); + break; + case PHYSICS_WIND: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) PhysicsConstraintWindTimeline(frameCount, bezierCount, index)), 1); + break; + case PHYSICS_GRAVITY: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) PhysicsConstraintGravityTimeline(frameCount, bezierCount, index)), 1); + break; + case PHYSICS_MIX: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) PhysicsConstraintMixTimeline(frameCount, bezierCount, index)), 1); + break; + default: { + ArrayUtils::deleteElements(timelines); + setError("Invalid physics constraint timeline type: ", String().append(type).buffer()); + return NULL; + } + } + } + } + + // Slider timelines. + for (int i = 0, n = input.readInt(true); i < n; i++) { + int index = input.readInt(true); + for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { + int type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true); + switch (type) { + case SLIDER_TIME: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) SliderTimeline(frameCount, bezierCount, index)), 1); + break; + case SLIDER_MIX: + readTimeline(input, timelines, *(new (__FILE__, __LINE__) SliderMixTimeline(frameCount, bezierCount, index)), 1); + break; + default: { + ArrayUtils::deleteElements(timelines); + setError("Invalid slider timeline type: ", String().append(type).buffer()); + return NULL; + } + } + } + } + + // Attachment timelines. + for (int i = 0, n = input.readInt(true); i < n; ++i) { + Skin *skin = skeletonData._skins[input.readInt(true)]; + for (int ii = 0, nn = input.readInt(true); ii < nn; ++ii) { + int slotIndex = input.readInt(true); + for (int iii = 0, nnn = input.readInt(true); iii < nnn; iii++) { + const char *attachmentName = input.readStringRef(); + Attachment *attachment = skin->getAttachment(slotIndex, String(attachmentName)); + if (!attachment) { + ArrayUtils::deleteElements(timelines); + setError("Timeline attachment not found: ", attachmentName); + return NULL; + } + int timelineType = input.readByte(), frameCount = input.readInt(true), frameLast = frameCount - 1; + switch (timelineType) { + case ATTACHMENT_DEFORM: { + VertexAttachment *vertexAttachment = static_cast(attachment); + bool weighted = vertexAttachment->_bones.size() > 0; + Array &vertices = vertexAttachment->_vertices; + int deformLength = weighted ? (int) vertices.size() / 3 * 2 : (int) vertices.size(); + + DeformTimeline *timeline = new (__FILE__, __LINE__) + DeformTimeline(frameCount, input.readInt(true), slotIndex, *vertexAttachment); + + float time = input.readFloat(); + for (int frame = 0, bezier = 0;; ++frame) { + Array deform; + size_t end = (size_t) input.readInt(true); + if (end == 0) { + if (weighted) { + deform.setSize(deformLength, 0); + for (int iiii = 0; iiii < deformLength; ++iiii) deform[iiii] = 0; + } else { + deform.clearAndAddAll(vertices); + } + } else { + deform.setSize(deformLength, 0); + size_t start = (size_t) input.readInt(true); + end += start; + if (scale == 1) { + for (size_t v = start; v < end; ++v) deform[v] = input.readFloat(); + } else { + for (size_t v = start; v < end; ++v) deform[v] = input.readFloat() * scale; + } + if (!weighted) { + for (size_t v = 0, vn = deform.size(); v < vn; ++v) deform[v] += vertices[v]; + } + } + timeline->setFrame(frame, time, deform); + if (frame == frameLast) break; + float time2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, *timeline, bezier++, frame, 0, time, time2, 0, 1, 1); + break; + } + time = time2; + } + + timelines.add(timeline); + break; + } + case ATTACHMENT_SEQUENCE: { + SequenceTimeline *timeline = new (__FILE__, __LINE__) SequenceTimeline(frameCount, slotIndex, *attachment); + for (int frame = 0; frame < frameCount; frame++) { + float time = input.readFloat(); + int modeAndIndex = input.readInt(); + float delay = input.readFloat(); + timeline->setFrame(frame, time, (SequenceMode) (modeAndIndex & 0xf), modeAndIndex >> 4, delay); + } + timelines.add(timeline); + break; + } + default: { + ArrayUtils::deleteElements(timelines); + setError("Invalid attachment timeline type: ", String().append(timelineType).buffer()); + return NULL; + } + } + } + } + } + + // Draw order timeline. + size_t slotCount = skeletonData._slots.size(); + size_t drawOrderCount = (size_t) input.readInt(true); + if (drawOrderCount > 0) { + DrawOrderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderTimeline(drawOrderCount); + for (size_t i = 0; i < drawOrderCount; ++i) { + float time = input.readFloat(); + Array drawOrder; + readDrawOrder(input, slotCount, drawOrder); + timeline->setFrame(i, time, drawOrder.size() == 0 ? NULL : &drawOrder); + } + timelines.add(timeline); + } + + // Draw order folder timelines. + size_t folderCount = (size_t) input.readInt(true); + for (size_t i = 0; i < folderCount; ++i) { + size_t folderSlotCount = (size_t) input.readInt(true); + Array folderSlots; + folderSlots.setSize(folderSlotCount, 0); + for (size_t ii = 0; ii < folderSlotCount; ++ii) folderSlots[ii] = input.readInt(true); + size_t keyCount = (size_t) input.readInt(true); + DrawOrderFolderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderFolderTimeline(keyCount, folderSlots, slotCount); + for (size_t ii = 0; ii < keyCount; ++ii) { + float time = input.readFloat(); + Array drawOrder; + readDrawOrder(input, folderSlotCount, drawOrder); + timeline->setFrame(ii, time, drawOrder.size() == 0 ? NULL : &drawOrder); + } + timelines.add(timeline); + } + + // Event timeline. + int eventCount = input.readInt(true); + if (eventCount > 0) { + EventTimeline *timeline = new (__FILE__, __LINE__) EventTimeline(eventCount); + for (int i = 0; i < eventCount; ++i) { + float time = input.readFloat(); + EventData *eventData = skeletonData._events[input.readInt(true)]; + Event *event = new (__FILE__, __LINE__) Event(time, *eventData); + event->_intValue = input.readInt(false); + event->_floatValue = input.readFloat(); + const char *stringValue = input.readString(); + if (stringValue == NULL) + event->_stringValue = eventData->_setupPose._stringValue; + else + event->_stringValue.own(stringValue); + + if (!eventData->_audioPath.isEmpty()) { + event->_volume = input.readFloat(); + event->_balance = input.readFloat(); + } + timeline->setFrame(i, *event); + } + timelines.add(timeline); + } + + float duration = 0; + for (int i = 0, n = (int) timelines.size(); i < n; i++) { + duration = MathUtil::max(duration, (timelines[i])->getDuration()); + } + Animation *animation = new (__FILE__, __LINE__) Animation(String(name)); + animation->setTimelines(timelines, bones); + animation->setDuration(duration); + if (nonessential) Color::rgba8888ToColor(animation->getColor(), input.readInt()); + return animation; +} + +void SkeletonBinary::readTimeline(DataInput &input, Array &timelines, CurveTimeline1 &timeline, float scale) { + float time = input.readFloat(), value = input.readFloat() * scale; + for (int frame = 0, bezier = 0, frameLast = (int) timeline.getFrameCount() - 1;; frame++) { + timeline.setFrame(frame, time, value); + if (frame == frameLast) break; + float time2 = input.readFloat(), value2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale); + break; + } + time = time2; + value = value2; + } + timelines.add(&timeline); +} + +void SkeletonBinary::readTimeline(DataInput &input, Array &timelines, BoneTimeline2 &timeline, float scale) { + float time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale; + for (int frame = 0, bezier = 0, frameLast = (int) timeline.getFrameCount() - 1;; frame++) { + timeline.setFrame(frame, time, value1, value2); + if (frame == frameLast) break; + float time2 = input.readFloat(), nvalue1 = input.readFloat() * scale, nvalue2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale); + setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale); + break; + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + } + timelines.add(&timeline); +} + +void SkeletonBinary::readDrawOrder(DataInput &input, size_t slotCount, Array &drawOrder) { + size_t changeCount = (size_t) input.readInt(true); + drawOrder.clear(); + if (changeCount == 0) return; + + drawOrder.setSize(slotCount, 0); + for (int i = (int) slotCount - 1; i >= 0; --i) drawOrder[i] = -1; + Array unchanged; + unchanged.setSize(slotCount - changeCount, 0); + size_t originalIndex = 0, unchangedIndex = 0; + for (size_t i = 0; i < changeCount; ++i) { + size_t slotIndex = (size_t) input.readInt(true); + while (originalIndex != slotIndex) unchanged[unchangedIndex++] = (int) originalIndex++; + size_t index = originalIndex; + drawOrder[index + (size_t) input.readInt(true)] = (int) originalIndex++; + } + while (originalIndex < slotCount) unchanged[unchangedIndex++] = (int) originalIndex++; + for (int i = (int) slotCount - 1; i >= 0; --i) + if (drawOrder[i] == -1) drawOrder[i] = unchanged[--unchangedIndex]; +} + +void SkeletonBinary::setBezier(DataInput &input, CurveTimeline &timeline, int bezier, int frame, int value, float time1, float time2, float value1, + float value2, float scale) { + float cx1 = input.readFloat(); + float cy1 = input.readFloat(); + float cx2 = input.readFloat(); + float cy2 = input.readFloat(); + timeline.setBezier(bezier, frame, value, time1, value1, cx1, cy1 * scale, cx2, cy2 * scale, time2, value2); +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonBounds.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonBounds.cpp new file mode 100644 index 0000000..faece49 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonBounds.cpp @@ -0,0 +1,245 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include + +using namespace spine; + +SkeletonBounds::SkeletonBounds() : _minX(0), _minY(0), _maxX(0), _maxY(0) { +} + +SkeletonBounds::~SkeletonBounds() { + for (size_t i = 0, n = _polygons.size(); i < n; i++) _polygonPool.free(_polygons[i]); + _polygons.clear(); +} + +void SkeletonBounds::update(Skeleton &skeleton, bool updateAabb) { + Array &slots = skeleton.getSlots(); + size_t slotCount = slots.size(); + + _boundingBoxes.clear(); + for (size_t i = 0, n = _polygons.size(); i < n; ++i) { + _polygonPool.free(_polygons[i]); + } + + _polygons.clear(); + + for (size_t i = 0; i < slotCount; i++) { + Slot *slot = slots[i]; + if (!slot->getBone().isActive()) continue; + + Attachment *attachment = slot->_appliedPose->getAttachment(); + if (attachment == NULL || !attachment->getRTTI().instanceOf(BoundingBoxAttachment::rtti)) continue; + BoundingBoxAttachment *boundingBox = static_cast(attachment); + _boundingBoxes.add(boundingBox); + + Polygon *polygonP = _polygonPool.obtain(); + _polygons.add(polygonP); + + Polygon &polygon = *polygonP; + + size_t count = boundingBox->getWorldVerticesLength(); + polygon._count = (int) count; + if (polygon._vertices.size() < count) { + polygon._vertices.setSize(count, 0); + } + boundingBox->computeWorldVertices(skeleton, *slot, 0, count, polygon._vertices, 0, 2); + } + + if (updateAabb) + aabbCompute(); + else { + _minX = FLT_MIN; + _minY = FLT_MIN; + _maxX = FLT_MAX; + _maxY = FLT_MAX; + } +} + +bool SkeletonBounds::aabbContainsPoint(float x, float y) { + return x >= _minX && x <= _maxX && y >= _minY && y <= _maxY; +} + +bool SkeletonBounds::aabbIntersectsSegment(float x1, float y1, float x2, float y2) { + float minX = _minX; + float minY = _minY; + float maxX = _maxX; + float maxY = _maxY; + + if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) { + return false; + } + + float m = (y2 - y1) / (x2 - x1); + float y = m * (minX - x1) + y1; + if (y > minY && y < maxY) return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) return true; + float x = (minY - y1) / m + x1; + if (x > minX && x < maxX) return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) return true; + return false; +} + +bool SkeletonBounds::aabbIntersectsSkeleton(SkeletonBounds &bounds) { + return _minX < bounds._maxX && _maxX > bounds._minX && _minY < bounds._maxY && _maxY > bounds._minY; +} + +bool SkeletonBounds::containsPoint(Polygon &polygon, float x, float y) { + Array &vertices = polygon._vertices; + int nn = polygon._count; + + int prevIndex = nn - 2; + bool inside = false; + for (int ii = 0; ii < nn; ii += 2) { + float vertexY = vertices[ii + 1]; + float prevY = vertices[prevIndex + 1]; + if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { + float vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) { + inside = !inside; + } + } + prevIndex = ii; + } + return inside; +} + +BoundingBoxAttachment *SkeletonBounds::containsPoint(float x, float y) { + for (size_t i = 0, n = _polygons.size(); i < n; ++i) + if (containsPoint(*_polygons[i], x, y)) return _boundingBoxes[i]; + return NULL; +} + +BoundingBoxAttachment *SkeletonBounds::intersectsSegment(float x1, float y1, float x2, float y2) { + for (size_t i = 0, n = _polygons.size(); i < n; ++i) + if (intersectsSegment(*_polygons[i], x1, y1, x2, y2)) return _boundingBoxes[i]; + return NULL; +} + +bool SkeletonBounds::intersectsSegment(Polygon &polygon, float x1, float y1, float x2, float y2) { + Array &vertices = polygon._vertices; + size_t nn = polygon._count; + + float width12 = x1 - x2, height12 = y1 - y2; + float det1 = x1 * y2 - y1 * x2; + float x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (size_t ii = 0; ii < nn; ii += 2) { + float x4 = vertices[ii], y4 = vertices[ii + 1]; + float det2 = x3 * y4 - y3 * x4; + float width34 = x3 - x4, height34 = y3 - y4; + float det3 = width12 * height34 - height12 * width34; + float x = (det1 * width34 - width12 * det2) / det3; + if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { + float y = (det1 * height34 - height12 * det2) / det3; + if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) { + return true; + } + } + x3 = x4; + y3 = y4; + } + + return false; +} + +spine::Polygon *SkeletonBounds::getPolygon(BoundingBoxAttachment *attachment) { + int index = _boundingBoxes.indexOf(attachment); + return index == -1 ? NULL : _polygons[index]; +} + +BoundingBoxAttachment *SkeletonBounds::getBoundingBox(spine::Polygon *polygon) { + int index = _polygons.indexOf(polygon); + return index == -1 ? NULL : _boundingBoxes[index]; +} + +Array &SkeletonBounds::getPolygons() { + return _polygons; +} + +Array &SkeletonBounds::getBoundingBoxes() { + return _boundingBoxes; +} + +float SkeletonBounds::getMinX() { + return _minX; +} + +float SkeletonBounds::getMinY() { + return _minY; +} + +float SkeletonBounds::getMaxX() { + return _maxX; +} + +float SkeletonBounds::getMaxY() { + return _maxY; +} + +float SkeletonBounds::getWidth() { + return _maxX - _minX; +} + +float SkeletonBounds::getHeight() { + return _maxY - _minY; +} + +void SkeletonBounds::aabbCompute() { + float minX = FLT_MAX; + float minY = FLT_MAX; + float maxX = FLT_MIN; + float maxY = FLT_MIN; + + for (size_t i = 0, n = _polygons.size(); i < n; ++i) { + Polygon *polygon = _polygons[i]; + Array &vertices = polygon->_vertices; + for (int ii = 0, nn = polygon->_count; ii < nn; ii += 2) { + float x = vertices[ii]; + float y = vertices[ii + 1]; + minX = MathUtil::min(minX, x); + minY = MathUtil::min(minY, y); + maxX = MathUtil::max(maxX, x); + maxY = MathUtil::max(maxY, y); + } + } + _minX = minX; + _minY = minY; + _maxX = maxX; + _maxY = maxY; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonClipping.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonClipping.cpp new file mode 100644 index 0000000..e9b6893 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonClipping.cpp @@ -0,0 +1,600 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include + +using namespace spine; + +SkeletonClipping::SkeletonClipping() : _clipAttachment(NULL), _inverse(false) { + _clippingPolygons.ensureCapacity(1); +} + +size_t SkeletonClipping::clipStart(Skeleton &skeleton, Slot &slot, ClippingAttachment *clip) { + if (_clipAttachment != NULL) return 0; + + int n = (int) clip->getWorldVerticesLength(); + if (n < 6) return 0; + _clipAttachment = clip; + _inverse = clip->getInverse(); + _clippingPolygons.clear(); + + clip->computeWorldVertices(skeleton, slot, 0, n, _clippingPolygon.setSize(n, 0).buffer(), 0, 2); + bool convex = makeClockwise(_clippingPolygon); + if (convex || _inverse || clip->getConvex()) { + if (!convex) makeConvex(_clippingPolygon); + _clippingPolygon.add(_clippingPolygon[0]); + _clippingPolygon.add(_clippingPolygon[1]); + _clippingPolygons.add(&_clippingPolygon); + } else { + Array *> &polygons = _triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon)); + for (size_t i = 0, n2 = polygons.size(); i < n2; ++i) _clippingPolygons.add(polygons[i]); + } + + return _clippingPolygons.size(); +} + +void SkeletonClipping::clipEnd(Slot &slot) { + if (_clipAttachment != NULL && _clipAttachment->_endSlot == &slot._data) { + clipEnd(); + } +} + +void SkeletonClipping::clipEnd() { + if (_clipAttachment == NULL) return; + _clipAttachment = NULL; + _clippingPolygons.clear(); +} + +bool SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength) { + Array &clippedVertices = _clippedVertices; + clippedVertices.clear(); + Array &clippedTriangles = _clippedTriangles; + clippedTriangles.clear(); + unsigned short index = 0; + + if (_inverse) { + Array *polygon = _clippingPolygons[0]; + for (size_t i = 0; i < trianglesLength; i += 3) { + int t = triangles[i] << 1; + float x1 = vertices[t], y1 = vertices[t + 1]; + t = triangles[i + 1] << 1; + float x2 = vertices[t], y2 = vertices[t + 1]; + t = triangles[i + 2] << 1; + float x3 = vertices[t], y3 = vertices[t + 1]; + clipInverse(x1, y1, x2, y2, x3, y3, polygon); + + float *iv = _inverseVertices.buffer(); + for (size_t offset = 0, nn = _inverseVertices.size(); offset < nn;) { + int polygonSize = (int) iv[offset++]; + int vertexCount = polygonSize >> 1; + size_t s = clippedVertices.size(); + + float *cv = clippedVertices.setSize(s + polygonSize, 0).buffer(); + memcpy(cv + s, iv + offset, sizeof(float) * polygonSize); + + s = clippedTriangles.size(); + unsigned short *ct = clippedTriangles.setSize(s + 3 * (vertexCount - 2), 0).buffer(); + for (int ii = 1; ii < vertexCount - 1; ii++, s += 3) { + ct[s] = index; + ct[s + 1] = (unsigned short) (index + ii); + ct[s + 2] = (unsigned short) (index + ii + 1); + } + index += (unsigned short) vertexCount; + offset += polygonSize; + } + } + return true; + } + + Array &clipOutput = _clipOutput; + Array **polygons = _clippingPolygons.buffer(); + int polygonsCount = (int) _clippingPolygons.size(); + bool clipped = false; + for (size_t i = 0; i < trianglesLength; i += 3) { + int t = triangles[i] << 1; + float x1 = vertices[t], y1 = vertices[t + 1]; + t = triangles[i + 1] << 1; + float x2 = vertices[t], y2 = vertices[t + 1]; + t = triangles[i + 2] << 1; + float x3 = vertices[t], y3 = vertices[t + 1]; + for (int p = 0; p < polygonsCount; p++) { + size_t s = clippedVertices.size(); + if (clip(x1, y1, x2, y2, x3, y3, polygons[p])) { + int clipOutputLength = (int) clipOutput.size(); + if (clipOutputLength == 0) continue; + clipped = true; + int clipOutputCount = clipOutputLength >> 1; + + float *cv = clippedVertices.setSize(s + clipOutputLength, 0).buffer(); + memcpy(cv + s, clipOutput.buffer(), sizeof(float) * clipOutputLength); + + s = clippedTriangles.size(); + unsigned short *ct = clippedTriangles.setSize(s + 3 * (clipOutputCount - 2), 0).buffer(); + for (int ii = 1, nn = clipOutputCount - 1; ii < nn; ii++, s += 3) { + ct[s] = index; + ct[s + 1] = (unsigned short) (index + ii); + ct[s + 2] = (unsigned short) (index + ii + 1); + } + index += (unsigned short) clipOutputCount; + } else { + float *cv = clippedVertices.setSize(s + 6, 0).buffer(); + cv[s] = x1; + cv[s + 1] = y1; + cv[s + 2] = x2; + cv[s + 3] = y2; + cv[s + 4] = x3; + cv[s + 5] = y3; + + s = clippedTriangles.size(); + unsigned short *ct = clippedTriangles.setSize(s + 3, 0).buffer(); + ct[s] = index; + ct[s + 1] = (unsigned short) (index + 1); + ct[s + 2] = (unsigned short) (index + 2); + index += 3; + break; + } + } + } + return clipped; +} + +bool SkeletonClipping::clipTriangles(Array &vertices, Array &triangles, Array &uvs, size_t stride) { + return clipTriangles(vertices.buffer(), triangles.buffer(), triangles.size(), uvs.buffer(), stride); +} + +bool SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength, float *uvs, size_t stride) { + Array &clippedVertices = _clippedVertices; + clippedVertices.clear(); + Array &clippedTriangles = _clippedTriangles; + clippedTriangles.clear(); + _clippedUVs.clear(); + unsigned short index = 0; + + if (_inverse) { + Array *polygon = _clippingPolygons[0]; + for (size_t i = 0; i < trianglesLength; i += 3) { + int t0 = triangles[i], t1 = triangles[i + 1], t2 = triangles[i + 2]; + float x1 = vertices[t0 * stride], y1 = vertices[t0 * stride + 1]; + float x2 = vertices[t1 * stride], y2 = vertices[t1 * stride + 1]; + float x3 = vertices[t2 * stride], y3 = vertices[t2 * stride + 1]; + clipInverse(x1, y1, x2, y2, x3, y3, polygon); + size_t nn = _inverseVertices.size(); + if (nn == 0) continue; + + float u1 = uvs[t0 << 1], v1 = uvs[(t0 << 1) + 1]; + float u2 = uvs[t1 << 1], v2 = uvs[(t1 << 1) + 1]; + float u3 = uvs[t2 << 1], v3 = uvs[(t2 << 1) + 1]; + float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1, d = 1 / (d0 * d2 + d1 * (y1 - y3)); + float *iv = _inverseVertices.buffer(); + for (size_t offset = 0; offset < nn;) { + int polygonSize = (int) iv[offset++]; + int vertexCount = polygonSize >> 1; + + size_t s = clippedVertices.size(); + float *cv = clippedVertices.setSize(s + polygonSize, 0).buffer(); + float *cu = _clippedUVs.setSize(s + polygonSize, 0).buffer(); + for (int ii = 0; ii < polygonSize; ii += 2, s += 2) { + float x = iv[offset + ii], y = iv[offset + ii + 1]; + cv[s] = x; + cv[s + 1] = y; + float c0 = x - x3, c1 = y - y3, a = (d0 * c0 + d1 * c1) * d, b = (d4 * c0 + d2 * c1) * d, c = 1 - a - b; + cu[s] = u1 * a + u2 * b + u3 * c; + cu[s + 1] = v1 * a + v2 * b + v3 * c; + } + + s = clippedTriangles.size(); + unsigned short *ct = clippedTriangles.setSize(s + 3 * (vertexCount - 2), 0).buffer(); + for (int ii = 1; ii < vertexCount - 1; ii++, s += 3) { + ct[s] = index; + ct[s + 1] = (unsigned short) (index + ii); + ct[s + 2] = (unsigned short) (index + ii + 1); + } + index += (unsigned short) vertexCount; + offset += polygonSize; + } + } + return true; + } + + Array &clipOutput = _clipOutput; + Array **polygons = _clippingPolygons.buffer(); + int polygonsCount = (int) _clippingPolygons.size(); + bool clipped = false; + for (size_t i = 0; i < trianglesLength; i += 3) { + int t = triangles[i]; + float x1 = vertices[t * stride], y1 = vertices[t * stride + 1]; + float u1 = uvs[t << 1], v1 = uvs[(t << 1) + 1]; + t = triangles[i + 1]; + float x2 = vertices[t * stride], y2 = vertices[t * stride + 1]; + float u2 = uvs[t << 1], v2 = uvs[(t << 1) + 1]; + t = triangles[i + 2]; + float x3 = vertices[t * stride], y3 = vertices[t * stride + 1]; + float u3 = uvs[t << 1], v3 = uvs[(t << 1) + 1]; + float d0 = 0, d1 = 0, d2 = 0, d4 = 0, d = 0; + for (int p = 0; p < polygonsCount; p++) { + size_t s = clippedVertices.size(); + if (clip(x1, y1, x2, y2, x3, y3, polygons[p])) { + int clipOutputLength = (int) clipOutput.size(); + if (clipOutputLength == 0) continue; + clipped = true; + int clipOutputCount = clipOutputLength >> 1; + if (d == 0) { + d0 = y2 - y3; + d1 = x3 - x2; + d2 = x1 - x3; + d4 = y3 - y1; + d = 1 / (d0 * d2 - d1 * d4); + } + + float *cv = clippedVertices.setSize(s + clipOutputCount * 2, 0).buffer(); + float *cu = _clippedUVs.setSize(s + clipOutputCount * 2, 0).buffer(); + for (int ii = 0; ii < clipOutputLength; ii += 2, s += 2) { + float x = clipOutput[ii], y = clipOutput[ii + 1]; + cv[s] = x; + cv[s + 1] = y; + float c0 = x - x3, c1 = y - y3, a = (d0 * c0 + d1 * c1) * d, b = (d4 * c0 + d2 * c1) * d, c = 1 - a - b; + cu[s] = u1 * a + u2 * b + u3 * c; + cu[s + 1] = v1 * a + v2 * b + v3 * c; + } + + s = clippedTriangles.size(); + unsigned short *ct = clippedTriangles.setSize(s + 3 * (clipOutputCount - 2), 0).buffer(); + clipOutputCount--; + for (int ii = 1; ii < clipOutputCount; ii++, s += 3) { + ct[s] = index; + ct[s + 1] = (unsigned short) (index + ii); + ct[s + 2] = (unsigned short) (index + ii + 1); + } + index += (unsigned short) (clipOutputCount + 1); + } else { + float *cv = clippedVertices.setSize(s + 6, 0).buffer(); + cv[s] = x1; + cv[s + 1] = y1; + cv[s + 2] = x2; + cv[s + 3] = y2; + cv[s + 4] = x3; + cv[s + 5] = y3; + + float *cu = _clippedUVs.setSize(s + 6, 0).buffer(); + cu[s] = u1; + cu[s + 1] = v1; + cu[s + 2] = u2; + cu[s + 3] = v2; + cu[s + 4] = u3; + cu[s + 5] = v3; + + s = clippedTriangles.size(); + unsigned short *ct = clippedTriangles.setSize(s + 3, 0).buffer(); + ct[s] = index; + ct[s + 1] = (unsigned short) (index + 1); + ct[s + 2] = (unsigned short) (index + 2); + index += 3; + break; + } + } + } + return clipped; +} + +bool SkeletonClipping::isClipping() { + return _clipAttachment != NULL; +} + +Array &SkeletonClipping::getClippedVertices() { + return _clippedVertices; +} + +Array &SkeletonClipping::getClippedTriangles() { + return _clippedTriangles; +} + +Array &SkeletonClipping::getClippedUVs() { + return _clippedUVs; +} + +bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Array *polygon) { + Array &originalOutput = _clipOutput; + bool clipped = false; + + Array *input; + Array *output; + if (polygon->size() % 4 >= 2) { + input = &_clipOutput; + output = &_scratch; + } else { + input = &_scratch; + output = &_clipOutput; + } + + float *v = polygon->buffer(); + float *iv = input->setSize(8, 0).buffer(); + iv[0] = x1; + iv[1] = y1; + iv[2] = x2; + iv[3] = y2; + iv[4] = x3; + iv[5] = y3; + iv[6] = x1; + iv[7] = y1; + output->clear(); + + int last = (int) polygon->size() - 4; + for (int i = 0;; i += 2) { + float edgeX = v[i], edgeY = v[i + 1], ex = edgeX - v[i + 2], ey = edgeY - v[i + 3]; + size_t outputStart = output->size(); + iv = input->buffer(); + x1 = iv[0]; + y1 = iv[1]; + float s1 = ey * (edgeX - x1) - ex * (edgeY - y1); + for (size_t ii = 2, nn = input->size() - 2; ii <= nn; ii += 2) { + x2 = iv[ii]; + y2 = iv[ii + 1]; + float s2 = ey * (edgeX - x2) - ex * (edgeY - y2); + if (s1 > 0) { + if (s2 > 0) { + output->add(x2); + output->add(y2); + } else { + float ix = x2 - x1, iy = y2 - y1, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + output->add(x1 + ix * t); + output->add(y1 + iy * t); + clipped = true; + } else { + output->add(x2); + output->add(y2); + } + } + } else if (s2 > 0) { + float ix = x2 - x1, iy = y2 - y1, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + output->add(x1 + ix * t); + output->add(y1 + iy * t); + output->add(x2); + output->add(y2); + clipped = true; + } else { + output->add(x2); + output->add(y2); + } + } else { + clipped = true; + } + x1 = x2; + y1 = y2; + s1 = s2; + } + if (outputStart == output->size()) { + originalOutput.clear(); + return true; + } + + output->add((*output)[0]); + output->add((*output)[1]); + + if (i == last) break; + Array *temp = output; + output = input; + output->clear(); + input = temp; + } + + if (&originalOutput != output) { + originalOutput.clear(); + for (size_t i = 0, n = output->size() - 2; i < n; ++i) originalOutput.add((*output)[i]); + } else { + originalOutput.setSize(originalOutput.size() - 2, 0); + } + + return clipped; +} + +void SkeletonClipping::clipInverse(float x1, float y1, float x2, float y2, float x3, float y3, Array *polygon) { + _inverseVertices.clear(); + _inverseVertices.ensureCapacity(polygon->size() * 3); + int last = (int) polygon->size() - 4; + + Array *input; + Array *output; + if (polygon->size() % 4 >= 2) { + input = &_clipOutput; + output = &_scratch; + } else { + input = &_scratch; + output = &_clipOutput; + } + + float *v = polygon->buffer(); + float *iv = input->setSize(8, 0).buffer(); + iv[0] = x1; + iv[1] = y1; + iv[2] = x2; + iv[3] = y2; + iv[4] = x3; + iv[5] = y3; + iv[6] = x1; + iv[7] = y1; + output->clear(); + + for (int i = 0;; i += 2) { + float edgeX = v[i], edgeY = v[i + 1], ex = edgeX - v[i + 2], ey = edgeY - v[i + 3]; + size_t outputStart = output->size(), fragmentStart = _inverseVertices.size(); + _inverseVertices.add(0); + iv = input->buffer(); + x1 = iv[0]; + y1 = iv[1]; + float s1 = ey * (edgeX - x1) - ex * (edgeY - y1); + for (size_t ii = 2, nn = input->size() - 2; ii <= nn; ii += 2) { + x2 = iv[ii]; + y2 = iv[ii + 1]; + float s2 = ey * (edgeX - x2) - ex * (edgeY - y2); + if (s1 > 0) { + if (s2 > 0) { + output->add(x2); + output->add(y2); + } else { + float ix = x2 - x1, iy = y2 - y1, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + float cx = x1 + ix * t, cy = y1 + iy * t; + output->add(cx); + output->add(cy); + _inverseVertices.add(cx); + _inverseVertices.add(cy); + _inverseVertices.add(x2); + _inverseVertices.add(y2); + } else { + output->add(x2); + output->add(y2); + } + } + } else if (s2 > 0) { + float ix = x2 - x1, iy = y2 - y1, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + float cx = x1 + ix * t, cy = y1 + iy * t; + _inverseVertices.add(cx); + _inverseVertices.add(cy); + output->add(cx); + output->add(cy); + output->add(x2); + output->add(y2); + } else { + output->add(x2); + output->add(y2); + } + } else { + _inverseVertices.add(x2); + _inverseVertices.add(y2); + } + x1 = x2; + y1 = y2; + s1 = s2; + } + + int fragmentSize = (int) _inverseVertices.size() - (int) fragmentStart - 1; + if (fragmentSize >= 6) + _inverseVertices[fragmentStart] = (float) fragmentSize; + else + _inverseVertices.setSize(fragmentStart, 0); + + if (outputStart == output->size()) break; + + output->add((*output)[0]); + output->add((*output)[1]); + + if (i == last) break; + Array *temp = output; + output = input; + output->clear(); + input = temp; + } +} + +bool SkeletonClipping::makeClockwise(Array &polygon) { + float *v = polygon.buffer(); + int n = (int) polygon.size(); + bool noCW = true, noCCW = true; + float area = 0, prevX = v[n - 2], prevY = v[n - 1], currX = v[0], currY = v[1]; + for (int i = 2; i < n; i += 2) { + float nextX = v[i], nextY = v[i + 1]; + area += currX * nextY - nextX * currY; + float cross = (currX - prevX) * (nextY - currY) - (currY - prevY) * (nextX - currX); + noCCW &= cross <= 0; + noCW &= cross >= 0; + prevX = currX; + prevY = currY; + currX = nextX; + currY = nextY; + } + area += currX * v[1] - v[0] * currY; + float cross = (currX - prevX) * (v[1] - currY) - (currY - prevY) * (v[0] - currX); + noCCW &= cross <= 0; + noCW &= cross >= 0; + if (area >= 0) { + for (int i = 0, lastX = n - 2, half = n >> 1; i < half; i += 2) { + float x = v[i], y = v[i + 1]; + int other = lastX - i; + v[i] = v[other]; + v[i + 1] = v[other + 1]; + v[other] = x; + v[other + 1] = y; + } + return noCW; + } + return noCCW; +} + +void SkeletonClipping::makeConvex(Array &polygon) { + int n = (int) polygon.size(); + float *v = polygon.buffer(); + float *sorted = _clipOutput.setSize(n, 0).buffer(); + for (int i = 0; i < n; i++) sorted[i] = v[i]; + for (int i = 2; i < n; i += 2) { + float x = sorted[i], y = sorted[i + 1]; + int p = i - 2; + for (; p >= 0 && (sorted[p] > x || (sorted[p] == x && sorted[p + 1] > y)); p -= 2) { + sorted[p + 2] = sorted[p]; + sorted[p + 3] = sorted[p + 1]; + } + sorted[p + 2] = x; + sorted[p + 3] = y; + } + v[0] = sorted[0]; + v[1] = sorted[1]; + v[2] = sorted[2]; + v[3] = sorted[3]; + int s = 4; + for (int i = 4; i < n; i += 2, s += 2) { + float x = sorted[i], y = sorted[i + 1]; + while ((v[s - 2] - v[s - 4]) * (y - v[s - 3]) - (v[s - 1] - v[s - 3]) * (x - v[s - 4]) >= 0) { + s -= 2; + if (s == 2) break; + } + v[s] = x; + v[s + 1] = y; + } + v[s] = sorted[n - 4]; + v[s + 1] = sorted[n - 3]; + int t = s; + s += 2; + for (int i = n - 6; i >= 0; i -= 2, s += 2) { + float x = sorted[i], y = sorted[i + 1]; + while ((v[s - 2] - v[s - 4]) * (y - v[s - 3]) - (v[s - 1] - v[s - 3]) * (x - v[s - 4]) >= 0) { + s -= 2; + if (s == t) break; + } + v[s] = x; + v[s + 1] = y; + } + polygon.setSize(s - 2, 0); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonData.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonData.cpp new file mode 100644 index 0000000..1c42b90 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonData.cpp @@ -0,0 +1,218 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +SkeletonData::SkeletonData() + : _name(), _defaultSkin(NULL), _x(0), _y(0), _width(0), _height(0), _referenceScale(100), _version(), _hash(), _fps(30), _imagesPath(), + _audioPath() { +} + +SkeletonData::~SkeletonData() { + ArrayUtils::deleteElements(_bones); + ArrayUtils::deleteElements(_slots); + ArrayUtils::deleteElements(_skins); + + _defaultSkin = NULL; + + ArrayUtils::deleteElements(_events); + ArrayUtils::deleteElements(_animations); + ArrayUtils::deleteElements(_constraints); + for (size_t i = 0; i < _strings.size(); i++) { + SpineExtension::free(_strings[i], __FILE__, __LINE__); + } +} + +BoneData *SkeletonData::findBone(const String &boneName) { + return ArrayUtils::findWithName(_bones, boneName); +} + +SlotData *SkeletonData::findSlot(const String &slotName) { + return ArrayUtils::findWithName(_slots, slotName); +} + +Skin *SkeletonData::findSkin(const String &skinName) { + return ArrayUtils::findWithName(_skins, skinName); +} + +EventData *SkeletonData::findEvent(const String &eventDataName) { + return ArrayUtils::findWithName(_events, eventDataName); +} + +Animation *SkeletonData::findAnimation(const String &animationName) { + return ArrayUtils::findWithName(_animations, animationName); +} + +Array &SkeletonData::findSliderAnimations(Array &animations) { + for (size_t i = 0, n = _constraints.size(); i < n; i++) { + ConstraintData *constraint = _constraints[i]; + if (constraint->getRTTI().instanceOf(SliderData::rtti)) { + SliderData *data = static_cast(constraint); + if (data->_animation != NULL) animations.add(data->_animation); + } + } + return animations; +} + +const String &SkeletonData::getName() { + return _name; +} + +void SkeletonData::setName(const String &inValue) { + _name = inValue; +} + +Array &SkeletonData::getBones() { + return _bones; +} + +Array &SkeletonData::getSlots() { + return _slots; +} + +Array &SkeletonData::getSkins() { + return _skins; +} + +Skin *SkeletonData::getDefaultSkin() { + return _defaultSkin; +} + +void SkeletonData::setDefaultSkin(Skin *inValue) { + _defaultSkin = inValue; +} + +Array &SkeletonData::getEvents() { + return _events; +} + +Array &SkeletonData::getAnimations() { + return _animations; +} + +float SkeletonData::getX() { + return _x; +} + +void SkeletonData::setX(float inValue) { + _x = inValue; +} + +float SkeletonData::getY() { + return _y; +} + +void SkeletonData::setY(float inValue) { + _y = inValue; +} + +float SkeletonData::getWidth() { + return _width; +} + +void SkeletonData::setWidth(float inValue) { + _width = inValue; +} + +float SkeletonData::getHeight() { + return _height; +} + +void SkeletonData::setHeight(float inValue) { + _height = inValue; +} + +float SkeletonData::getReferenceScale() { + return _referenceScale; +} + +void SkeletonData::setReferenceScale(float inValue) { + _referenceScale = inValue; +} + +const String &SkeletonData::getVersion() { + return _version; +} + +void SkeletonData::setVersion(const String &inValue) { + _version = inValue; +} + +const String &SkeletonData::getHash() { + return _hash; +} + +void SkeletonData::setHash(const String &inValue) { + _hash = inValue; +} + +const String &SkeletonData::getImagesPath() { + return _imagesPath; +} + +void SkeletonData::setImagesPath(const String &inValue) { + _imagesPath = inValue; +} + + +const String &SkeletonData::getAudioPath() { + return _audioPath; +} + +void SkeletonData::setAudioPath(const String &inValue) { + _audioPath = inValue; +} + +float SkeletonData::getFps() { + return _fps; +} + +void SkeletonData::setFps(float inValue) { + _fps = inValue; +} + +Array &SkeletonData::getConstraints() { + return _constraints; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonJson.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonJson.cpp new file mode 100644 index 0000000..7244d99 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonJson.cpp @@ -0,0 +1,1570 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +class SP_API Vertices : public SpineObject { +public: + Array _bones; + Array _weights; +}; + +#define SKELETON_JSON_ERROR(root, message, value) \ + do { \ + delete skeletonData; \ + setError(root, message, value); \ + return NULL; \ + } while (0) + +static FromProperty *fromProperty(const char *type) { + if (strcmp(type, "rotate") == 0) + return new FromRotate(); + else if (strcmp(type, "x") == 0) + return new FromX(); + else if (strcmp(type, "y") == 0) + return new FromY(); + else if (strcmp(type, "scaleX") == 0) + return new FromScaleX(); + else if (strcmp(type, "scaleY") == 0) + return new FromScaleY(); + else if (strcmp(type, "shearY") == 0) + return new FromShearY(); + else + return NULL; +} + +static float propertyScale(const char *type, float scale) { + if (strcmp(type, "x") == 0 || strcmp(type, "y") == 0) + return scale; + else + return 1; +} + +SkeletonJson::SkeletonJson(Atlas &atlas) : _attachmentLoader(new(__FILE__, __LINE__) AtlasAttachmentLoader(atlas)), _scale(1), _ownsLoader(true) { +} + +SkeletonJson::SkeletonJson(AttachmentLoader &attachmentLoader, bool ownsLoader) + : _attachmentLoader(&attachmentLoader), _scale(1), _ownsLoader(ownsLoader) { +} + +SkeletonJson::~SkeletonJson() { + ArrayUtils::deleteElements(_linkedMeshes); + + if (_ownsLoader) delete _attachmentLoader; +} + +SkeletonData *SkeletonJson::readSkeletonDataFile(const String &path) { + int length; + SkeletonData *skeletonData; + const char *json = SpineExtension::readFile(path, &length); + if (length == 0 || !json) { + setError(NULL, "Unable to read skeleton file: ", path); + return NULL; + } + + skeletonData = readSkeletonData(json); + SpineExtension::free(json, __FILE__, __LINE__); + + if (skeletonData) { + // Extract filename without extension from path + int lastSlash = path.lastIndexOf('/'); + int lastBackslash = path.lastIndexOf('\\'); + int start = 0; + if (lastSlash != -1) start = lastSlash + 1; + if (lastBackslash != -1 && lastBackslash > start) start = lastBackslash + 1; + + int lastDot = path.lastIndexOf('.'); + if (lastDot != -1 && lastDot > start) { + skeletonData->_name = path.substring(start, lastDot - start); + } else { + skeletonData->_name = path.substring(start); + } + } + + return skeletonData; +} + +SkeletonData *SkeletonJson::readSkeletonData(const char *json) { + SkeletonData *skeletonData; + Json *root, *skeleton, *bones, *constraints, *slots, *skins, *animations, *events; + + _error = ""; + _linkedMeshes.clear(); + + root = new (__FILE__, __LINE__) Json(json); + + if (!root) { + setError(NULL, "Invalid skeleton JSON: ", Json::getError()); + return NULL; + } + + skeletonData = new (__FILE__, __LINE__) SkeletonData(); + + skeleton = Json::getItem(root, "skeleton"); + if (skeleton) { + skeletonData->_hash = Json::getString(skeleton, "hash", 0); + skeletonData->_version = Json::getString(skeleton, "spine", 0); + if (!skeletonData->_version.startsWith(SPINE_VERSION_STRING)) { + char errorMsg[255]; + snprintf(errorMsg, 255, "Skeleton version %s does not match runtime version %s", skeletonData->_version.buffer(), SPINE_VERSION_STRING); + SKELETON_JSON_ERROR(NULL, errorMsg, ""); + } + skeletonData->_x = Json::getFloat(skeleton, "x", 0); + skeletonData->_y = Json::getFloat(skeleton, "y", 0); + skeletonData->_width = Json::getFloat(skeleton, "width", 0); + skeletonData->_height = Json::getFloat(skeleton, "height", 0); + skeletonData->_referenceScale = Json::getFloat(skeleton, "referenceScale", 100) * _scale; + skeletonData->_fps = Json::getFloat(skeleton, "fps", 30); + skeletonData->_audioPath = Json::getString(skeleton, "audio", 0); + skeletonData->_imagesPath = Json::getString(skeleton, "images", 0); + } + + /* Bones. */ + bones = Json::getItem(root, "bones"); + if (bones) { + skeletonData->_bones.setSize(bones->_size, 0); + Json *boneMap = bones->_child; + for (int bonesCount = 0; boneMap; boneMap = boneMap->_next, ++bonesCount) { + BoneData *parent = 0; + const char *parentName = Json::getString(boneMap, "parent", 0); + if (parentName) { + parent = skeletonData->findBone(parentName); + if (!parent) SKELETON_JSON_ERROR(root, "Parent bone not found: ", parentName); + } + BoneData *data = new (__FILE__, __LINE__) BoneData(bonesCount, Json::getString(boneMap, "name", 0), parent); + data->_length = Json::getFloat(boneMap, "length", 0) * _scale; + BonePose &setup = data->_setupPose; + setup._x = Json::getFloat(boneMap, "x", 0) * _scale; + setup._y = Json::getFloat(boneMap, "y", 0) * _scale; + setup._rotation = Json::getFloat(boneMap, "rotation", 0); + setup._scaleX = Json::getFloat(boneMap, "scaleX", 1); + setup._scaleY = Json::getFloat(boneMap, "scaleY", 1); + setup._shearX = Json::getFloat(boneMap, "shearX", 0); + setup._shearY = Json::getFloat(boneMap, "shearY", 0); + setup._inherit = Inherit_valueOf(Json::getString(boneMap, "inherit", "normal")); + data->_skinRequired = Json::getBoolean(boneMap, "skin", false); + + const char *color = Json::getString(boneMap, "color", NULL); + if (color) Color::valueOf(color, data->getColor()); + + data->_icon = Json::getString(boneMap, "icon", ""); + data->_iconSize = Json::getFloat(boneMap, "iconSize", 1); + data->_iconRotation = Json::getFloat(boneMap, "iconRotation", 0); + data->_visible = Json::getBoolean(boneMap, "visible", true); + + skeletonData->_bones[bonesCount] = data; + } + } + + /* Slots. */ + slots = Json::getItem(root, "slots"); + if (slots) { + skeletonData->_slots.setSize(slots->_size, 0); + Json *slotMap = slots->_child; + for (int slotCount = 0; slotMap; slotMap = slotMap->_next, ++slotCount) { + String slotName = String(Json::getString(slotMap, "name", 0)); + const char *boneName = Json::getString(slotMap, "bone", 0); + BoneData *boneData = skeletonData->findBone(boneName); + if (!boneData) SKELETON_JSON_ERROR(root, "Slot bone not found: ", boneName); + + SlotData *data = new (__FILE__, __LINE__) SlotData(slotCount, slotName, *boneData); + + const char *color = Json::getString(slotMap, "color", 0); + if (color) Color::valueOf(color, data->_setupPose.getColor()); + + const char *dark = Json::getString(slotMap, "dark", 0); + if (dark) { + data->_setupPose._darkColor = Color::valueOf(dark); + data->_setupPose._hasDarkColor = true; + } + + data->setAttachmentName(Json::getString(slotMap, "attachment", NULL)); + data->_blendMode = BlendMode_valueOf(Json::getString(slotMap, "blend", "normal")); + data->_visible = Json::getBoolean(slotMap, "visible", true); + skeletonData->_slots[slotCount] = data; + } + } + + /* Constraints. */ + constraints = Json::getItem(root, "constraints"); + if (constraints) { + for (Json *constraintMap = constraints->_child; constraintMap; constraintMap = constraintMap->_next) { + const char *name = Json::getString(constraintMap, "name", 0); + bool skinRequired = Json::getBoolean(constraintMap, "skin", false); + const char *type = Json::getString(constraintMap, "type", 0); + if (strcmp(type, "ik") == 0) { + IkConstraintData *data = new (__FILE__, __LINE__) IkConstraintData(name); + data->setSkinRequired(skinRequired); + + Json *entry = Json::getItem(constraintMap, "bones"); + data->_bones.setSize(entry->_size, 0); + entry = entry->_child; + for (int boneCount = 0; entry; entry = entry->_next, ++boneCount) { + data->_bones[boneCount] = skeletonData->findBone(entry->_valueString); + if (!data->_bones[boneCount]) SKELETON_JSON_ERROR(root, "IK bone not found: ", entry->_valueString); + } + + const char *targetName = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findBone(targetName); + if (!data->_target) SKELETON_JSON_ERROR(root, "IK target bone not found: ", targetName); + + const char *scaleY = Json::getString(constraintMap, "scaleY", NULL); + if (scaleY) data->_scaleYMode = ScaleYMode_valueOf(scaleY); + IkConstraintPose &setup = data->_setupPose; + setup._mix = Json::getFloat(constraintMap, "mix", 1); + setup._softness = Json::getFloat(constraintMap, "softness", 0) * _scale; + setup._bendDirection = Json::getBoolean(constraintMap, "bendPositive", true) ? 1 : -1; + setup._compress = Json::getBoolean(constraintMap, "compress", false); + setup._stretch = Json::getBoolean(constraintMap, "stretch", false); + + skeletonData->_constraints.add(data); + } else if (strcmp(type, "transform") == 0) { + TransformConstraintData *data = new (__FILE__, __LINE__) TransformConstraintData(name); + data->setSkinRequired(skinRequired); + + Json *entry = Json::getItem(constraintMap, "bones"); + data->_bones.setSize(entry->_size, 0); + entry = entry->_child; + for (int boneCount = 0; entry; entry = entry->_next, ++boneCount) { + data->_bones[boneCount] = skeletonData->findBone(entry->_valueString); + if (!data->_bones[boneCount]) SKELETON_JSON_ERROR(root, "Transform constraint bone not found: ", entry->_valueString); + } + + const char *sourceName = Json::getString(constraintMap, "source", 0); + data->_source = skeletonData->findBone(sourceName); + if (!data->_source) SKELETON_JSON_ERROR(root, "Transform constraint source bone not found: ", sourceName); + + data->_localSource = Json::getBoolean(constraintMap, "localSource", false); + data->_localTarget = Json::getBoolean(constraintMap, "localTarget", false); + data->_additive = Json::getBoolean(constraintMap, "additive", false); + data->_clamp = Json::getBoolean(constraintMap, "clamp", false); + + bool rotate = false, x = false, y = false, scaleX = false, scaleY = false, shearY = false; + Json *properties = Json::getItem(constraintMap, "properties"); + if (properties) { + for (Json *fromEntry = properties->_child; fromEntry; fromEntry = fromEntry->_next) { + FromProperty *from = fromProperty(fromEntry->_name); + if (!from) SKELETON_JSON_ERROR(root, "Invalid transform constraint from property: ", fromEntry->_name); + float fromScale = propertyScale(fromEntry->_name, _scale); + from->_offset = Json::getFloat(fromEntry, "offset", 0) * fromScale; + Json *toEntry = Json::getItem(fromEntry, "to"); + if (toEntry) { + for (toEntry = toEntry->_child; toEntry; toEntry = toEntry->_next) { + ToProperty *to = NULL; + float toScale = 1; + + if (strcmp(toEntry->_name, "rotate") == 0) { + rotate = true; + to = new ToRotate(); + } else if (strcmp(toEntry->_name, "x") == 0) { + x = true; + to = new ToX(); + toScale = _scale; + } else if (strcmp(toEntry->_name, "y") == 0) { + y = true; + to = new ToY(); + toScale = _scale; + } else if (strcmp(toEntry->_name, "scaleX") == 0) { + scaleX = true; + to = new ToScaleX(); + } else if (strcmp(toEntry->_name, "scaleY") == 0) { + scaleY = true; + to = new ToScaleY(); + } else if (strcmp(toEntry->_name, "shearY") == 0) { + shearY = true; + to = new ToShearY(); + } else { + SKELETON_JSON_ERROR(root, "Invalid transform constraint to property: ", toEntry->_name); + } + + to->_offset = Json::getFloat(toEntry, "offset", 0) * toScale; + to->_max = Json::getFloat(toEntry, "max", 1) * toScale; + to->_scale = Json::getFloat(toEntry, "scale", 1) * toScale / fromScale; + from->_to.add(to); + } + } + + if (from->_to.size() > 0) + data->_properties.add(from); + else + delete from; + } + } + + data->_offsets[TransformConstraintData::ROTATION] = Json::getFloat(constraintMap, "rotation", 0); + data->_offsets[TransformConstraintData::X] = Json::getFloat(constraintMap, "x", 0) * _scale; + data->_offsets[TransformConstraintData::Y] = Json::getFloat(constraintMap, "y", 0) * _scale; + data->_offsets[TransformConstraintData::SCALEX] = Json::getFloat(constraintMap, "scaleX", 0); + data->_offsets[TransformConstraintData::SCALEY] = Json::getFloat(constraintMap, "scaleY", 0); + data->_offsets[TransformConstraintData::SHEARY] = Json::getFloat(constraintMap, "shearY", 0); + + TransformConstraintPose &setup = data->_setupPose; + if (rotate) setup._mixRotate = Json::getFloat(constraintMap, "mixRotate", 1); + if (x) setup._mixX = Json::getFloat(constraintMap, "mixX", 1); + if (y) setup._mixY = Json::getFloat(constraintMap, "mixY", setup._mixX); + if (scaleX) setup._mixScaleX = Json::getFloat(constraintMap, "mixScaleX", 1); + if (scaleY) setup._mixScaleY = Json::getFloat(constraintMap, "mixScaleY", setup._mixScaleX); + if (shearY) setup._mixShearY = Json::getFloat(constraintMap, "mixShearY", 1); + + skeletonData->_constraints.add(data); + } else if (strcmp(type, "path") == 0) { + PathConstraintData *data = new (__FILE__, __LINE__) PathConstraintData(name); + data->setSkinRequired(skinRequired); + + Json *entry = Json::getItem(constraintMap, "bones"); + data->_bones.setSize(entry->_size, 0); + entry = entry->_child; + for (int boneCount = 0; entry; entry = entry->_next, ++boneCount) { + data->_bones[boneCount] = skeletonData->findBone(entry->_valueString); + if (!data->_bones[boneCount]) SKELETON_JSON_ERROR(root, "Path bone not found: ", entry->_valueString); + } + + const char *slotName = Json::getString(constraintMap, "slot", 0); + data->_slot = skeletonData->findSlot(slotName); + if (!data->_slot) SKELETON_JSON_ERROR(root, "Path slot not found: ", slotName); + + data->_positionMode = PositionMode_valueOf(Json::getString(constraintMap, "positionMode", "percent")); + data->_spacingMode = SpacingMode_valueOf(Json::getString(constraintMap, "spacingMode", "length")); + data->_rotateMode = RotateMode_valueOf(Json::getString(constraintMap, "rotateMode", "tangent")); + data->_offsetRotation = Json::getFloat(constraintMap, "rotation", 0); + PathConstraintPose &setup = data->_setupPose; + setup._position = Json::getFloat(constraintMap, "position", 0); + if (data->_positionMode == PositionMode_Fixed) setup._position *= _scale; + setup._spacing = Json::getFloat(constraintMap, "spacing", 0); + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) setup._spacing *= _scale; + setup._mixRotate = Json::getFloat(constraintMap, "mixRotate", 1); + setup._mixX = Json::getFloat(constraintMap, "mixX", 1); + setup._mixY = Json::getFloat(constraintMap, "mixY", setup._mixX); + + skeletonData->_constraints.add(data); + } else if (strcmp(type, "physics") == 0) { + PhysicsConstraintData *data = new (__FILE__, __LINE__) PhysicsConstraintData(name); + data->setSkinRequired(skinRequired); + + const char *boneName = Json::getString(constraintMap, "bone", 0); + data->_bone = skeletonData->findBone(boneName); + if (!data->_bone) SKELETON_JSON_ERROR(root, "Physics bone not found: ", boneName); + + data->_x = Json::getFloat(constraintMap, "x", 0); + data->_y = Json::getFloat(constraintMap, "y", 0); + data->_rotate = Json::getFloat(constraintMap, "rotate", 0); + data->_scaleX = Json::getFloat(constraintMap, "scaleX", 0); + const char *scaleY = Json::getString(constraintMap, "scaleY", NULL); + if (scaleY) data->_scaleYMode = ScaleYMode_valueOf(scaleY); + data->_shearX = Json::getFloat(constraintMap, "shearX", 0); + data->_limit = Json::getFloat(constraintMap, "limit", 5000) * _scale; + data->_step = 1.0f / Json::getInt(constraintMap, "fps", 60); + PhysicsConstraintPose &setup = data->_setupPose; + setup._inertia = Json::getFloat(constraintMap, "inertia", 0.5f); + setup._strength = Json::getFloat(constraintMap, "strength", 100); + setup._damping = Json::getFloat(constraintMap, "damping", 0.85f); + setup._massInverse = 1.0f / Json::getFloat(constraintMap, "mass", 1); + setup._wind = Json::getFloat(constraintMap, "wind", 0); + setup._gravity = Json::getFloat(constraintMap, "gravity", 0); + setup._mix = Json::getFloat(constraintMap, "mix", 1); + data->_inertiaGlobal = Json::getBoolean(constraintMap, "inertiaGlobal", false); + data->_strengthGlobal = Json::getBoolean(constraintMap, "strengthGlobal", false); + data->_dampingGlobal = Json::getBoolean(constraintMap, "dampingGlobal", false); + data->_massGlobal = Json::getBoolean(constraintMap, "massGlobal", false); + data->_windGlobal = Json::getBoolean(constraintMap, "windGlobal", false); + data->_gravityGlobal = Json::getBoolean(constraintMap, "gravityGlobal", false); + data->_mixGlobal = Json::getBoolean(constraintMap, "mixGlobal", false); + + skeletonData->_constraints.add(data); + } else if (strcmp(type, "slider") == 0) { + SliderData *data = new (__FILE__, __LINE__) SliderData(name); + data->setSkinRequired(skinRequired); + data->_additive = Json::getBoolean(constraintMap, "additive", false); + data->_loop = Json::getBoolean(constraintMap, "loop", false); + data->_setupPose._mix = Json::getFloat(constraintMap, "mix", 1); + + const char *boneName = Json::getString(constraintMap, "bone", NULL); + if (boneName != NULL) { + data->_bone = skeletonData->findBone(boneName); + if (!data->_bone) SKELETON_JSON_ERROR(root, "Slider bone not found: ", boneName); + const char *property = Json::getString(constraintMap, "property", 0); + data->_property = fromProperty(property); + if (data->_property) { + float propertyScaleValue = propertyScale(property, _scale); + data->_property->_offset = Json::getFloat(constraintMap, "from", 0) * propertyScaleValue; + data->_offset = Json::getFloat(constraintMap, "to", 0); + data->_scale = Json::getFloat(constraintMap, "scale", 1) / propertyScaleValue; + data->_max = Json::getFloat(constraintMap, "max", 0); + data->_local = Json::getBoolean(constraintMap, "local", false); + } + } else + data->_setupPose._time = Json::getFloat(constraintMap, "time", 0); + + skeletonData->_constraints.add(data); + } + } + } + + /* Skins. */ + skins = Json::getItem(root, "skins"); + if (skins) { + for (Json *skinMap = skins->_child; skinMap; skinMap = skinMap->_next) { + Skin *skin = new (__FILE__, __LINE__) Skin(Json::getString(skinMap, "name", "")); + Json *item = Json::getItem(skinMap, "bones"); + if (item) { + for (Json *entry = item->_child; entry; entry = entry->_next) { + BoneData *data = skeletonData->findBone(entry->_valueString); + if (!data) SKELETON_JSON_ERROR(root, "Skin bone not found: ", entry->_valueString); + skin->getBones().add(data); + } + } + item = Json::getItem(skinMap, "ik"); + if (item) { + for (Json *entry = item->_child; entry; entry = entry->_next) { + IkConstraintData *data = skeletonData->findConstraint(entry->_valueString); + if (!data) SKELETON_JSON_ERROR(root, "Skin IK constraint not found: ", entry->_valueString); + skin->getConstraints().add(data); + } + } + item = Json::getItem(skinMap, "transform"); + if (item) { + for (Json *entry = item->_child; entry; entry = entry->_next) { + TransformConstraintData *data = skeletonData->findConstraint(entry->_valueString); + if (!data) SKELETON_JSON_ERROR(root, "Skin transform constraint not found: ", entry->_valueString); + skin->getConstraints().add(data); + } + } + item = Json::getItem(skinMap, "path"); + if (item) { + for (Json *entry = item->_child; entry; entry = entry->_next) { + PathConstraintData *data = skeletonData->findConstraint(entry->_valueString); + if (!data) SKELETON_JSON_ERROR(root, "Skin path constraint not found: ", entry->_valueString); + skin->getConstraints().add(data); + } + } + item = Json::getItem(skinMap, "physics"); + if (item) { + for (Json *entry = item->_child; entry; entry = entry->_next) { + PhysicsConstraintData *data = skeletonData->findConstraint(entry->_valueString); + if (!data) SKELETON_JSON_ERROR(root, "Skin physics constraint not found: ", entry->_valueString); + skin->getConstraints().add(data); + } + } + item = Json::getItem(skinMap, "slider"); + if (item) { + for (Json *entry = item->_child; entry; entry = entry->_next) { + SliderData *data = skeletonData->findConstraint(entry->_valueString); + if (!data) SKELETON_JSON_ERROR(root, "Skin slider not found: ", entry->_valueString); + skin->getConstraints().add(data); + } + } + + Json *attachments = Json::getItem(skinMap, "attachments"); + if (attachments) + for (Json *slotEntry = attachments->_child; slotEntry; slotEntry = slotEntry->_next) { + SlotData *slot = skeletonData->findSlot(slotEntry->_name); + if (!slot) SKELETON_JSON_ERROR(root, "Skin slot not found: ", slotEntry->_name); + for (Json *entry = slotEntry->_child; entry; entry = entry->_next) { + Attachment *attachment = readAttachment(entry, skin, slot->getIndex(), entry->_name, skeletonData); + if (attachment) + skin->setAttachment(slot->getIndex(), entry->_name, attachment); + else + SKELETON_JSON_ERROR(root, "Error reading attachment: ", entry->_name); + } + } + + const char *color = Json::getString(skinMap, "color", NULL); + if (color) Color::valueOf(color, skin->getColor()); + + skeletonData->_skins.add(skin); + if (strcmp(skin->getName().buffer(), "default") == 0) skeletonData->_defaultSkin = skin; + } + } + + /* Linked meshes. */ + int n = (int) _linkedMeshes.size(); + for (int i = 0; i < n; ++i) { + LinkedMesh *linkedMesh = _linkedMeshes[i]; + Skin *skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin(linkedMesh->_skin); + if (skin == NULL) SKELETON_JSON_ERROR(root, "Skin not found: ", linkedMesh->_skin.buffer()); + Attachment *source = skin->getAttachment(linkedMesh->_sourceIndex, linkedMesh->_source); + if (source == NULL) SKELETON_JSON_ERROR(root, "Source mesh not found: ", linkedMesh->_source.buffer()); + linkedMesh->_mesh->setTimelineAttachment(linkedMesh->_inheritTimelines ? source : linkedMesh->_mesh); + linkedMesh->_mesh->setSourceMesh(static_cast(source)); + linkedMesh->_mesh->updateSequence(); + if (linkedMesh->_inheritTimelines && linkedMesh->_slotIndex != linkedMesh->_sourceIndex) { + Array &timelineSlots = source->getTimelineSlots(); + bool found = false; + for (size_t ii = 0; ii < timelineSlots.size(); ++ii) { + if ((size_t) timelineSlots[ii] == linkedMesh->_slotIndex) { + found = true; + break; + } + } + if (!found) timelineSlots.add((int) linkedMesh->_slotIndex); + } + } + ArrayUtils::deleteElements(_linkedMeshes); + _linkedMeshes.clear(); + + /* Events. */ + events = Json::getItem(root, "events"); + if (events) { + skeletonData->_events.setSize(events->_size, 0); + int eventIndex = 0; + for (Json *eventMap = events->_child; eventMap; eventMap = eventMap->_next) { + EventData *eventData = new (__FILE__, __LINE__) EventData(String(eventMap->_name)); + Event &setup = eventData->_setupPose; + setup._intValue = Json::getInt(eventMap, "int", 0); + setup._floatValue = Json::getFloat(eventMap, "float", 0); + setup._stringValue = Json::getString(eventMap, "string", 0); + eventData->_audioPath = Json::getString(eventMap, "audio", 0); + if (eventData->_audioPath != NULL) { + setup._volume = Json::getFloat(eventMap, "volume", 1); + setup._balance = Json::getFloat(eventMap, "balance", 0); + } + skeletonData->_events[eventIndex] = eventData; + eventIndex++; + } + } + + /* Animations. */ + animations = Json::getItem(root, "animations"); + if (animations) { + skeletonData->_animations.setSize(animations->_size, 0); + int animationsIndex = 0; + for (Json *animationMap = animations->_child; animationMap; animationMap = animationMap->_next) { + Animation *animation = readAnimation(animationMap, skeletonData); + if (!animation) SKELETON_JSON_ERROR(root, "Error reading animation: ", animationMap->_name); + skeletonData->_animations[animationsIndex++] = animation; + } + } + + /* Slider animations. */ + if (constraints) { + for (Json *constraintMap = constraints->_child; constraintMap; constraintMap = constraintMap->_next) { + const char *type = Json::getString(constraintMap, "type", 0); + if (strcmp(type, "slider") == 0) { + SliderData *data = skeletonData->findConstraint(Json::getString(constraintMap, "name", NULL)); + const char *animationName = Json::getString(constraintMap, "animation", NULL); + if (animationName) { + data->_animation = skeletonData->findAnimation(animationName); + if (!data->_animation) SKELETON_JSON_ERROR(root, "Slider animation not found: ", animationName); + } + } + } + } + + delete root; + + return skeletonData; +} + +Attachment *SkeletonJson::readAttachment(Json *map, Skin *skin, int slotIndex, const char *placeholder, SkeletonData *skeletonData) { + float scale = _scale; + const char *name = Json::getString(map, "name", placeholder); + + const char *typeStr = Json::getString(map, "type", "region"); + AttachmentType type = AttachmentType_valueOf(typeStr); + switch (type) { + case AttachmentType_Region: { + const char *path = Json::getString(map, "path", name); + Json *sequenceJson = Json::getItem(map, "sequence"); + Sequence *sequence = readSequence(sequenceJson); + RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, placeholder, name, path, sequence); + if (!region) return NULL; + region->_path = path; + region->setX(Json::getFloat(map, "x", 0) * scale); + region->setY(Json::getFloat(map, "y", 0) * scale); + region->setScaleX(Json::getFloat(map, "scaleX", 1)); + region->setScaleY(Json::getFloat(map, "scaleY", 1)); + region->setRotation(Json::getFloat(map, "rotation", 0)); + region->setWidth(Json::getFloat(map, "width", 0) * scale); + region->setHeight(Json::getFloat(map, "height", 0) * scale); + + const char *color = Json::getString(map, "color", NULL); + if (color) Color::valueOf(color, region->getColor()); + + region->updateSequence(); + return region; + } + case AttachmentType_Boundingbox: { + BoundingBoxAttachment *box = _attachmentLoader->newBoundingBoxAttachment(*skin, placeholder, name); + if (!box) return NULL; + readVertices(map, box, Json::getInt(map, "vertexCount", 0) << 1); + + const char *color = Json::getString(map, "color", NULL); + if (color) Color::valueOf(color, box->getColor()); + return box; + } + case AttachmentType_Mesh: + case AttachmentType_Linkedmesh: { + const char *path = Json::getString(map, "path", name); + Sequence *sequence = readSequence(Json::getItem(map, "sequence")); + MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, placeholder, name, path, sequence); + if (!mesh) return NULL; + mesh->_path = path; + + const char *color = Json::getString(map, "color", NULL); + if (color) Color::valueOf(color, mesh->getColor()); + + mesh->setWidth(Json::getFloat(map, "width", 0) * scale); + mesh->setHeight(Json::getFloat(map, "height", 0) * scale); + + const char *source = Json::getString(map, "source", NULL); + if (source) { + int sourceIndex = slotIndex; + const char *slot = Json::getString(map, "slot", NULL); + if (slot != NULL) { + SlotData *sourceSlot = skeletonData->findSlot(slot); + if (!sourceSlot) { + setError(NULL, "Source mesh slot not found: ", slot); + return NULL; + } + sourceIndex = sourceSlot->getIndex(); + } + LinkedMesh *linkedMesh = new (__FILE__, __LINE__) + LinkedMesh(*mesh, Json::getString(map, "skin", NULL), slotIndex, sourceIndex, source, Json::getBoolean(map, "timelines", true)); + _linkedMeshes.add(linkedMesh); + return mesh; + } + + Array uvs; + if (!Json::asFloatArray(Json::getItem(map, "uvs"), uvs)) return NULL; + readVertices(map, mesh, uvs.size()); + Array triangles; + if (!Json::asUnsignedShortArray(Json::getItem(map, "triangles"), triangles)) return NULL; + mesh->_triangles.clearAndAddAll(triangles); + mesh->_regionUVs.clearAndAddAll(uvs); + + if (Json::getInt(map, "hull", 0)) mesh->setHullLength(Json::getInt(map, "hull", 0) << 1); + Array edges; + Json::asUnsignedShortArray(Json::getItem(map, "edges"), edges); + if (edges.size() > 0) mesh->_edges.clearAndAddAll(edges); + + mesh->updateSequence(); + return mesh; + } + case AttachmentType_Path: { + PathAttachment *path = _attachmentLoader->newPathAttachment(*skin, placeholder, name); + if (!path) return NULL; + path->setClosed(Json::getBoolean(map, "closed", false)); + path->setConstantSpeed(Json::getBoolean(map, "constantSpeed", true)); + + int vertexCount = Json::getInt(map, "vertexCount", 0); + readVertices(map, path, vertexCount << 1); + + if (!Json::asFloatArray(Json::getItem(map, "lengths"), path->_lengths)) return NULL; + for (int i = 0; i < (int) path->_lengths.size(); i++) path->_lengths[i] *= scale; + + const char *color = Json::getString(map, "color", NULL); + if (color) Color::valueOf(color, path->getColor()); + return path; + } + case AttachmentType_Point: { + PointAttachment *point = _attachmentLoader->newPointAttachment(*skin, placeholder, name); + if (!point) return NULL; + point->setX(Json::getFloat(map, "x", 0) * scale); + point->setY(Json::getFloat(map, "y", 0) * scale); + point->setRotation(Json::getFloat(map, "rotation", 0)); + + const char *color = Json::getString(map, "color", NULL); + if (color) Color::valueOf(color, point->getColor()); + return point; + } + case AttachmentType_Clipping: { + ClippingAttachment *clip = _attachmentLoader->newClippingAttachment(*skin, placeholder, name); + if (!clip) return NULL; + + const char *end = Json::getString(map, "end", NULL); + if (end) { + SlotData *slot = skeletonData->findSlot(end); + if (!slot) return NULL; + clip->setEndSlot(slot); + } + + clip->setConvex(Json::getBoolean(map, "convex", false)); + clip->setInverse(Json::getBoolean(map, "inverse", false)); + + readVertices(map, clip, Json::getInt(map, "vertexCount", 0) << 1); + + const char *color = Json::getString(map, "color", NULL); + if (color) Color::valueOf(color, clip->getColor()); + return clip; + } + default: + return NULL; + } +} + +Sequence *SkeletonJson::readSequence(Json *item) { + if (item == NULL) return new (__FILE__, __LINE__) Sequence(1, false); + Sequence *sequence = new (__FILE__, __LINE__) Sequence(Json::getInt(item, "count", 0), true); + sequence->_start = Json::getInt(item, "start", 1); + sequence->_digits = Json::getInt(item, "digits", 0); + sequence->_setupIndex = Json::getInt(item, "setup", 0); + return sequence; +} + +void SkeletonJson::readVertices(Json *map, VertexAttachment *attachment, size_t verticesLength) { + attachment->setWorldVerticesLength(verticesLength); + Array vertices; + if (!Json::asFloatArray(Json::getItem(map, "vertices"), vertices)) { + return; + } + if (verticesLength == vertices.size()) { + if (_scale != 1) { + for (int i = 0; i < (int) vertices.size(); ++i) vertices[i] *= _scale; + } + attachment->getVertices().clearAndAddAll(vertices); + return; + } + + Vertices bonesAndWeights; + bonesAndWeights._weights.ensureCapacity(verticesLength * 3 * 3); + bonesAndWeights._bones.ensureCapacity(verticesLength * 3); + for (int i = 0, n = (int) vertices.size(); i < n;) { + int boneCount = (int) vertices[i++]; + bonesAndWeights._bones.add(boneCount); + for (int nn = i + (boneCount << 2); i < nn; i += 4) { + bonesAndWeights._bones.add((int) vertices[i]); + bonesAndWeights._weights.add(vertices[i + 1] * _scale); + bonesAndWeights._weights.add(vertices[i + 2] * _scale); + bonesAndWeights._weights.add(vertices[i + 3]); + } + } + attachment->getBones().clearAndAddAll(bonesAndWeights._bones); + attachment->getVertices().clearAndAddAll(bonesAndWeights._weights); +} + +Animation *SkeletonJson::readAnimation(Json *map, SkeletonData *skeletonData) { + Array timelines; + Array bones; + + // Slot timelines. + for (Json *slotMap = Json::getItem(map, "slots") ? Json::getItem(map, "slots")->_child : NULL; slotMap; slotMap = slotMap->_next) { + int slotIndex = findSlotIndex(skeletonData, slotMap->_name, timelines); + if (slotIndex == -1) return NULL; + + for (Json *timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) { + Json *keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + + int frames = timelineMap->_size; + if (strcmp(timelineMap->_name, "attachment") == 0) { + AttachmentTimeline *timeline = new (__FILE__, __LINE__) AttachmentTimeline(frames, slotIndex); + for (int frame = 0; keyMap; keyMap = keyMap->_next, ++frame) { + timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0), + Json::getItem(keyMap, "name") ? Json::getItem(keyMap, "name")->_valueString : NULL); + } + timelines.add(timeline); + + } else if (strcmp(timelineMap->_name, "rgba") == 0) { + RGBATimeline *timeline = new (__FILE__, __LINE__) RGBATimeline(frames, frames << 2, slotIndex); + float time = Json::getFloat(keyMap, "time", 0); + Color color; + Color::valueOf(Json::getString(keyMap, "color", 0), color); + + for (int frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b, color.a); + Json *nextMap = keyMap->_next; + if (!nextMap) { + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + Color newColor; + Color::valueOf(Json::getString(nextMap, "color", 0), newColor); + Json *curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (strcmp(timelineMap->_name, "rgb") == 0) { + RGBTimeline *timeline = new (__FILE__, __LINE__) RGBTimeline(frames, frames * 3, slotIndex); + float time = Json::getFloat(keyMap, "time", 0); + const char *colorStr = Json::getString(keyMap, "color", 0); + Color color; + if (colorStr && strlen(colorStr) >= 6) { + color.r = Color::parseHex(colorStr, 0); + color.g = Color::parseHex(colorStr, 1); + color.b = Color::parseHex(colorStr, 2); + } + + for (int frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b); + Json *nextMap = keyMap->_next; + if (!nextMap) { + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + const char *colorStr2 = Json::getString(nextMap, "color", 0); + Color newColor; + if (colorStr2 && strlen(colorStr2) >= 6) { + newColor.r = Color::parseHex(colorStr2, 0); + newColor.g = Color::parseHex(colorStr2, 1); + newColor.b = Color::parseHex(colorStr2, 2); + } + Json *curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (strcmp(timelineMap->_name, "alpha") == 0) { + readTimeline(timelines, keyMap, new (__FILE__, __LINE__) AlphaTimeline(frames, frames, slotIndex), 0, 1); + } else if (strcmp(timelineMap->_name, "rgba2") == 0) { + RGBA2Timeline *timeline = new (__FILE__, __LINE__) RGBA2Timeline(frames, frames * 7, slotIndex); + float time = Json::getFloat(keyMap, "time", 0); + Color color, color2; + Color::valueOf(Json::getString(keyMap, "light", 0), color); + const char *darkStr = Json::getString(keyMap, "dark", 0); + if (darkStr && strlen(darkStr) >= 6) { + color2.r = Color::parseHex(darkStr, 0); + color2.g = Color::parseHex(darkStr, 1); + color2.b = Color::parseHex(darkStr, 2); + } + + for (int frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b); + Json *nextMap = keyMap->_next; + if (!nextMap) { + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + Color newColor, newColor2; + Color::valueOf(Json::getString(nextMap, "light", 0), newColor); + const char *darkStr2 = Json::getString(nextMap, "dark", 0); + if (darkStr2 && strlen(darkStr2) >= 6) { + newColor2.r = Color::parseHex(darkStr2, 0); + newColor2.g = Color::parseHex(darkStr2, 1); + newColor2.b = Color::parseHex(darkStr2, 2); + } + Json *curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (strcmp(timelineMap->_name, "rgb2") == 0) { + RGB2Timeline *timeline = new (__FILE__, __LINE__) RGB2Timeline(frames, frames * 6, slotIndex); + float time = Json::getFloat(keyMap, "time", 0); + const char *lightStr = Json::getString(keyMap, "light", 0); + Color color, color2; + if (lightStr && strlen(lightStr) >= 6) { + color.r = Color::parseHex(lightStr, 0); + color.g = Color::parseHex(lightStr, 1); + color.b = Color::parseHex(lightStr, 2); + } + const char *darkStr = Json::getString(keyMap, "dark", 0); + if (darkStr && strlen(darkStr) >= 6) { + color2.r = Color::parseHex(darkStr, 0); + color2.g = Color::parseHex(darkStr, 1); + color2.b = Color::parseHex(darkStr, 2); + } + + for (int frame = 0, bezier = 0;; ++frame) { + timeline->setFrame(frame, time, color.r, color.g, color.b, color2.r, color2.g, color2.b); + Json *nextMap = keyMap->_next; + if (!nextMap) { + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + const char *lightStr2 = Json::getString(nextMap, "light", 0); + Color newColor, newColor2; + if (lightStr2 && strlen(lightStr2) >= 6) { + newColor.r = Color::parseHex(lightStr2, 0); + newColor.g = Color::parseHex(lightStr2, 1); + newColor.b = Color::parseHex(lightStr2, 2); + } + const char *darkStr2 = Json::getString(nextMap, "dark", 0); + if (darkStr2 && strlen(darkStr2) >= 6) { + newColor2.r = Color::parseHex(darkStr2, 0); + newColor2.g = Color::parseHex(darkStr2, 1); + newColor2.b = Color::parseHex(darkStr2, 2); + } + Json *curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.add(timeline); + } else { + ArrayUtils::deleteElements(timelines); + return NULL; + } + } + } + + // Bone timelines. + Json *boneMaps = Json::getItem(map, "bones"); + bones.ensureCapacity(boneMaps ? boneMaps->_size : 0); + for (Json *boneMap = boneMaps ? boneMaps->_child : NULL; boneMap; boneMap = boneMap->_next) { + int boneIndex = ArrayUtils::findIndexWithName(skeletonData->_bones, boneMap->_name); + if (boneIndex == -1) { + ArrayUtils::deleteElements(timelines); + return NULL; + } + bones.add(boneIndex); + + for (Json *timelineMap = boneMap->_child; timelineMap; timelineMap = timelineMap->_next) { + Json *keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + + int frames = timelineMap->_size; + if (strcmp(timelineMap->_name, "rotate") == 0) { + readTimeline(timelines, keyMap, new (__FILE__, __LINE__) RotateTimeline(frames, frames, boneIndex), 0, 1); + } else if (strcmp(timelineMap->_name, "translate") == 0) { + readTimeline(timelines, keyMap, new (__FILE__, __LINE__) TranslateTimeline(frames, frames << 1, boneIndex), "x", "y", 0, _scale); + } else if (strcmp(timelineMap->_name, "translatex") == 0) { + readTimeline(timelines, keyMap, new (__FILE__, __LINE__) TranslateXTimeline(frames, frames, boneIndex), 0, _scale); + } else if (strcmp(timelineMap->_name, "translatey") == 0) { + readTimeline(timelines, keyMap, new (__FILE__, __LINE__) TranslateYTimeline(frames, frames, boneIndex), 0, _scale); + } else if (strcmp(timelineMap->_name, "scale") == 0) { + readTimeline(timelines, keyMap, new (__FILE__, __LINE__) ScaleTimeline(frames, frames << 1, boneIndex), "x", "y", 1, 1); + } else if (strcmp(timelineMap->_name, "scalex") == 0) { + readTimeline(timelines, keyMap, new (__FILE__, __LINE__) ScaleXTimeline(frames, frames, boneIndex), 1, 1); + } else if (strcmp(timelineMap->_name, "scaley") == 0) { + readTimeline(timelines, keyMap, new (__FILE__, __LINE__) ScaleYTimeline(frames, frames, boneIndex), 1, 1); + } else if (strcmp(timelineMap->_name, "shear") == 0) { + readTimeline(timelines, keyMap, new (__FILE__, __LINE__) ShearTimeline(frames, frames << 1, boneIndex), "x", "y", 0, 1); + } else if (strcmp(timelineMap->_name, "shearx") == 0) { + readTimeline(timelines, keyMap, new (__FILE__, __LINE__) ShearXTimeline(frames, frames, boneIndex), 0, 1); + } else if (strcmp(timelineMap->_name, "sheary") == 0) { + readTimeline(timelines, keyMap, new (__FILE__, __LINE__) ShearYTimeline(frames, frames, boneIndex), 0, 1); + } else if (strcmp(timelineMap->_name, "inherit") == 0) { + InheritTimeline *timeline = new (__FILE__, __LINE__) InheritTimeline(frames, boneIndex); + for (int frame = 0; keyMap; keyMap = keyMap->_next, frame++) { + float time = Json::getFloat(keyMap, "time", 0); + Inherit inherit = Inherit_valueOf(Json::getString(keyMap, "inherit", "normal")); + timeline->setFrame(frame, time, inherit); + } + timelines.add(timeline); + } else { + ArrayUtils::deleteElements(timelines); + return NULL; + } + } + } + + // IK constraint timelines. + for (Json *timelineMap = Json::getItem(map, "ik") ? Json::getItem(map, "ik")->_child : NULL; timelineMap; timelineMap = timelineMap->_next) { + Json *keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + IkConstraintData *constraint = skeletonData->findConstraint(timelineMap->_name); + if (!constraint) { + ArrayUtils::deleteElements(timelines); + return NULL; + } + int constraintIndex = skeletonData->_constraints.indexOf(constraint); + IkConstraintTimeline *timeline = new (__FILE__, __LINE__) IkConstraintTimeline(timelineMap->_size, timelineMap->_size << 1, constraintIndex); + float time = Json::getFloat(keyMap, "time", 0); + float mix = Json::getFloat(keyMap, "mix", 1), softness = Json::getFloat(keyMap, "softness", 0) * _scale; + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mix, softness, Json::getBoolean(keyMap, "bendPositive", true) ? 1 : -1, + Json::getBoolean(keyMap, "compress", false), Json::getBoolean(keyMap, "stretch", false)); + Json *nextMap = keyMap->_next; + if (!nextMap) { + break; + } + + float time2 = Json::getFloat(nextMap, "time", 0); + float mix2 = Json::getFloat(nextMap, "mix", 1), softness2 = Json::getFloat(nextMap, "softness", 0) * _scale; + Json *curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, _scale); + } + + time = time2; + mix = mix2; + softness = softness2; + keyMap = nextMap; + } + + timelines.add(timeline); + } + + // Transform constraint timelines. + for (Json *timelineMap = Json::getItem(map, "transform") ? Json::getItem(map, "transform")->_child : NULL; timelineMap; + timelineMap = timelineMap->_next) { + Json *keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + TransformConstraintData *constraint = skeletonData->findConstraint(timelineMap->_name); + if (!constraint) { + ArrayUtils::deleteElements(timelines); + return NULL; + } + int constraintIndex = skeletonData->_constraints.indexOf(constraint); + TransformConstraintTimeline *timeline = new (__FILE__, __LINE__) + TransformConstraintTimeline(timelineMap->_size, timelineMap->_size * 6, constraintIndex); + float time = Json::getFloat(keyMap, "time", 0); + float mixRotate = Json::getFloat(keyMap, "mixRotate", 1); + float mixX = Json::getFloat(keyMap, "mixX", 1), mixY = Json::getFloat(keyMap, "mixY", mixX); + float mixScaleX = Json::getFloat(keyMap, "mixScaleX", 1), mixScaleY = Json::getFloat(keyMap, "mixScaleY", 1); + float mixShearY = Json::getFloat(keyMap, "mixShearY", 1); + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + Json *nextMap = keyMap->_next; + if (!nextMap) { + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + float mixRotate2 = Json::getFloat(nextMap, "mixRotate", 1); + float mixX2 = Json::getFloat(nextMap, "mixX", 1), mixY2 = Json::getFloat(nextMap, "mixY", mixX2); + float mixScaleX2 = Json::getFloat(nextMap, "mixScaleX", 1), mixScaleY2 = Json::getFloat(nextMap, "mixScaleY", 1); + float mixShearY2 = Json::getFloat(nextMap, "mixShearY", 1); + Json *curve = Json::getItem(keyMap, "curve"); + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + keyMap = nextMap; + } + + timelines.add(timeline); + } + + // Path constraint timelines. + for (Json *constraintMap = Json::getItem(map, "path") ? Json::getItem(map, "path")->_child : NULL; constraintMap; + constraintMap = constraintMap->_next) { + PathConstraintData *constraint = skeletonData->findConstraint(constraintMap->_name); + if (!constraint) { + ArrayUtils::deleteElements(timelines); + return NULL; + } + int index = skeletonData->_constraints.indexOf(constraint); + for (Json *timelineMap = constraintMap->_child; timelineMap; timelineMap = timelineMap->_next) { + Json *keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + + int frames = timelineMap->_size; + const char *timelineName = timelineMap->_name; + if (strcmp(timelineName, "position") == 0) { + PathConstraintPositionTimeline *timeline = new (__FILE__, __LINE__) PathConstraintPositionTimeline(frames, frames, index); + readTimeline(timelines, keyMap, timeline, 0, constraint->_positionMode == PositionMode_Fixed ? _scale : 1); + } else if (strcmp(timelineName, "spacing") == 0) { + CurveTimeline1 *timeline = new (__FILE__, __LINE__) PathConstraintSpacingTimeline(frames, frames, index); + readTimeline(timelines, keyMap, timeline, 0, + constraint->_spacingMode == SpacingMode_Length || constraint->_spacingMode == SpacingMode_Fixed ? _scale : 1); + } else if (strcmp(timelineName, "mix") == 0) { + PathConstraintMixTimeline *timeline = new (__FILE__, __LINE__) PathConstraintMixTimeline(frames, frames * 3, index); + float time = Json::getFloat(keyMap, "time", 0); + float mixRotate = Json::getFloat(keyMap, "mixRotate", 1); + float mixX = Json::getFloat(keyMap, "mixX", 1); + float mixY = Json::getFloat(keyMap, "mixY", mixX); + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, mixRotate, mixX, mixY); + Json *nextMap = keyMap->_next; + if (!nextMap) { + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + float mixRotate2 = Json::getFloat(nextMap, "mixRotate", 1); + float mixX2 = Json::getFloat(nextMap, "mixX", 1), mixY2 = Json::getFloat(nextMap, "mixY", mixX2); + Json *curve = Json::getItem(keyMap, "curve"); + if (curve != NULL) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + keyMap = nextMap; + } + timelines.add(timeline); + } + } + } + + // Physics constraint timelines. + for (Json *constraintMap = Json::getItem(map, "physics") ? Json::getItem(map, "physics")->_child : NULL; constraintMap; + constraintMap = constraintMap->_next) { + int index = -1; + if (constraintMap->_name && strlen(constraintMap->_name) > 0) { + PhysicsConstraintData *constraint = skeletonData->findConstraint(constraintMap->_name); + if (!constraint) { + ArrayUtils::deleteElements(timelines); + return NULL; + } + index = skeletonData->_constraints.indexOf(constraint); + } + for (Json *timelineMap = constraintMap->_child; timelineMap; timelineMap = timelineMap->_next) { + Json *keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + + int frames = timelineMap->_size; + const char *timelineName = timelineMap->_name; + if (strcmp(timelineName, "reset") == 0) { + PhysicsConstraintResetTimeline *timeline = new (__FILE__, __LINE__) PhysicsConstraintResetTimeline(frames, index); + for (int frame = 0; keyMap != NULL; keyMap = keyMap->_next, frame++) timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0)); + timelines.add(timeline); + continue; + } + + CurveTimeline1 *timeline = NULL; + float defaultValue = 0; + if (strcmp(timelineName, "inertia") == 0) { + timeline = new (__FILE__, __LINE__) PhysicsConstraintInertiaTimeline(frames, frames, index); + } else if (strcmp(timelineName, "strength") == 0) { + timeline = new (__FILE__, __LINE__) PhysicsConstraintStrengthTimeline(frames, frames, index); + } else if (strcmp(timelineName, "damping") == 0) { + timeline = new (__FILE__, __LINE__) PhysicsConstraintDampingTimeline(frames, frames, index); + } else if (strcmp(timelineName, "mass") == 0) { + timeline = new (__FILE__, __LINE__) PhysicsConstraintMassTimeline(frames, frames, index); + } else if (strcmp(timelineName, "wind") == 0) { + timeline = new (__FILE__, __LINE__) PhysicsConstraintWindTimeline(frames, frames, index); + } else if (strcmp(timelineName, "gravity") == 0) { + timeline = new (__FILE__, __LINE__) PhysicsConstraintGravityTimeline(frames, frames, index); + } else if (strcmp(timelineName, "mix") == 0) { + defaultValue = 1; + timeline = new (__FILE__, __LINE__) PhysicsConstraintMixTimeline(frames, frames, index); + } else { + continue; + } + readTimeline(timelines, keyMap, timeline, defaultValue, 1); + } + } + + // Slider timelines. + for (Json *constraintMap = Json::getItem(map, "slider") ? Json::getItem(map, "slider")->_child : NULL; constraintMap; + constraintMap = constraintMap->_next) { + SliderData *constraint = skeletonData->findConstraint(constraintMap->_name); + if (!constraint) { + ArrayUtils::deleteElements(timelines); + return NULL; + } + int index = skeletonData->_constraints.indexOf(constraint); + for (Json *timelineMap = constraintMap->_child; timelineMap; timelineMap = timelineMap->_next) { + Json *keyMap = timelineMap->_child; + if (keyMap == NULL) continue; + + int frames = timelineMap->_size; + if (strcmp(timelineMap->_name, "time") == 0) { + readTimeline(timelines, keyMap, new (__FILE__, __LINE__) SliderTimeline(frames, frames, index), 1, 1); + } else if (strcmp(timelineMap->_name, "mix") == 0) { + readTimeline(timelines, keyMap, new (__FILE__, __LINE__) SliderMixTimeline(frames, frames, index), 1, 1); + } + } + } + + // Attachment timelines. + for (Json *attachmentsMap = Json::getItem(map, "attachments") ? Json::getItem(map, "attachments")->_child : NULL; attachmentsMap; + attachmentsMap = attachmentsMap->_next) { + Skin *skin = skeletonData->findSkin(attachmentsMap->_name); + if (!skin) { + ArrayUtils::deleteElements(timelines); + return NULL; + } + for (Json *slotMap = attachmentsMap->_child; slotMap; slotMap = slotMap->_next) { + SlotData *slot = skeletonData->findSlot(slotMap->_name); + if (!slot) { + ArrayUtils::deleteElements(timelines); + setError(NULL, "Attachment slot not found: ", slotMap->_name); + return NULL; + } + int slotIndex = slot->getIndex(); + for (Json *attachmentMap = slotMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) { + Attachment *attachment = skin->getAttachment(slotIndex, attachmentMap->_name); + if (!attachment) { + ArrayUtils::deleteElements(timelines); + return NULL; + } + for (Json *timelineMap = attachmentMap->_child; timelineMap; timelineMap = timelineMap->_next) { + Json *keyMap = timelineMap->_child; + int frames = timelineMap->_size; + String timelineName = timelineMap->_name; + if (timelineName == "deform") { + VertexAttachment *vertexAttachment = static_cast(attachment); + bool weighted = vertexAttachment->_bones.size() != 0; + Array &vertices = vertexAttachment->_vertices; + int deformLength = weighted ? (int) vertices.size() / 3 * 2 : (int) vertices.size(); + + DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frames, frames, slotIndex, *vertexAttachment); + float time = Json::getFloat(keyMap, "time", 0); + for (int frame = 0, bezier = 0;; frame++) { + Array deform; + Json *verticesValue = Json::getItem(keyMap, "vertices"); + if (!verticesValue) { + if (weighted) { + deform.setSize(deformLength, 0); + } else { + deform.clearAndAddAll(vertexAttachment->_vertices); + } + } else { + deform.setSize(deformLength, 0); + int i, start = Json::getInt(keyMap, "offset", 0); + Json *vertex; + for (vertex = verticesValue->_child, i = start; vertex; vertex = vertex->_next, ++i) { + deform[i] = vertex->_valueFloat; + } + if (_scale != 1) { + for (vertex = verticesValue->_child, i = start; vertex; vertex = vertex->_next, ++i) { + deform[i] *= _scale; + } + } + if (!weighted) { + for (i = 0; i < deformLength; ++i) { + deform[i] += vertices[i]; + } + } + } + + timeline->setFrame(frame, time, deform); + Json *nextMap = keyMap->_next; + if (!nextMap) { + break; + } + float time2 = Json::getFloat(nextMap, "time", 0); + Json *curve = Json::getItem(keyMap, "curve"); + if (curve) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1); + time = time2; + keyMap = nextMap; + } + timelines.add(timeline); + } else if (timelineName == "sequence") { + SequenceTimeline *timeline = new (__FILE__, __LINE__) SequenceTimeline(frames, slotIndex, *attachment); + float lastDelay = 0; + for (int frame = 0; keyMap != NULL; keyMap = keyMap->_next, frame++) { + float delay = Json::getFloat(keyMap, "delay", lastDelay); + timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0), + SequenceMode_valueOf(Json::getString(keyMap, "mode", "hold")), Json::getInt(keyMap, "index", 0), + delay); + lastDelay = delay; + } + timelines.add(timeline); + } + } + } + } + } + + // Draw order timeline. + Json *drawOrder = Json::getItem(map, "drawOrder"); + if (drawOrder) { + DrawOrderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderTimeline(drawOrder->_size); + int slotCount = (int) skeletonData->_slots.size(); + int frame = 0; + for (Json *keyMap = drawOrder->_child; keyMap; keyMap = keyMap->_next, ++frame) { + Array drawOrder2; + if (!readDrawOrder(skeletonData, keyMap, slotCount, NULL, drawOrder2)) { + ArrayUtils::deleteElements(timelines); + return NULL; + } + timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0), drawOrder2.size() == 0 ? NULL : &drawOrder2); + } + timelines.add(timeline); + } + + // Draw order folder timelines. + Json *drawOrderFolder = Json::getItem(map, "drawOrderFolder"); + if (drawOrderFolder) { + for (Json *timelineMap = drawOrderFolder->_child; timelineMap; timelineMap = timelineMap->_next) { + Json *slotEntry = Json::getItem(timelineMap, "slots"); + Array folderSlots; + folderSlots.setSize(slotEntry ? slotEntry->_size : 0, 0); + int ii = 0; + for (Json *entry = slotEntry ? slotEntry->_child : NULL; entry; entry = entry->_next, ++ii) { + SlotData *slot = skeletonData->findSlot(entry->_valueString); + if (!slot) { + ArrayUtils::deleteElements(timelines); + setError(NULL, "Draw order folder slot not found: ", entry->_valueString); + return NULL; + } + folderSlots[ii] = slot->getIndex(); + } + Json *keyMap = Json::getItem(timelineMap, "keys"); + DrawOrderFolderTimeline *timeline = new (__FILE__, __LINE__) + DrawOrderFolderTimeline(keyMap ? keyMap->_size : 0, folderSlots, skeletonData->_slots.size()); + int frame = 0; + for (Json *entry = keyMap ? keyMap->_child : NULL; entry; entry = entry->_next, ++frame) { + Array folderDrawOrder; + if (!readDrawOrder(skeletonData, entry, (int) folderSlots.size(), &folderSlots, folderDrawOrder)) { + ArrayUtils::deleteElements(timelines); + return NULL; + } + timeline->setFrame(frame, Json::getFloat(entry, "time", 0), folderDrawOrder.size() == 0 ? NULL : &folderDrawOrder); + } + timelines.add(timeline); + } + } + + // Event timeline. + Json *events = Json::getItem(map, "events"); + if (events) { + EventTimeline *timeline = new (__FILE__, __LINE__) EventTimeline(events->_size); + int frame = 0; + for (Json *keyMap = events->_child; keyMap; keyMap = keyMap->_next, ++frame) { + EventData *eventData = skeletonData->findEvent(Json::getString(keyMap, "name", 0)); + if (!eventData) { + ArrayUtils::deleteElements(timelines); + return NULL; + } + Event &setup = eventData->_setupPose; + Event *event = new (__FILE__, __LINE__) Event(Json::getFloat(keyMap, "time", 0), *eventData); + event->_intValue = Json::getInt(keyMap, "int", setup._intValue); + event->_floatValue = Json::getFloat(keyMap, "float", setup._floatValue); + event->_stringValue = Json::getString(keyMap, "string", setup._stringValue.buffer()); + if (!eventData->_audioPath.isEmpty()) { + event->_volume = Json::getFloat(keyMap, "volume", setup._volume); + event->_balance = Json::getFloat(keyMap, "balance", setup._balance); + } + timeline->setFrame(frame, *event); + } + timelines.add(timeline); + } + + float duration = 0; + for (size_t i = 0; i < timelines.size(); i++) duration = MathUtil::max(duration, timelines[i]->getDuration()); + Animation *animation = new (__FILE__, __LINE__) Animation(String(map->_name)); + animation->setTimelines(timelines, bones); + animation->setDuration(duration); + const char *color = Json::getString(map, "color", NULL); + if (color) Color::valueOf(color, animation->getColor()); + return animation; +} + +void SkeletonJson::readTimeline(Array &timelines, Json *keyMap, CurveTimeline1 *timeline, float defaultValue, float scale) { + float time = Json::getFloat(keyMap, "time", 0), value = Json::getFloat(keyMap, "value", defaultValue) * scale; + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, value); + Json *nextMap = keyMap->_next; + if (!nextMap) { + timelines.add(timeline); + return; + } + float time2 = Json::getFloat(nextMap, "time", 0); + float value2 = Json::getFloat(nextMap, "value", defaultValue) * scale; + Json *curve = Json::getItem(keyMap, "curve"); + if (curve != NULL) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value, value2, scale); + time = time2; + value = value2; + keyMap = nextMap; + } +} + +void SkeletonJson::readTimeline(Array &timelines, Json *keyMap, BoneTimeline2 *timeline, const char *name1, const char *name2, + float defaultValue, float scale) { + float time = Json::getFloat(keyMap, "time", 0); + float value1 = Json::getFloat(keyMap, name1, defaultValue) * scale, value2 = Json::getFloat(keyMap, name2, defaultValue) * scale; + for (int frame = 0, bezier = 0;; frame++) { + timeline->setFrame(frame, time, value1, value2); + Json *nextMap = keyMap->_next; + if (!nextMap) { + timelines.add(timeline); + return; + } + float time2 = Json::getFloat(nextMap, "time", 0); + float nvalue1 = Json::getFloat(nextMap, name1, defaultValue) * scale, nvalue2 = Json::getFloat(nextMap, name2, defaultValue) * scale; + Json *curve = Json::getItem(keyMap, "curve"); + if (curve != NULL) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + keyMap = nextMap; + } +} + +int SkeletonJson::readCurve(Json *curve, CurveTimeline *timeline, int bezier, int frame, int value, float time1, float time2, float value1, + float value2, float scale) { + if (curve->_type == Json::JSON_STRING) { + if (strcmp(curve->_valueString, "stepped") == 0) timeline->setStepped(frame); + return bezier; + } + curve = Json::getItem(curve, value << 2); + float cx1 = curve->_valueFloat; + curve = curve->_next; + float cy1 = curve->_valueFloat * scale; + curve = curve->_next; + float cx2 = curve->_valueFloat; + curve = curve->_next; + float cy2 = curve->_valueFloat * scale; + setBezier(timeline, frame, value, bezier, time1, value1, cx1, cy1, cx2, cy2, time2, value2); + return bezier + 1; +} + +void SkeletonJson::setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1, float cy1, float cx2, + float cy2, float time2, float value2) { + timeline->setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2); +} + +int SkeletonJson::findSlotIndex(SkeletonData *skeletonData, const String &slotName, Array timelines) { + int slotIndex = ArrayUtils::findIndexWithName(skeletonData->getSlots(), slotName); + if (slotIndex == -1) { + ArrayUtils::deleteElements(timelines); + setError(NULL, "Slot not found: ", slotName); + } + return slotIndex; +} + +bool SkeletonJson::readDrawOrder(SkeletonData *skeletonData, Json *keyMap, int slotCount, const Array *folderSlots, Array &drawOrder) { + Json *changes = Json::getItem(keyMap, "offsets"); + drawOrder.clear(); + if (changes == NULL) return true; + + drawOrder.setSize(slotCount, 0); + for (int i = slotCount - 1; i >= 0; i--) drawOrder[i] = -1; + Array unchanged; + unchanged.setSize(slotCount - changes->_size, 0); + int originalIndex = 0, unchangedIndex = 0; + for (Json *offsetMap = changes->_child; offsetMap; offsetMap = offsetMap->_next) { + const char *slotName = Json::getString(offsetMap, "slot", 0); + SlotData *slot = skeletonData->findSlot(slotName); + if (slot == NULL) { + setError(NULL, "Draw order slot not found: ", slotName); + return false; + } + int index; + if (folderSlots == NULL) { + index = slot->getIndex(); + } else { + index = -1; + for (int i = 0; i < slotCount; i++) { + if ((*folderSlots)[i] == slot->getIndex()) { + index = i; + break; + } + } + if (index == -1) { + setError(NULL, "Slot not in folder: ", slotName); + return false; + } + } + while (originalIndex != index) unchanged[unchangedIndex++] = originalIndex++; + int drawOrderIndex = originalIndex; + drawOrder[drawOrderIndex + Json::getInt(offsetMap, "offset", 0)] = originalIndex++; + } + while (originalIndex < slotCount) unchanged[unchangedIndex++] = originalIndex++; + for (int i = slotCount - 1; i >= 0; i--) + if (drawOrder[i] == -1) drawOrder[i] = unchanged[--unchangedIndex]; + return true; +} + +void SkeletonJson::setError(Json *root, const String &value1, const String &value2) { + _error = String(value1).append(value2); + delete root; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonRenderer.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonRenderer.cpp new file mode 100644 index 0000000..5e017c0 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SkeletonRenderer.cpp @@ -0,0 +1,249 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +SkeletonRenderer::SkeletonRenderer() : _allocator(4096), _worldVertices(), _quadIndices(), _clipping(), _renderCommands() { + _quadIndices.add(0); + _quadIndices.add(1); + _quadIndices.add(2); + _quadIndices.add(2); + _quadIndices.add(3); + _quadIndices.add(0); +} + +SkeletonRenderer::~SkeletonRenderer() { +} + +static RenderCommand *createRenderCommand(BlockAllocator &allocator, int numVertices, int32_t numIndices, BlendMode blendMode, void *texture) { + RenderCommand *cmd = allocator.allocate(1); + cmd->positions = allocator.allocate(numVertices << 1); + cmd->uvs = allocator.allocate(numVertices << 1); + cmd->colors = allocator.allocate(numVertices); + cmd->darkColors = allocator.allocate(numVertices); + cmd->numVertices = numVertices; + cmd->indices = allocator.allocate(numIndices); + cmd->numIndices = numIndices; + cmd->blendMode = blendMode; + cmd->texture = texture; + cmd->next = nullptr; + return cmd; +} + +static RenderCommand *batchSubCommands(BlockAllocator &allocator, Array &commands, int first, int last, int numVertices, + int numIndices) { + RenderCommand *batched = createRenderCommand(allocator, numVertices, numIndices, commands[first]->blendMode, commands[first]->texture); + float *positions = batched->positions; + float *uvs = batched->uvs; + uint32_t *colors = batched->colors; + uint32_t *darkColors = batched->darkColors; + uint16_t *indices = batched->indices; + int indicesOffset = 0; + for (int i = first; i <= last; i++) { + RenderCommand *cmd = commands[i]; + memcpy(positions, cmd->positions, sizeof(float) * 2 * cmd->numVertices); + memcpy(uvs, cmd->uvs, sizeof(float) * 2 * cmd->numVertices); + memcpy(colors, cmd->colors, sizeof(int32_t) * cmd->numVertices); + memcpy(darkColors, cmd->darkColors, sizeof(int32_t) * cmd->numVertices); + for (int ii = 0; ii < cmd->numIndices; ii++) indices[ii] = cmd->indices[ii] + indicesOffset; + indicesOffset += cmd->numVertices; + positions += 2 * cmd->numVertices; + uvs += 2 * cmd->numVertices; + colors += cmd->numVertices; + darkColors += cmd->numVertices; + indices += cmd->numIndices; + } + return batched; +} + +static RenderCommand *batchCommands(BlockAllocator &allocator, Array &commands) { + if (commands.size() == 0) return nullptr; + + RenderCommand *root = nullptr; + RenderCommand *last = nullptr; + + RenderCommand *first = commands[0]; + int startIndex = 0; + int i = 1; + int numVertices = first->numVertices; + int numIndices = first->numIndices; + while (i <= (int) commands.size()) { + RenderCommand *cmd = i < (int) commands.size() ? commands[i] : nullptr; + + if (cmd && cmd->numVertices == 0 && cmd->numIndices == 0) { + i++; + continue; + } + + if (cmd != nullptr && cmd->texture == first->texture && cmd->blendMode == first->blendMode && cmd->colors[0] == first->colors[0] && + cmd->darkColors[0] == first->darkColors[0] && numIndices + cmd->numIndices < 0xffff) { + numVertices += cmd->numVertices; + numIndices += cmd->numIndices; + } else { + RenderCommand *batched = batchSubCommands(allocator, commands, startIndex, i - 1, numVertices, numIndices); + if (!last) { + root = last = batched; + } else { + last->next = batched; + last = batched; + } + if (i == (int) commands.size()) break; + first = commands[i]; + startIndex = i; + numVertices = first->numVertices; + numIndices = first->numIndices; + } + i++; + } + return root; +} + +RenderCommand *SkeletonRenderer::render(Skeleton &skeleton) { + _allocator.compress(); + _renderCommands.clear(); + + SkeletonClipping &clipper = _clipping; + + Array &drawOrder = skeleton.getDrawOrder().getAppliedPose(); + for (unsigned i = 0; i < drawOrder.size(); ++i) { + Slot &slot = *drawOrder[i]; + Attachment *attachment = slot.getAppliedPose().getAttachment(); + if (!attachment) { + clipper.clipEnd(slot); + continue; + } + + // Early out if the slot color is 0 or the bone is not active + if ((slot.getAppliedPose().getColor().a == 0 || !slot.getBone().isActive()) && !attachment->getRTTI().isExactly(ClippingAttachment::rtti)) { + clipper.clipEnd(slot); + continue; + } + + Array *worldVertices = &_worldVertices; + Array *quadIndices = &_quadIndices; + Array *vertices = worldVertices; + int32_t verticesCount; + Array *uvs; + Array *indices; + int32_t indicesCount; + Color *attachmentColor; + void *texture; + + if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) { + RegionAttachment *regionAttachment = (RegionAttachment *) attachment; + attachmentColor = ®ionAttachment->getColor(); + + if (attachmentColor->a == 0) { + clipper.clipEnd(slot); + continue; + } + + Sequence &sequence = regionAttachment->getSequence(); + int sequenceIndex = sequence.resolveIndex(slot.getAppliedPose()); + TextureRegion *region = sequence.getRegion(sequenceIndex); + worldVertices->setSize(8, 0); + regionAttachment->computeWorldVertices(slot, regionAttachment->getOffsets(slot.getAppliedPose()), *worldVertices, 0, 2); + verticesCount = 4; + uvs = &sequence.getUVs(sequenceIndex); + indices = quadIndices; + indicesCount = 6; + texture = region->_rendererObject; + + } else if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) { + MeshAttachment *mesh = (MeshAttachment *) attachment; + attachmentColor = &mesh->getColor(); + + if (attachmentColor->a == 0) { + clipper.clipEnd(slot); + continue; + } + + Sequence &sequence = mesh->getSequence(); + int sequenceIndex = sequence.resolveIndex(slot.getAppliedPose()); + TextureRegion *region = sequence.getRegion(sequenceIndex); + worldVertices->setSize(mesh->getWorldVerticesLength(), 0); + mesh->computeWorldVertices(skeleton, slot, 0, mesh->getWorldVerticesLength(), worldVertices->buffer(), 0, 2); + verticesCount = (int32_t) (mesh->getWorldVerticesLength() >> 1); + uvs = &sequence.getUVs(sequenceIndex); + indices = &mesh->getTriangles(); + indicesCount = (int32_t) indices->size(); + texture = region->_rendererObject; + + } else if (attachment->getRTTI().isExactly(ClippingAttachment::rtti)) { + ClippingAttachment *clip = (ClippingAttachment *) slot.getAppliedPose().getAttachment(); + clipper.clipStart(skeleton, slot, clip); + continue; + } else + continue; + + uint8_t r = static_cast(skeleton.getColor().r * slot.getAppliedPose().getColor().r * attachmentColor->r * 255); + uint8_t g = static_cast(skeleton.getColor().g * slot.getAppliedPose().getColor().g * attachmentColor->g * 255); + uint8_t b = static_cast(skeleton.getColor().b * slot.getAppliedPose().getColor().b * attachmentColor->b * 255); + uint8_t a = static_cast(skeleton.getColor().a * slot.getAppliedPose().getColor().a * attachmentColor->a * 255); + uint32_t color = (a << 24) | (r << 16) | (g << 8) | b; + uint32_t darkColor = 0xff000000; + if (slot.getAppliedPose().hasDarkColor()) { + Color &slotDarkColor = slot.getAppliedPose().getDarkColor(); + darkColor = 0xff000000 | (static_cast(slotDarkColor.r * 255) << 16) | (static_cast(slotDarkColor.g * 255) << 8) | + static_cast(slotDarkColor.b * 255); + } + + if (clipper.isClipping()) { + clipper.clipTriangles(*worldVertices, *indices, *uvs, 2); + vertices = &clipper.getClippedVertices(); + verticesCount = (int32_t) (clipper.getClippedVertices().size() >> 1); + uvs = &clipper.getClippedUVs(); + indices = &clipper.getClippedTriangles(); + indicesCount = (int32_t) (clipper.getClippedTriangles().size()); + } + + RenderCommand *cmd = createRenderCommand(_allocator, verticesCount, indicesCount, slot.getData().getBlendMode(), texture); + _renderCommands.add(cmd); + memcpy(cmd->positions, vertices->buffer(), (verticesCount << 1) * sizeof(float)); + memcpy(cmd->uvs, uvs->buffer(), (verticesCount << 1) * sizeof(float)); + for (int ii = 0; ii < verticesCount; ii++) { + cmd->colors[ii] = color; + cmd->darkColors[ii] = darkColor; + } + memcpy(cmd->indices, indices->buffer(), indices->size() * sizeof(uint16_t)); + clipper.clipEnd(slot); + } + clipper.clipEnd(); + + return batchCommands(_allocator, _renderCommands); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Skin.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Skin.cpp new file mode 100644 index 0000000..42ec9b3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Skin.cpp @@ -0,0 +1,192 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include + +using namespace spine; + +Skin::AttachmentMap::AttachmentMap() { +} + +static void disposeAttachment(Attachment *attachment) { + if (!attachment) return; + attachment->dereference(); + if (attachment->getRefCount() == 0) delete attachment; +} + +void Skin::AttachmentMap::put(size_t slotIndex, const String &placeholder, Attachment *attachment) { + if (slotIndex >= _buckets.size()) _buckets.setSize(slotIndex + 1, Array()); + Array &bucket = _buckets[slotIndex]; + int existing = findInBucket(bucket, placeholder); + attachment->reference(); + if (existing >= 0) { + disposeAttachment(bucket[existing]._attachment); + bucket[existing]._attachment = attachment; + } else { + bucket.add(Entry(slotIndex, placeholder, attachment)); + } +} + +Attachment *Skin::AttachmentMap::get(size_t slotIndex, const String &placeholder) { + if (slotIndex >= _buckets.size()) return NULL; + int existing = findInBucket(_buckets[slotIndex], placeholder); + return existing >= 0 ? _buckets[slotIndex][existing]._attachment : NULL; +} + +void Skin::AttachmentMap::remove(size_t slotIndex, const String &placeholder) { + if (slotIndex >= _buckets.size()) return; + int existing = findInBucket(_buckets[slotIndex], placeholder); + if (existing >= 0) { + disposeAttachment(_buckets[slotIndex][existing]._attachment); + _buckets[slotIndex].removeAt(existing); + } +} + +int Skin::AttachmentMap::findInBucket(Array &bucket, const String &placeholder) { + for (size_t i = 0; i < bucket.size(); i++) + if (bucket[i]._placeholder == placeholder) return (int) i; + return -1; +} + +Skin::AttachmentMap::Entries Skin::AttachmentMap::getEntries() { + return Skin::AttachmentMap::Entries(_buckets); +} + +Skin::Skin(const String &name) : _name(name), _attachments(), _color(0.99607843f, 0.61960787f, 0.30980393f, 1) { + assert(_name.length() > 0); +} + +Skin::~Skin() { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry entry = entries.next(); + disposeAttachment(entry._attachment); + } +} + +void Skin::setAttachment(size_t slotIndex, const String &placeholder, Attachment *attachment) { + _attachments.put(slotIndex, placeholder, attachment); +} + +Attachment *Skin::getAttachment(size_t slotIndex, const String &placeholder) { + return _attachments.get(slotIndex, placeholder); +} + +void Skin::removeAttachment(size_t slotIndex, const String &placeholder) { + _attachments.remove(slotIndex, placeholder); +} + +void Skin::findNamesForSlot(size_t slotIndex, Array &names) { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == slotIndex) { + names.add(entry._placeholder); + } + } +} + +void Skin::findAttachmentsForSlot(size_t slotIndex, Array &attachments) { + Skin::AttachmentMap::Entries entries = _attachments.getEntries(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == slotIndex) attachments.add(entry._attachment); + } +} + +const String &Skin::getName() { + return _name; +} + +Skin::AttachmentMap::Entries Skin::getAttachments() { + return _attachments.getEntries(); +} + +void Skin::attachAll(Skeleton &skeleton, Skin &oldSkin) { + Array &slots = skeleton.getSlots(); + Skin::AttachmentMap::Entries entries = oldSkin.getAttachments(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + int slotIndex = (int) entry._slotIndex; + Slot *slot = slots[slotIndex]; + + if (slot->getPose().getAttachment() == entry._attachment) { + Attachment *attachment = getAttachment(slotIndex, entry._placeholder); + if (attachment) slot->getPose().setAttachment(attachment); + } + } +} + +void Skin::addSkin(Skin &other) { + for (size_t i = 0; i < other.getBones().size(); i++) + if (!_bones.contains(other.getBones()[i])) _bones.add(other.getBones()[i]); + + for (size_t i = 0; i < other.getConstraints().size(); i++) + if (!_constraints.contains(other.getConstraints()[i])) _constraints.add(other.getConstraints()[i]); + + AttachmentMap::Entries entries = other.getAttachments(); + while (entries.hasNext()) { + AttachmentMap::Entry &entry = entries.next(); + setAttachment(entry._slotIndex, entry._placeholder, entry._attachment); + } +} + +void Skin::copySkin(Skin &other) { + for (size_t i = 0; i < other.getBones().size(); i++) + if (!_bones.contains(other.getBones()[i])) _bones.add(other.getBones()[i]); + + for (size_t i = 0; i < other.getConstraints().size(); i++) + if (!_constraints.contains(other.getConstraints()[i])) _constraints.add(other.getConstraints()[i]); + + AttachmentMap::Entries entries = other.getAttachments(); + while (entries.hasNext()) { + AttachmentMap::Entry &entry = entries.next(); + if (entry._attachment->getRTTI().isExactly(MeshAttachment::rtti)) + setAttachment(entry._slotIndex, entry._placeholder, &static_cast(entry._attachment)->newLinkedMesh()); + else + setAttachment(entry._slotIndex, entry._placeholder, &entry._attachment->copy()); + } +} + +Array &Skin::getConstraints() { + return _constraints; +} + +Array &Skin::getBones() { + return _bones; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Slider.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Slider.cpp new file mode 100644 index 0000000..2de1e14 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Slider.cpp @@ -0,0 +1,182 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(Slider, Constraint) + +namespace { + SlotTimeline *asSlotTimeline(Timeline *timeline) { + if (timeline->getRTTI().isExactly(AlphaTimeline::rtti)) return static_cast(timeline); + if (timeline->getRTTI().instanceOf(SlotCurveTimeline::rtti)) return static_cast(timeline); + if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) return static_cast(timeline); + if (timeline->getRTTI().isExactly(SequenceTimeline::rtti)) return static_cast(timeline); + return NULL; + } + + ConstraintTimeline *asConstraintTimeline(Timeline *timeline) { + if (timeline->getRTTI().instanceOf(ConstraintTimeline1::rtti)) return static_cast(timeline); + if (timeline->getRTTI().instanceOf(PhysicsConstraintTimeline::rtti)) return static_cast(timeline); + if (timeline->getRTTI().isExactly(PhysicsConstraintResetTimeline::rtti)) return static_cast(timeline); + if (timeline->getRTTI().isExactly(IkConstraintTimeline::rtti)) return static_cast(timeline); + if (timeline->getRTTI().isExactly(PathConstraintMixTimeline::rtti)) return static_cast(timeline); + if (timeline->getRTTI().isExactly(TransformConstraintTimeline::rtti)) return static_cast(timeline); + return NULL; + } + + void constrain(Skeleton &skeleton, Constraint *constraint) { + if (constraint->getRTTI().instanceOf(IkConstraint::rtti)) + skeleton.constrained(*static_cast(constraint)); + else if (constraint->getRTTI().instanceOf(PathConstraint::rtti)) + skeleton.constrained(*static_cast(constraint)); + else if (constraint->getRTTI().instanceOf(PhysicsConstraint::rtti)) + skeleton.constrained(*static_cast(constraint)); + else if (constraint->getRTTI().instanceOf(Slider::rtti)) + skeleton.constrained(*static_cast(constraint)); + else if (constraint->getRTTI().instanceOf(TransformConstraint::rtti)) + skeleton.constrained(*static_cast(constraint)); + } +} + +float Slider::_offsets[6]; + +Slider::Slider(SliderData &data, Skeleton &skeleton) : SliderBase(data), _bone(NULL) { + if (data._bone != NULL) { + _bone = skeleton._bones[data._bone->getIndex()]; + } +} + +Slider &Slider::copy(Skeleton &skeleton) { + Slider *copy = new (__FILE__, __LINE__) Slider(_data, skeleton); + copy->_pose.set(_pose); + return *copy; +} + +void Slider::update(Skeleton &skeleton, Physics physics) { + SliderPose &p = *_appliedPose; + if (p._mix == 0) return; + + Animation *animation = _data._animation; + if (_bone != NULL) { + if (!_bone->isActive()) return; + if (_data._local) _bone->_appliedPose->validateLocalTransform(skeleton); + p._time = _data._offset + + (_data._property->value(skeleton, *_bone->_appliedPose, _data._local, _offsets) - _data._property->_offset) * _data._scale; + if (_data._loop) + p._time = animation->getDuration() + MathUtil::fmod(p._time, animation->getDuration()); + else + p._time = MathUtil::max(0.0f, p._time); + } + + Array &bones = skeleton._bones; + const Array &indices = animation->getBones(); + for (size_t i = 0, n = indices.size(); i < n; i++) bones[indices[i]]->_appliedPose->modifyLocal(skeleton); + + animation->apply(skeleton, p._time, p._time, _data._loop, NULL, p._mix, MixFrom_Current, _data._additive, false, true); +} + +void Slider::sort(Skeleton &skeleton) { + if (_bone != NULL && !_data._local) skeleton.sortBone(_bone); + skeleton._updateCache.add(this); + + Array &bones = skeleton._bones; + const Array &indices = _data._animation->getBones(); + for (size_t i = 0, n = indices.size(); i < n; i++) { + Bone *bone = bones[indices[i]]; + bone->_sorted = false; + skeleton.sortReset(bone->getChildren()); + skeleton.constrained(*bone); + } + + Array &timelines = _data._animation->getTimelines(); + Array &slots = skeleton._slots; + Array &constraints = skeleton._constraints; + Array &physics = skeleton._physics; + size_t physicsCount = physics.size(); + for (size_t i = 0, n = timelines.size(); i < n; i++) { + Timeline *t = timelines[i]; + + SlotTimeline *slotTimeline = asSlotTimeline(t); + if (slotTimeline) { + skeleton.constrained(*slots[slotTimeline->getSlotIndex()]); + } else if (t->getRTTI().instanceOf(DrawOrderTimeline::rtti) || t->getRTTI().instanceOf(DrawOrderFolderTimeline::rtti)) { + skeleton.getDrawOrder().constrained(); + } else { + ConstraintTimeline *constraintTimeline = asConstraintTimeline(t); + if (!constraintTimeline) continue; + if (t->getRTTI().instanceOf(PhysicsConstraintTimeline::rtti) && constraintTimeline->getConstraintIndex() == -1) { + for (size_t ii = 0; ii < physicsCount; ii++) skeleton.constrained(*physics[ii]); + } else { + int index = constraintTimeline->getConstraintIndex(); + if (index != -1) constrain(skeleton, constraints[index]); + } + } + } +} + +bool Slider::isSourceActive() { + return _bone == NULL || _bone->isActive(); +} + +Bone &Slider::getBone() { + return *_bone; +} + +void Slider::setBone(Bone &bone) { + _bone = &bone; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SliderData.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SliderData.cpp new file mode 100644 index 0000000..311eab4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SliderData.cpp @@ -0,0 +1,127 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(SliderData, ConstraintData) + +SliderData::SliderData(const String &name) + : ConstraintDataGeneric(name), _animation(NULL), _additive(false), _loop(false), _bone(NULL), _property(NULL), _offset(0.0f), + _scale(0.0f), _max(0.0f), _local(false) { +} + +SliderData::~SliderData() { + if (_property) { + ArrayUtils::deleteElements(_property->_to); + delete _property; + _property = NULL; + } +} + +Constraint &SliderData::create(Skeleton &skeleton) { + return *(new (__FILE__, __LINE__) Slider(*this, skeleton)); +} + +Animation &SliderData::getAnimation() { + return *_animation; +} + +void SliderData::setAnimation(Animation &animation) { + _animation = &animation; +} + +bool SliderData::getAdditive() { + return _additive; +} + +void SliderData::setAdditive(bool additive) { + _additive = additive; +} + +bool SliderData::getLoop() { + return _loop; +} + +void SliderData::setLoop(bool loop) { + _loop = loop; +} + +BoneData *SliderData::getBone() { + return _bone; +} + +void SliderData::setBone(BoneData *bone) { + _bone = bone; +} + +FromProperty *SliderData::getProperty() { + return _property; +} + +void SliderData::setProperty(FromProperty *property) { + _property = property; +} + +float SliderData::getScale() { + return _scale; +} + +void SliderData::setScale(float scale) { + _scale = scale; +} + +float SliderData::getOffset() { + return _offset; +} + +void SliderData::setOffset(float offset) { + _offset = offset; +} + +float SliderData::getMax() { + return _max; +} + +void SliderData::setMax(float max) { + _max = max; +} + +bool SliderData::getLocal() { + return _local; +} + +void SliderData::setLocal(bool local) { + _local = local; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SliderMixTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SliderMixTimeline.cpp new file mode 100644 index 0000000..433b032 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SliderMixTimeline.cpp @@ -0,0 +1,67 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(SliderMixTimeline, ConstraintTimeline1) + +SliderMixTimeline::SliderMixTimeline(size_t frameCount, size_t bezierCount, int sliderIndex) + : ConstraintTimeline1(frameCount, bezierCount, sliderIndex, Property_SliderMix) { + PropertyId ids[] = {((PropertyId) Property_SliderMix << 32) | sliderIndex}; + setPropertyIds(ids, 1); + _additive = true; +} + +SliderMixTimeline::~SliderMixTimeline() { +} + +void SliderMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(out); + + Slider *constraint = (Slider *) skeleton._constraints[_constraintIndex]; + if (constraint->isActive()) { + SliderPose &pose = appliedPose ? *constraint->_appliedPose : constraint->_pose; + SliderData &data = constraint->_data; + pose._mix = getAbsoluteValue(time, alpha, from, add, pose._mix, data._setupPose._mix); + } +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SliderPose.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SliderPose.cpp new file mode 100644 index 0000000..0419ce4 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SliderPose.cpp @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +SliderPose::SliderPose() : _time(0), _mix(0) { +} + +SliderPose::~SliderPose() { +} + +void SliderPose::set(SliderPose &pose) { + _time = pose._time; + _mix = pose._mix; +} + +float SliderPose::getTime() { + return _time; +} + +void SliderPose::setTime(float time) { + this->_time = time; +} + +float SliderPose::getMix() { + return _mix; +} + +void SliderPose::setMix(float mix) { + this->_mix = mix; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SliderTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SliderTimeline.cpp new file mode 100644 index 0000000..b3f628e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SliderTimeline.cpp @@ -0,0 +1,66 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(SliderTimeline, ConstraintTimeline1) + +SliderTimeline::SliderTimeline(size_t frameCount, size_t bezierCount, int sliderIndex) + : ConstraintTimeline1(frameCount, bezierCount, sliderIndex, Property_SliderTime) { + PropertyId ids[] = {((PropertyId) Property_SliderTime << 32) | sliderIndex}; + setPropertyIds(ids, 1); +} + +SliderTimeline::~SliderTimeline() { +} + +void SliderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(out); + + Slider *constraint = (Slider *) skeleton._constraints[_constraintIndex]; + if (constraint->isActive()) { + SliderPose &pose = appliedPose ? *constraint->_appliedPose : constraint->_pose; + SliderData &data = constraint->_data; + pose._time = getAbsoluteValue(time, alpha, from, add, pose._time, data._setupPose._time); + } +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Slot.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Slot.cpp new file mode 100644 index 0000000..7d954de --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Slot.cpp @@ -0,0 +1,64 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +Slot::Slot(SlotData &data, Skeleton &skeleton) + : PosedGeneric(data), _skeleton(skeleton), _bone(*skeleton.getBones()[data._boneData._index]), _attachmentState(0) { + + if (data.getSetupPose().hasDarkColor()) { + _pose._hasDarkColor = true; + _constrainedPose._hasDarkColor = true; + } + setupPose(); +} + +Bone &Slot::getBone() { + return _bone; +} + +void Slot::setupPose() { + _pose._color.set(_data._setupPose._color); + if (_pose._hasDarkColor) _pose._darkColor.set(_data._setupPose._darkColor); + _pose._sequenceIndex = _data._setupPose._sequenceIndex; + if (_data._attachmentName.isEmpty()) + _pose.setAttachment(NULL); + else { + _pose._attachment = NULL; + _pose.setAttachment(_skeleton.getAttachment(_data._index, _data._attachmentName)); + } +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SlotCurveTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SlotCurveTimeline.cpp new file mode 100644 index 0000000..7f54052 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SlotCurveTimeline.cpp @@ -0,0 +1,64 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL_MULTI(SlotCurveTimeline, CurveTimeline, SlotTimeline) + +SlotCurveTimeline::SlotCurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount, int slotIndex) + : CurveTimeline(frameCount, frameEntries, bezierCount), SlotTimeline(), _slotIndex(slotIndex) { +} + +SlotCurveTimeline::~SlotCurveTimeline() { +} + +int SlotCurveTimeline::getSlotIndex() { + return _slotIndex; +} + +void SlotCurveTimeline::setSlotIndex(int inValue) { + _slotIndex = inValue; +} + +void SlotCurveTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, bool out, + bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(out); + + Slot *slot = skeleton._slots[_slotIndex]; + if (slot->_bone.isActive()) _apply(*slot, appliedPose ? *slot->_appliedPose : slot->_pose, time, alpha, from, add); +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SlotData.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SlotData.cpp new file mode 100644 index 0000000..9d261f8 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SlotData.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +#include + +using namespace spine; + +SlotData::SlotData(int index, const String &name, BoneData &boneData) + : PosedDataGeneric(name), _index(index), _boneData(boneData), _attachmentName(), _blendMode(BlendMode_Normal), _visible(true) { + assert(index >= 0); +} + +int SlotData::getIndex() { + return _index; +} + +BoneData &SlotData::getBoneData() { + return _boneData; +} + +void SlotData::setAttachmentName(const String &attachmentName) { + _attachmentName = attachmentName; +} + +const String &SlotData::getAttachmentName() { + return _attachmentName; +} + +BlendMode SlotData::getBlendMode() { + return _blendMode; +} + +void SlotData::setBlendMode(BlendMode blendMode) { + _blendMode = blendMode; +} + +bool SlotData::getVisible() { + return _visible; +} + +void SlotData::setVisible(bool visible) { + _visible = visible; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SlotPose.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SlotPose.cpp new file mode 100644 index 0000000..c416df1 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SlotPose.cpp @@ -0,0 +1,91 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +using namespace spine; + +SlotPose::SlotPose() : _color(1, 1, 1, 1), _darkColor(0, 0, 0, 0), _hasDarkColor(false), _attachment(nullptr), _sequenceIndex(0) { +} + +SlotPose::~SlotPose() { +} + +void SlotPose::set(SlotPose &pose) { + _color.set(pose._color); + if (pose._hasDarkColor) _darkColor.set(pose._darkColor); + _hasDarkColor = pose._hasDarkColor; + _attachment = pose._attachment; + _sequenceIndex = pose._sequenceIndex; + _deform.clear(); + _deform.addAll(pose._deform); +} + +Color &SlotPose::getColor() { + return _color; +} + +Color &SlotPose::getDarkColor() { + return _darkColor; +} + +bool SlotPose::hasDarkColor() { + return _hasDarkColor; +} + +void SlotPose::setHasDarkColor(bool hasDarkColor) { + _hasDarkColor = hasDarkColor; +} + +Attachment *SlotPose::getAttachment() { + return _attachment; +} + +void SlotPose::setAttachment(Attachment *attachment) { + if (_attachment == attachment) return; + + // Check if we need to clear deform based on timeline attachment. + if (!attachment || !_attachment || attachment->getTimelineAttachment() != _attachment->getTimelineAttachment()) _deform.clear(); + _attachment = attachment; + _sequenceIndex = -1; +} + +int SlotPose::getSequenceIndex() { + return _sequenceIndex; +} + +void SlotPose::setSequenceIndex(int sequenceIndex) { + _sequenceIndex = sequenceIndex; +} + +Array &SlotPose::getDeform() { + return _deform; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SlotTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SlotTimeline.cpp new file mode 100644 index 0000000..c314515 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SlotTimeline.cpp @@ -0,0 +1,40 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(SlotTimeline) + +SlotTimeline::SlotTimeline() { +} + +SlotTimeline::~SlotTimeline() { +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SpineObject.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SpineObject.cpp new file mode 100644 index 0000000..d71bf6e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/SpineObject.cpp @@ -0,0 +1,63 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +using namespace spine; + +void *SpineObject::operator new(size_t sz) { + return SpineExtension::getInstance()->_calloc(sz, __FILE__, __LINE__); +} + +void *SpineObject::operator new(size_t sz, const char *file, int line) { + return SpineExtension::getInstance()->_calloc(sz, file, line); +} + +void *SpineObject::operator new(size_t sz, void *ptr) { + SP_UNUSED(sz); + return ptr; +} + +void SpineObject::operator delete(void *p, const char *file, int line) { + SpineExtension::free(p, file, line); +} + +void SpineObject::operator delete(void *p, void *mem) { + SP_UNUSED(mem); + SpineExtension::free(p, __FILE__, __LINE__); +} + +void SpineObject::operator delete(void *p) { + SpineExtension::free(p, __FILE__, __LINE__); +} + +SpineObject::~SpineObject() { + SpineExtension::beforeFree(this); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TextureLoader.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TextureLoader.cpp new file mode 100644 index 0000000..4dd2a5f --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TextureLoader.cpp @@ -0,0 +1,38 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +namespace spine { + TextureLoader::TextureLoader() { + } + + TextureLoader::~TextureLoader() { + } +}// namespace spine diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TextureRegion.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TextureRegion.cpp new file mode 100644 index 0000000..373a430 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TextureRegion.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(TextureRegion) \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Timeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Timeline.cpp new file mode 100644 index 0000000..2b63f9e --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Timeline.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(Timeline) + +Timeline::Timeline(size_t frameCount, size_t frameEntries) + : _propertyIds(), _frames(), _frameEntries(frameEntries), _additive(false), _instant(false) { + _frames.setSize(frameCount * frameEntries, 0); +} + +Timeline::~Timeline() { +} + +Array &Timeline::getPropertyIds() { + return _propertyIds; +} + +void Timeline::setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount) { + _propertyIds.clear(); + _propertyIds.ensureCapacity(propertyIdsCount); + for (size_t i = 0; i < propertyIdsCount; i++) { + _propertyIds.add(propertyIds[i]); + } +} + +size_t Timeline::getFrameCount() { + return _frames.size() / _frameEntries; +} + +Array &Timeline::getFrames() { + return _frames; +} + +size_t Timeline::getFrameEntries() { + return _frameEntries; +} + +float Timeline::getDuration() { + return _frames[_frames.size() - getFrameEntries()]; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TransformConstraint.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TransformConstraint.cpp new file mode 100644 index 0000000..d6da79d --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TransformConstraint.cpp @@ -0,0 +1,138 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +using namespace spine; + +RTTI_IMPL(TransformConstraint, Constraint) + +TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : TransformConstraintBase(data) { + + _bones.ensureCapacity(data.getBones().size()); + for (size_t i = 0; i < data.getBones().size(); i++) { + BoneData *boneData = data.getBones()[i]; + _bones.add(&skeleton._bones[boneData->getIndex()]->_constrainedPose); + } + + _source = skeleton._bones[data._source->getIndex()]; +} + +TransformConstraint &TransformConstraint::copy(Skeleton &skeleton) { + TransformConstraint *copy = new (__FILE__, __LINE__) TransformConstraint(_data, skeleton); + copy->_pose.set(_pose); + return *copy; +} + +/// Applies the constraint to the constrained bones. +void TransformConstraint::update(Skeleton &skeleton, Physics physics) { + TransformConstraintPose &p = *_appliedPose; + if (p._mixRotate == 0 && p._mixX == 0 && p._mixY == 0 && p._mixScaleX == 0 && p._mixScaleY == 0 && p._mixShearY == 0) return; + + TransformConstraintData &data = _data; + bool localSource = data._localSource, localTarget = data._localTarget, additive = data._additive, clamp = data._clamp; + float *offsets = data._offsets; + BonePose &source = *_source->_appliedPose; + if (localSource) { + source.validateLocalTransform(skeleton); + } + FromProperty **fromItems = data._properties.buffer(); + size_t fn = data._properties.size(); + BonePose **bones = _bones.buffer(); + for (size_t i = 0, n = _bones.size(); i < n; i++) { + BonePose *bone = bones[i]; + if (localTarget) { + bone->modifyLocal(skeleton); + } else { + bone->modifyWorld(skeleton); + } + for (size_t f = 0; f < fn; f++) { + FromProperty *from = fromItems[f]; + float value = from->value(skeleton, source, localSource, offsets) - from->_offset; + Array &toProps = from->_to; + ToProperty **toItems = toProps.buffer(); + for (size_t t = 0, tn = toProps.size(); t < tn; t++) { + ToProperty *to = toItems[t]; + if (to->mix(p) != 0) { + float clamped = to->_offset + value * to->_scale; + if (clamp) { + if (to->_offset < to->_max) + clamped = MathUtil::clamp(clamped, to->_offset, to->_max); + else + clamped = MathUtil::clamp(clamped, to->_max, to->_offset); + } + to->apply(skeleton, p, *bone, clamped, localTarget, additive); + } + } + } + } +} + +void TransformConstraint::sort(Skeleton &skeleton) { + if (!_data._localSource) skeleton.sortBone(_source); + BonePose **bones = _bones.buffer(); + size_t boneCount = _bones.size(); + bool worldTarget = !_data._localTarget; + if (worldTarget) { + for (size_t i = 0; i < boneCount; i++) skeleton.sortBone(bones[i]->_bone); + } + skeleton._updateCache.add(this); + for (size_t i = 0; i < boneCount; i++) { + Bone *bone = bones[i]->_bone; + skeleton.sortReset(bone->_children); + skeleton.constrained(*bone); + } + for (size_t i = 0; i < boneCount; i++) bones[i]->_bone->_sorted = worldTarget; +} + +bool TransformConstraint::isSourceActive() { + return _source->_active; +} + +/// The bones that will be modified by this transform constraint. +Array &TransformConstraint::getBones() { + return _bones; +} + +/// The bone whose world transform will be copied to the constrained bones. +Bone &TransformConstraint::getSource() { + return *_source; +} + +void TransformConstraint::setSource(Bone &source) { + _source = &source; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TransformConstraintData.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TransformConstraintData.cpp new file mode 100644 index 0000000..0611134 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TransformConstraintData.cpp @@ -0,0 +1,363 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +// Define static constants for TransformConstraintData +const int TransformConstraintData::ROTATION = 0; +const int TransformConstraintData::X = 1; +const int TransformConstraintData::Y = 2; +const int TransformConstraintData::SCALEX = 3; +const int TransformConstraintData::SCALEY = 4; +const int TransformConstraintData::SHEARY = 5; + +RTTI_IMPL(TransformConstraintData, ConstraintData) +RTTI_IMPL_NOPARENT(FromProperty) +RTTI_IMPL_NOPARENT(ToProperty) +RTTI_IMPL(FromRotate, FromProperty) +RTTI_IMPL(ToRotate, ToProperty) +RTTI_IMPL(FromX, FromProperty) +RTTI_IMPL(ToX, ToProperty) +RTTI_IMPL(FromY, FromProperty) +RTTI_IMPL(ToY, ToProperty) +RTTI_IMPL(FromScaleX, FromProperty) +RTTI_IMPL(ToScaleX, ToProperty) +RTTI_IMPL(FromScaleY, FromProperty) +RTTI_IMPL(ToScaleY, ToProperty) +RTTI_IMPL(FromShearY, FromProperty) +RTTI_IMPL(ToShearY, ToProperty) + +TransformConstraintData::TransformConstraintData(const String &name) + : ConstraintDataGeneric(name), _source(NULL), _localSource(false), _localTarget(false), + _additive(false), _clamp(false) { + for (int i = 0; i < 6; i++) { + _offsets[i] = 0; + } +} + +Array &TransformConstraintData::getBones() { + return _bones; +} + +BoneData &TransformConstraintData::getSource() { + return *_source; +} + +void TransformConstraintData::setSource(BoneData &source) { + _source = &source; +} + +float TransformConstraintData::getOffsetRotation() { + return _offsets[ROTATION]; +} + +void TransformConstraintData::setOffsetRotation(float offsetRotation) { + _offsets[ROTATION] = offsetRotation; +} + +float TransformConstraintData::getOffsetX() { + return _offsets[X]; +} + +void TransformConstraintData::setOffsetX(float offsetX) { + _offsets[X] = offsetX; +} + +float TransformConstraintData::getOffsetY() { + return _offsets[Y]; +} + +void TransformConstraintData::setOffsetY(float offsetY) { + _offsets[Y] = offsetY; +} + +float TransformConstraintData::getOffsetScaleX() { + return _offsets[SCALEX]; +} + +void TransformConstraintData::setOffsetScaleX(float offsetScaleX) { + _offsets[SCALEX] = offsetScaleX; +} + +float TransformConstraintData::getOffsetScaleY() { + return _offsets[SCALEY]; +} + +void TransformConstraintData::setOffsetScaleY(float offsetScaleY) { + _offsets[SCALEY] = offsetScaleY; +} + +float TransformConstraintData::getOffsetShearY() { + return _offsets[SHEARY]; +} + +void TransformConstraintData::setOffsetShearY(float offsetShearY) { + _offsets[SHEARY] = offsetShearY; +} + +bool TransformConstraintData::getLocalSource() { + return _localSource; +} + +void TransformConstraintData::setLocalSource(bool localSource) { + _localSource = localSource; +} + +bool TransformConstraintData::getLocalTarget() { + return _localTarget; +} + +void TransformConstraintData::setLocalTarget(bool localTarget) { + _localTarget = localTarget; +} + +bool TransformConstraintData::getAdditive() { + return _additive; +} + +void TransformConstraintData::setAdditive(bool additive) { + _additive = additive; +} + +bool TransformConstraintData::getClamp() { + return _clamp; +} + +void TransformConstraintData::setClamp(bool clamp) { + _clamp = clamp; +} + +Array &TransformConstraintData::getProperties() { + return _properties; +} + +FromProperty::FromProperty() : SpineObject(), _offset(0) { +} + +FromProperty::~FromProperty() { +} + +ToProperty::ToProperty() : SpineObject(), _offset(0), _max(0), _scale(1) { +} + +ToProperty::~ToProperty() { +} + +float FromRotate::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) { + if (local) return source._rotation + offsets[TransformConstraintData::ROTATION]; + float sx = skeleton.getScaleX(), sy = skeleton.getScaleY(); + float value = MathUtil::atan2(source._c / sy, source._a / sx) * MathUtil::Rad_Deg + + ((source._a * source._d - source._b * source._c) * sx * sy > 0 ? offsets[TransformConstraintData::ROTATION] + : -offsets[TransformConstraintData::ROTATION]); + if (value < 0) value += 360; + return value; +} + +float ToRotate::mix(TransformConstraintPose &pose) { + return pose._mixRotate; +} + +void ToRotate::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { + if (local) { + bone._rotation += (additive ? value : value - bone._rotation) * pose._mixRotate; + } else { + float sx = skeleton.getScaleX(), sy = skeleton.getScaleY(), ix = 1 / sx, iy = 1 / sy; + float a = bone._a * ix, b = bone._b * ix, c = bone._c * iy, d = bone._d * iy; + value *= MathUtil::Deg_Rad; + if (!additive) value -= MathUtil::atan2(c, a); + if (value > MathUtil::Pi) + value -= MathUtil::Pi_2; + else if (value < -MathUtil::Pi)// + value += MathUtil::Pi_2; + value *= pose._mixRotate; + float cosVal = MathUtil::cos(value), sinVal = MathUtil::sin(value); + bone._a = (cosVal * a - sinVal * c) * sx; + bone._b = (cosVal * b - sinVal * d) * sx; + bone._c = (sinVal * a + cosVal * c) * sy; + bone._d = (sinVal * b + cosVal * d) * sy; + } +} + +float FromX::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) { + return local + ? source._x + offsets[TransformConstraintData::X] + : (offsets[TransformConstraintData::X] * source._a + offsets[TransformConstraintData::Y] * source._b + source._worldX) / skeleton.getScaleX(); +} + +float ToX::mix(TransformConstraintPose &pose) { + return pose._mixX; +} + +void ToX::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { + if (local) { + bone._x += (additive ? value : value - bone._x) * pose._mixX; + } else { + if (!additive) value -= bone._worldX / skeleton.getScaleX(); + bone._worldX += value * pose._mixX * skeleton.getScaleX(); + } +} + +float FromY::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) { + return local + ? source._y + offsets[TransformConstraintData::Y] + : (offsets[TransformConstraintData::X] * source._c + offsets[TransformConstraintData::Y] * source._d + source._worldY) / skeleton.getScaleY(); +} + +float ToY::mix(TransformConstraintPose &pose) { + return pose._mixY; +} + +void ToY::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { + if (local) { + bone._y += (additive ? value : value - bone._y) * pose._mixY; + } else { + if (!additive) value -= bone._worldY / skeleton.getScaleY(); + bone._worldY += value * pose._mixY * skeleton.getScaleY(); + } +} + +float FromScaleX::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) { + if (local) return source._scaleX + offsets[TransformConstraintData::SCALEX]; + float a = source._a / skeleton.getScaleX(), c = source._c / skeleton.getScaleY(); + return MathUtil::sqrt(a * a + c * c) + offsets[TransformConstraintData::SCALEX]; +} + +float ToScaleX::mix(TransformConstraintPose &pose) { + return pose._mixScaleX; +} + +void ToScaleX::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { + if (local) { + if (additive) + bone._scaleX *= 1 + (value - 1) * pose._mixScaleX; + else if (bone._scaleX != 0)// + bone._scaleX += (value - bone._scaleX) * pose._mixScaleX; + } else if (additive) { + float s = 1 + (value - 1) * pose._mixScaleX; + bone._a *= s; + bone._c *= s; + } else { + float a = bone._a / skeleton.getScaleX(), c = bone._c / skeleton.getScaleY(), s = MathUtil::sqrt(a * a + c * c); + if (s != 0) { + s = 1 + (value - s) * pose._mixScaleX / s; + bone._a *= s; + bone._c *= s; + } + } +} + +float FromScaleY::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) { + if (local) return source._scaleY + offsets[TransformConstraintData::SCALEY]; + float b = source._b / skeleton.getScaleX(), d = source._d / skeleton.getScaleY(); + return MathUtil::sqrt(b * b + d * d) + offsets[TransformConstraintData::SCALEY]; +} + +float ToScaleY::mix(TransformConstraintPose &pose) { + return pose._mixScaleY; +} + +void ToScaleY::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { + if (local) { + if (additive) + bone._scaleY *= 1 + (value - 1) * pose._mixScaleY; + else if (bone._scaleY != 0)// + bone._scaleY += (value - bone._scaleY) * pose._mixScaleY; + } else if (additive) { + float s = 1 + (value - 1) * pose._mixScaleY; + bone._b *= s; + bone._d *= s; + } else { + float b = bone._b / skeleton.getScaleX(), d = bone._d / skeleton.getScaleY(), s = MathUtil::sqrt(b * b + d * d); + if (s != 0) { + s = 1 + (value - s) * pose._mixScaleY / s; + bone._b *= s; + bone._d *= s; + } + } +} + +float FromShearY::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) { + if (local) return source._shearY + offsets[TransformConstraintData::SHEARY]; + float ix = 1 / skeleton.getScaleX(), iy = 1 / skeleton.getScaleY(); + return (MathUtil::atan2(source._d * iy, source._b * ix) - MathUtil::atan2(source._c * iy, source._a * ix)) * MathUtil::Rad_Deg - 90 + + offsets[TransformConstraintData::SHEARY]; +} + +float ToShearY::mix(TransformConstraintPose &pose) { + return pose._mixShearY; +} + +void ToShearY::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { + if (local) { + if (!additive) value -= bone._shearY; + bone._shearY += value * pose._mixShearY; + } else { + float sx = skeleton.getScaleX(), sy = skeleton.getScaleY(), b = bone._b / sx, d = bone._d / sy, by = MathUtil::atan2(d, b); + value = (value + 90) * MathUtil::Deg_Rad; + if (additive) + value -= MathUtil::Pi / 2; + else { + value -= by - MathUtil::atan2(bone._c / sy, bone._a / sx); + if (value > MathUtil::Pi) + value -= MathUtil::Pi_2; + else if (value < -MathUtil::Pi)// + value += MathUtil::Pi_2; + } + value = by + value * pose._mixShearY; + float s = MathUtil::sqrt(b * b + d * d); + bone._b = MathUtil::cos(value) * s * sx; + bone._d = MathUtil::sin(value) * s * sy; + } +} + +TransformConstraintData::~TransformConstraintData() { + // Clean up all FromProperty objects, which will in turn clean up their ToProperty objects + for (size_t i = 0; i < _properties.size(); i++) { + FromProperty *fromProp = _properties[i]; + if (fromProp) { + // Clean up the ToProperty objects in the FromProperty + ArrayUtils::deleteElements(fromProp->_to); + delete fromProp; + } + } + _properties.clear(); +} + +Constraint &TransformConstraintData::create(Skeleton &skeleton) { + return *(new (__FILE__, __LINE__) TransformConstraint(*this, skeleton)); +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TransformConstraintPose.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TransformConstraintPose.cpp new file mode 100644 index 0000000..85efe1a --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TransformConstraintPose.cpp @@ -0,0 +1,95 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +TransformConstraintPose::TransformConstraintPose() : _mixRotate(0), _mixX(0), _mixY(0), _mixScaleX(0), _mixScaleY(0), _mixShearY(0) { +} + +TransformConstraintPose::~TransformConstraintPose() { +} + +void TransformConstraintPose::set(TransformConstraintPose &pose) { + _mixRotate = pose._mixRotate; + _mixX = pose._mixX; + _mixY = pose._mixY; + _mixScaleX = pose._mixScaleX; + _mixScaleY = pose._mixScaleY; + _mixShearY = pose._mixShearY; +} + +float TransformConstraintPose::getMixRotate() { + return _mixRotate; +} + +void TransformConstraintPose::setMixRotate(float mixRotate) { + this->_mixRotate = mixRotate; +} + +float TransformConstraintPose::getMixX() { + return _mixX; +} + +void TransformConstraintPose::setMixX(float mixX) { + this->_mixX = mixX; +} + +float TransformConstraintPose::getMixY() { + return _mixY; +} + +void TransformConstraintPose::setMixY(float mixY) { + this->_mixY = mixY; +} + +float TransformConstraintPose::getMixScaleX() { + return _mixScaleX; +} + +void TransformConstraintPose::setMixScaleX(float mixScaleX) { + this->_mixScaleX = mixScaleX; +} + +float TransformConstraintPose::getMixScaleY() { + return _mixScaleY; +} + +void TransformConstraintPose::setMixScaleY(float mixScaleY) { + this->_mixScaleY = mixScaleY; +} + +float TransformConstraintPose::getMixShearY() { + return _mixShearY; +} + +void TransformConstraintPose::setMixShearY(float mixShearY) { + this->_mixShearY = mixShearY; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TransformConstraintTimeline.cpp new file mode 100644 index 0000000..b6a09a3 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -0,0 +1,160 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL_MULTI(TransformConstraintTimeline, CurveTimeline, ConstraintTimeline) + +TransformConstraintTimeline::TransformConstraintTimeline(size_t frameCount, size_t bezierCount, int transformConstraintIndex) + : CurveTimeline(frameCount, TransformConstraintTimeline::ENTRIES, bezierCount), ConstraintTimeline(), _constraintIndex(transformConstraintIndex) { + PropertyId ids[] = {((PropertyId) Property_TransformConstraint << 32) | transformConstraintIndex}; + setPropertyIds(ids, 1); + _additive = true; +} + +TransformConstraintTimeline::~TransformConstraintTimeline() { +} + +void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array *events, float alpha, MixFrom from, bool add, + bool out, bool appliedPose) { + SP_UNUSED(lastTime); + SP_UNUSED(events); + SP_UNUSED(out); + + TransformConstraint *constraint = (TransformConstraint *) skeleton._constraints[_constraintIndex]; + if (!constraint->isActive()) return; + TransformConstraintPose &pose = appliedPose ? *constraint->_appliedPose : constraint->_pose; + + if (time < _frames[0]) { + TransformConstraintPose &setup = constraint->_data._setupPose; + switch (from) { + case MixFrom_Setup: + pose._mixRotate = setup._mixRotate; + pose._mixX = setup._mixX; + pose._mixY = setup._mixY; + pose._mixScaleX = setup._mixScaleX; + pose._mixScaleY = setup._mixScaleY; + pose._mixShearY = setup._mixShearY; + break; + case MixFrom_First: + pose._mixRotate += (setup._mixRotate - pose._mixRotate) * alpha; + pose._mixX += (setup._mixX - pose._mixX) * alpha; + pose._mixY += (setup._mixY - pose._mixY) * alpha; + pose._mixScaleX += (setup._mixScaleX - pose._mixScaleX) * alpha; + pose._mixScaleY += (setup._mixScaleY - pose._mixScaleY) * alpha; + pose._mixShearY += (setup._mixShearY - pose._mixShearY) * alpha; + break; + case MixFrom_Current: + break; + } + return; + } + + float rotate, x, y, scaleX, scaleY, shearY; + int i = Animation::search(_frames, time, ENTRIES); + int curveType = (int) _curves[i / ENTRIES]; + switch (curveType) { + case LINEAR: { + float before = _frames[i]; + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + scaleX = _frames[i + SCALEX]; + scaleY = _frames[i + SCALEY]; + shearY = _frames[i + SHEARY]; + float t = (time - before) / (_frames[i + ENTRIES] - before); + rotate += (_frames[i + ENTRIES + ROTATE] - rotate) * t; + x += (_frames[i + ENTRIES + X] - x) * t; + y += (_frames[i + ENTRIES + Y] - y) * t; + scaleX += (_frames[i + ENTRIES + SCALEX] - scaleX) * t; + scaleY += (_frames[i + ENTRIES + SCALEY] - scaleY) * t; + shearY += (_frames[i + ENTRIES + SHEARY] - shearY) * t; + break; + } + case STEPPED: { + rotate = _frames[i + ROTATE]; + x = _frames[i + X]; + y = _frames[i + Y]; + scaleX = _frames[i + SCALEX]; + scaleY = _frames[i + SCALEY]; + shearY = _frames[i + SHEARY]; + break; + } + default: { + rotate = getBezierValue(time, i, ROTATE, curveType - BEZIER); + x = getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER); + y = getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER); + scaleX = getBezierValue(time, i, SCALEX, curveType + BEZIER_SIZE * 3 - BEZIER); + scaleY = getBezierValue(time, i, SCALEY, curveType + BEZIER_SIZE * 4 - BEZIER); + shearY = getBezierValue(time, i, SHEARY, curveType + BEZIER_SIZE * 5 - BEZIER); + } + } + + TransformConstraintPose &base = from == MixFrom_Setup ? constraint->_data._setupPose : pose; + if (add) { + pose._mixRotate = base._mixRotate + rotate * alpha; + pose._mixX = base._mixX + x * alpha; + pose._mixY = base._mixY + y * alpha; + pose._mixScaleX = base._mixScaleX + scaleX * alpha; + pose._mixScaleY = base._mixScaleY + scaleY * alpha; + pose._mixShearY = base._mixShearY + shearY * alpha; + } else { + pose._mixRotate = base._mixRotate + (rotate - base._mixRotate) * alpha; + pose._mixX = base._mixX + (x - base._mixX) * alpha; + pose._mixY = base._mixY + (y - base._mixY) * alpha; + pose._mixScaleX = base._mixScaleX + (scaleX - base._mixScaleX) * alpha; + pose._mixScaleY = base._mixScaleY + (scaleY - base._mixScaleY) * alpha; + pose._mixShearY = base._mixShearY + (shearY - base._mixShearY) * alpha; + } +} + +void TransformConstraintTimeline::setFrame(int frame, float time, float mixRotate, float mixX, float mixY, float mixScaleX, float mixScaleY, + float mixShearY) { + frame *= ENTRIES; + _frames[frame] = time; + _frames[frame + ROTATE] = mixRotate; + _frames[frame + X] = mixX; + _frames[frame + Y] = mixY; + _frames[frame + SCALEX] = mixScaleX; + _frames[frame + SCALEY] = mixScaleY; + _frames[frame + SHEARY] = mixShearY; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TranslateTimeline.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TranslateTimeline.cpp new file mode 100644 index 0000000..fea071b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/TranslateTimeline.cpp @@ -0,0 +1,123 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(TranslateTimeline, BoneTimeline2) + +TranslateTimeline::TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) + : BoneTimeline2(frameCount, bezierCount, boneIndex, Property_X, Property_Y) { +} + +void TranslateTimeline::_apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) { + SP_UNUSED(out); + if (time < _frames[0]) { + switch (from) { + case MixFrom_Setup: + pose._x = setup._x; + pose._y = setup._y; + break; + case MixFrom_First: + pose._x += (setup._x - pose._x) * alpha; + pose._y += (setup._y - pose._y) * alpha; + break; + case MixFrom_Current: + break; + } + return; + } + + float x, y; + int i = Animation::search(_frames, time, BoneTimeline2::ENTRIES); + int curveType = (int) _curves[i / BoneTimeline2::ENTRIES]; + switch (curveType) { + case CurveTimeline::LINEAR: { + float before = _frames[i]; + x = _frames[i + BoneTimeline2::VALUE1]; + y = _frames[i + BoneTimeline2::VALUE2]; + float t = (time - before) / (_frames[i + BoneTimeline2::ENTRIES] - before); + x += (_frames[i + BoneTimeline2::ENTRIES + BoneTimeline2::VALUE1] - x) * t; + y += (_frames[i + BoneTimeline2::ENTRIES + BoneTimeline2::VALUE2] - y) * t; + break; + } + case CurveTimeline::STEPPED: { + x = _frames[i + BoneTimeline2::VALUE1]; + y = _frames[i + BoneTimeline2::VALUE2]; + break; + } + default: { + x = getBezierValue(time, i, BoneTimeline2::VALUE1, curveType - BoneTimeline2::BEZIER); + y = getBezierValue(time, i, BoneTimeline2::VALUE2, curveType + BoneTimeline2::BEZIER_SIZE - BoneTimeline2::BEZIER); + } + } + + if (from == MixFrom_Setup) { + pose._x = setup._x + x * alpha; + pose._y = setup._y + y * alpha; + } else if (add) { + pose._x += x * alpha; + pose._y += y * alpha; + } else { + pose._x += (setup._x + x - pose._x) * alpha; + pose._y += (setup._y + y - pose._y) * alpha; + } +} + +RTTI_IMPL(TranslateXTimeline, BoneTimeline1) + +TranslateXTimeline::TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) + : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_X) { +} + +void TranslateXTimeline::_apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) { + SP_UNUSED(out); + pose._x = getRelativeValue(time, alpha, from, add, pose._x, setup._x); +} + +RTTI_IMPL(TranslateYTimeline, BoneTimeline1) + +TranslateYTimeline::TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) + : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Y) { +} + +void TranslateYTimeline::_apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) { + SP_UNUSED(out); + pose._y = getRelativeValue(time, alpha, from, add, pose._y, setup._y); +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Triangulator.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Triangulator.cpp new file mode 100644 index 0000000..3a38c44 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Triangulator.cpp @@ -0,0 +1,258 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +using namespace spine; + +Triangulator::~Triangulator() { + ArrayUtils::deleteElements(_convexPolygons); + ArrayUtils::deleteElements(_convexPolygonsIndices); +} + +Array &Triangulator::triangulate(Array &verticesArray) { + float *vertices = verticesArray.buffer(); + int vertexCount = (int) (verticesArray.size() >> 1); + + Array &indicesArray = _indices; + indicesArray.clear(); + int *indices = indicesArray.setSize(vertexCount, 0).buffer(); + for (int i = 0; i < vertexCount; i++) indices[i] = i; + + Array &isConcaveArray = _isConcaveArray; + bool *isConcaveItems = isConcaveArray.setSize(vertexCount, false).buffer(); + for (int i = 0; i < vertexCount; i++) isConcaveItems[i] = isConcave(i, vertexCount, vertices, indices); + + Array &triangles = _triangles; + triangles.clear(); + triangles.ensureCapacity(MathUtil::max(0, vertexCount - 2) * 3); + + while (vertexCount > 3) { + int previous = vertexCount - 1, i = 0, next = 1; + while (true) { + if (!isConcaveItems[i]) { + int p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + float p1x = vertices[p1], p1y = vertices[p1 + 1]; + float p2x = vertices[p2], p2y = vertices[p2 + 1]; + float p3x = vertices[p3], p3y = vertices[p3 + 1]; + bool ear = true; + for (int ii = next + 1 < vertexCount ? next + 1 : 0; ii != previous;) { + if (isConcaveItems[ii]) { + int v = indices[ii] << 1; + float vx = vertices[v], vy = vertices[v + 1]; + if (positiveArea(p3x, p3y, p1x, p1y, vx, vy) && positiveArea(p1x, p1y, p2x, p2y, vx, vy) && + positiveArea(p2x, p2y, p3x, p3y, vx, vy)) { + ear = false; + break; + } + } + if (++ii == vertexCount) ii = 0; + } + if (ear) break; + } + + if (next == 0) { + do { + if (!isConcaveItems[i]) break; + i--; + } while (i > 0); + previous = i > 0 ? i - 1 : vertexCount - 1; + next = i + 1 < vertexCount ? i + 1 : 0; + break; + } + + previous = i; + i = next; + if (++next == vertexCount) next = 0; + } + + triangles.add(indices[previous]); + triangles.add(indices[i]); + triangles.add(indices[next]); + indicesArray.removeAt(i); + isConcaveArray.removeAt(i); + vertexCount--; + indices = indicesArray.buffer(); + isConcaveItems = isConcaveArray.buffer(); + + int previousIndex = i > 0 ? i - 1 : vertexCount - 1; + int nextIndex = i < vertexCount ? i : 0; + isConcaveItems[previousIndex] = isConcave(previousIndex, vertexCount, vertices, indices); + isConcaveItems[nextIndex] = isConcave(nextIndex, vertexCount, vertices, indices); + } + if (vertexCount == 3) { + triangles.add(indices[2]); + triangles.add(indices[0]); + triangles.add(indices[1]); + } + return triangles; +} + +Array *> &Triangulator::decompose(Array &verticesArray, Array &triangles) { + float *vertices = verticesArray.buffer(); + + Array *> &convexPolygons = _convexPolygons; + for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) _polygonPool.free(convexPolygons[i]); + convexPolygons.clear(); + + Array *> &convexPolygonsIndices = _convexPolygonsIndices; + for (size_t i = 0, n = convexPolygonsIndices.size(); i < n; ++i) _polygonIndicesPool.free(convexPolygonsIndices[i]); + convexPolygonsIndices.clear(); + + Array *polygonIndices = _polygonIndicesPool.obtain(); + polygonIndices->clear(); + + Array *polygon = _polygonPool.obtain(); + polygon->clear(); + + int fanBaseIndex = -1, lastWinding = 0; + int *trianglesItems = triangles.buffer(); + for (int i = 0, n = (int) triangles.size(); i < n; i += 3) { + int t1 = trianglesItems[i] << 1, t2 = trianglesItems[i + 1] << 1, t3 = trianglesItems[i + 2] << 1; + float x1 = vertices[t1], y1 = vertices[t1 + 1]; + float x2 = vertices[t2], y2 = vertices[t2 + 1]; + float x3 = vertices[t3], y3 = vertices[t3 + 1]; + + if (fanBaseIndex == t1) { + int o = (int) polygon->size() - 4; + float *p = polygon->buffer(); + if (winding(p[o], p[o + 1], p[o + 2], p[o + 3], x3, y3) == lastWinding && winding(x3, y3, p[0], p[1], p[2], p[3]) == lastWinding) { + polygon->add(x3); + polygon->add(y3); + polygonIndices->add(t3); + continue; + } + } + + if (polygon->size() > 0) { + convexPolygons.add(polygon); + convexPolygonsIndices.add(polygonIndices); + polygon = _polygonPool.obtain(); + polygonIndices = _polygonIndicesPool.obtain(); + } + polygon->clear(); + polygon->add(x1); + polygon->add(y1); + polygon->add(x2); + polygon->add(y2); + polygon->add(x3); + polygon->add(y3); + polygonIndices->clear(); + polygonIndices->add(t1); + polygonIndices->add(t2); + polygonIndices->add(t3); + lastWinding = winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + + if (polygon->size() > 0) { + convexPolygons.add(polygon); + convexPolygonsIndices.add(polygonIndices); + } + + Array **convexPolygonsIndicesItems = convexPolygonsIndices.buffer(); + Array **convexPolygonsItems = convexPolygons.buffer(); + for (int i = 0, n = (int) convexPolygons.size(); i < n; i++) { + polygonIndices = convexPolygonsIndicesItems[i]; + if (polygonIndices->size() == 0) continue; + int firstIndex = (*polygonIndices)[0]; + int lastIndex = (*polygonIndices)[polygonIndices->size() - 1]; + + polygon = convexPolygonsItems[i]; + int o = (int) polygon->size() - 4; + float *p = polygon->buffer(); + float prevPrevX = p[o], prevPrevY = p[o + 1]; + float prevX = p[o + 2], prevY = p[o + 3]; + float firstX = p[0], firstY = p[1]; + float secondX = p[2], secondY = p[3]; + int polygonWinding = winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + + for (int ii = 0; ii < n; ii++) { + if (ii == i) continue; + Array *otherIndices = convexPolygonsIndicesItems[ii]; + if (otherIndices->size() != 3) continue; + int otherFirstIndex = (*otherIndices)[0]; + int otherSecondIndex = (*otherIndices)[1]; + int otherLastIndex = (*otherIndices)[2]; + + Array *otherPoly = convexPolygonsItems[ii]; + float x3 = (*otherPoly)[otherPoly->size() - 2], y3 = (*otherPoly)[otherPoly->size() - 1]; + + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue; + if (winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3) == polygonWinding && + winding(x3, y3, firstX, firstY, secondX, secondY) == polygonWinding) { + otherPoly->clear(); + otherIndices->clear(); + polygon->add(x3); + polygon->add(y3); + polygonIndices->add(otherLastIndex); + lastIndex = otherLastIndex; + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = -1; + } + } + } + + for (int i = (int) convexPolygons.size() - 1; i >= 0; --i) { + polygon = convexPolygonsItems[i]; + if (polygon->size() == 0) { + convexPolygons.removeAt(i); + _polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.removeAt(i); + _polygonIndicesPool.free(polygonIndices); + } else { + polygon->add((*polygon)[0]); + polygon->add((*polygon)[1]); + } + } + + return convexPolygons; +} + +bool Triangulator::isConcave(int index, int vertexCount, const float *vertices, const int *indices) { + int previous = indices[index > 0 ? index - 1 : vertexCount - 1] << 1; + int current = indices[index] << 1; + int next = indices[index + 1 < vertexCount ? index + 1 : 0] << 1; + + return !positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]); +} + +bool Triangulator::positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; +} + +int Triangulator::winding(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0 ? 1 : -1; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Update.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Update.cpp new file mode 100644 index 0000000..81ee025 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/Update.cpp @@ -0,0 +1,40 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +using namespace spine; + +RTTI_IMPL_NOPARENT(Update) + +Update::Update() { +} + +Update::~Update() { +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/VertexAttachment.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/VertexAttachment.cpp new file mode 100644 index 0000000..af9526b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/src/spine/VertexAttachment.cpp @@ -0,0 +1,167 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +#include +#include + +using namespace spine; + +RTTI_IMPL(VertexAttachment, Attachment) + +VertexAttachment::VertexAttachment(const String &name) : Attachment(name), _worldVerticesLength(0), _id(getNextID()) { +} + +VertexAttachment::~VertexAttachment() { +} + + +void VertexAttachment::computeWorldVertices(Skeleton &skeleton, Slot &slot, size_t start, size_t count, Array &worldVertices, size_t offset, + size_t stride) { + computeWorldVertices(skeleton, slot, start, count, worldVertices.buffer(), offset, stride); +} + +void VertexAttachment::computeWorldVertices(Skeleton &skeleton, Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset, + size_t stride) { + count = offset + (count >> 1) * stride; + Array *deformArray = &slot.getAppliedPose().getDeform(); + Array *vertices = &_vertices; + Array &bones = _bones; + if (bones.size() == 0) { + if (deformArray->size() > 0) vertices = deformArray; + + BonePose &bone = slot.getBone().getAppliedPose(); + float x = bone.getWorldX(); + float y = bone.getWorldY(); + float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD(); + for (size_t vv = start, w = offset; w < count; vv += 2, w += stride) { + float vx = (*vertices)[vv]; + float vy = (*vertices)[vv + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + + int v = 0, skip = 0; + for (size_t i = 0; i < start; i += 2) { + int n = (int) bones[v]; + v += n + 1; + skip += n; + } + + Array &skeletonBones = skeleton.getBones(); + if (deformArray->size() == 0) { + for (size_t w = offset, b = skip * 3; w < count; w += stride) { + float wx = 0, wy = 0; + int n = (int) bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + Bone *boneP = skeletonBones[bones[v]]; + BonePose &bonePose = boneP->getAppliedPose(); + float vx = (*vertices)[b]; + float vy = (*vertices)[b + 1]; + float weight = (*vertices)[b + 2]; + wx += (vx * bonePose.getA() + vy * bonePose.getB() + bonePose.getWorldX()) * weight; + wy += (vx * bonePose.getC() + vy * bonePose.getD() + bonePose.getWorldY()) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } else { + for (size_t w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + float wx = 0, wy = 0; + int n = (int) bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + Bone *boneP = skeletonBones[bones[v]]; + BonePose &bonePose = boneP->getAppliedPose(); + float vx = (*vertices)[b] + (*deformArray)[f]; + float vy = (*vertices)[b + 1] + (*deformArray)[f + 1]; + float weight = (*vertices)[b + 2]; + wx += (vx * bonePose.getA() + vy * bonePose.getB() + bonePose.getWorldX()) * weight; + wy += (vx * bonePose.getC() + vy * bonePose.getD() + bonePose.getWorldY()) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } +} + +int VertexAttachment::getId() { + return _id; +} + +Array &VertexAttachment::getBones() { + return _bones; +} + +void VertexAttachment::setBones(Array &bones) { + _bones.clearAndAddAll(bones); +} + +Array &VertexAttachment::getVertices() { + return _vertices; +} + +void VertexAttachment::setVertices(Array &vertices) { + _vertices.clearAndAddAll(vertices); +} + +size_t VertexAttachment::getWorldVerticesLength() { + return _worldVerticesLength; +} + +void VertexAttachment::setWorldVerticesLength(size_t inValue) { + _worldVerticesLength = inValue; +} + +Attachment *VertexAttachment::getTimelineAttachment() { + return Attachment::getTimelineAttachment(); +} + +void VertexAttachment::setTimelineAttachment(Attachment *attachment) { + Attachment::setTimelineAttachment(attachment); +} + +int VertexAttachment::getNextID() { + static int nextID = 0; + return nextID++; +} + +void VertexAttachment::copyTo(VertexAttachment &other) { + other._bones.clearAndAddAll(this->_bones); + other._vertices.clearAndAddAll(this->_vertices); + other._worldVerticesLength = this->_worldVerticesLength; + other.setTimelineAttachment(this->getTimelineAttachment()); + other.setTimelineSlots(this->getTimelineSlots()); +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/HeadlessTest.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/HeadlessTest.cpp new file mode 100644 index 0000000..ff7ea15 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/HeadlessTest.cpp @@ -0,0 +1,303 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include "SkeletonSerializer.h" +#include +#include +#include +#include +#include +#include + +static void printBonePoseJson(spine::BonePose &pose) { + printf("{"); + printf("\"x\":%.6f,\"y\":%.6f,\"rotation\":%.6f,\"scaleX\":%.6f,\"scaleY\":%.6f,\"shearX\":%.6f,\"shearY\":%.6f,", pose.getX(), pose.getY(), + pose.getRotation(), pose.getScaleX(), pose.getScaleY(), pose.getShearX(), pose.getShearY()); + printf("\"a\":%.6f,\"b\":%.6f,\"c\":%.6f,\"d\":%.6f,", pose.getA(), pose.getB(), pose.getC(), pose.getD()); + printf("\"worldX\":%.6f,\"worldY\":%.6f,\"worldRotationX\":%.6f,\"worldRotationY\":%.6f,\"worldScaleX\":%.6f,\"worldScaleY\":%.6f", + pose.getWorldX(), pose.getWorldY(), pose.getWorldRotationX(), pose.getWorldRotationY(), pose.getWorldScaleX(), pose.getWorldScaleY()); + printf("}"); +} + +static void printSlotPoseJson(spine::SlotPose &pose) { + printf("{"); + printf("\"attachment\":"); + spine::Attachment *attachment = pose.getAttachment(); + if (attachment) + printf("\"%s\"", attachment->getName().buffer()); + else + printf("null"); + printf(",\"sequenceIndex\":%d,", pose.getSequenceIndex()); + spine::Color &color = pose.getColor(); + printf("\"color\":{\"r\":%.6f,\"g\":%.6f,\"b\":%.6f,\"a\":%.6f}", color.r, color.g, color.b, color.a); + printf("}"); +} + +static void printSkeletonFrameJson(spine::Skeleton &skeleton, int frame) { + printf("\n=== ANIMATION FRAME %d ===\n", frame); + printf("{"); + printf("\"frame\":%d,", frame); + printf("\"time\":%.6f,", skeleton.getTime()); + printf("\"bones\":["); + spine::Array &bones = skeleton.getBones(); + for (size_t i = 0; i < bones.size(); i++) { + if (i) printf(","); + spine::Bone *bone = bones[i]; + printf("{"); + printf("\"name\":\"%s\",", bone->getData().getName().buffer()); + printf("\"pose\":"); + printBonePoseJson(bone->getPose()); + printf(",\"appliedPose\":"); + printBonePoseJson(bone->getAppliedPose()); + printf("}"); + } + printf("],\"slots\":["); + spine::Array &slots = skeleton.getSlots(); + for (size_t i = 0; i < slots.size(); i++) { + if (i) printf(","); + spine::Slot *slot = slots[i]; + printf("{"); + printf("\"name\":\"%s\",", slot->getData().getName().buffer()); + printf("\"pose\":"); + printSlotPoseJson(slot->getPose()); + printf(",\"appliedPose\":"); + printSlotPoseJson(slot->getAppliedPose()); + printf("}"); + } + printf("]}"); +} + +using namespace spine; + +// Provide the default extension implementation +namespace spine { + SpineExtension *getDefaultExtension() { + return new DefaultSpineExtension(); + } +}// namespace spine + +// Mock texture that doesn't require OpenGL +class MockTexture { +public: + int width = 1024; + int height = 1024; +}; + +// Custom texture loader that doesn't load actual textures +class HeadlessTextureLoader : public TextureLoader { +public: + virtual void load(AtlasPage &page, const String &path) override { + // Don't load actual texture, just set dimensions + page.texture = new MockTexture(); + page.width = 1024; + page.height = 1024; + } + + virtual void unload(void *texture) override { + delete static_cast(texture); + } +}; + +static bool testInheritTimelineBoneIndex() { + InheritTimeline timeline(1, 123); + if (timeline.getBoneIndex() != 123) { + fprintf(stderr, "InheritTimeline bone index was not initialized correctly\n"); + return false; + } + return true; +} + +int main(int argc, char *argv[]) { + // Set locale to ensure consistent number formatting + setlocale(LC_ALL, "C"); + + if (!testInheritTimelineBoneIndex()) return 1; + + if (argc < 3) { + fprintf(stderr, "Usage: HeadlessTest [animation-name] [animation-name-2]\n"); + return 1; + } + + Bone::setYDown(false); + + const char *skeletonPath = argv[1]; + const char *atlasPath = argv[2]; + const char *animationName = argc >= 4 ? argv[3] : nullptr; + const char *animationName2 = argc >= 5 ? argv[4] : nullptr; + + // Load atlas with headless texture loader + HeadlessTextureLoader textureLoader; + Atlas *atlas = new Atlas(atlasPath, &textureLoader); + + // Load skeleton data + SkeletonData *skeletonData = nullptr; + + if (strstr(skeletonPath, ".json") != nullptr) { + SkeletonJson json(*atlas); + skeletonData = json.readSkeletonDataFile(skeletonPath); + } else { + SkeletonBinary binary(*atlas); + skeletonData = binary.readSkeletonDataFile(skeletonPath); + } + + if (!skeletonData) { + fprintf(stderr, "Failed to load skeleton data\n"); + delete atlas; + return 1; + } + + // Create skeleton instance + Skeleton skeleton(*skeletonData); + + // Set animation if provided + AnimationState *state = nullptr; + AnimationStateData *stateData = nullptr; + if (animationName != nullptr) { + // Create animation state only when needed + stateData = new AnimationStateData(*skeletonData); + state = new AnimationState(*stateData); + + // Find and set animation + Animation *animation = skeletonData->findAnimation(animationName); + if (!animation) { + fprintf(stderr, "Animation not found: %s\n", animationName); + delete skeletonData; + delete atlas; + return 1; + } + state->setAnimation(0, *animation, true); + // Update and apply + state->update(0.016f); + state->apply(skeleton); + } + + skeleton.updateWorldTransform(Physics_Update); + + // Use SkeletonSerializer for JSON output + SkeletonSerializer serializer; + + // Print skeleton data + printf("=== SKELETON DATA ===\n"); + printf("%s", serializer.serializeSkeletonData(skeletonData).buffer()); + + // Print skeleton state + printf("\n=== SKELETON STATE ===\n"); + printf("%s", serializer.serializeSkeleton(&skeleton).buffer()); + + // Print animation state only if animation was loaded + if (state != nullptr) { + printf("\n=== ANIMATION STATE ===\n"); + printf("%s", serializer.serializeAnimationState(state).buffer()); + } + + // Full animation sampling: if a single animation is provided, sample skeleton state for every + // frame across the full non-looping animation duration at 60 FPS. + if (state != nullptr && animationName2 == nullptr) { + Animation *animation = skeletonData->findAnimation(animationName); + if (!animation) { + fprintf(stderr, "Animation not found: %s\n", animationName); + delete state; + delete stateData; + delete skeletonData; + delete atlas; + return 1; + } + + skeleton.setupPose(); + state->clearTracks(); + state->setAnimation(0, *animation, false); + state->apply(skeleton); + skeleton.updateWorldTransform(Physics_Update); + + int frameCount = (int) ceilf(animation->getDuration() * 60.0f); + for (int i = 0; i <= frameCount; i++) { + if (i > 0) { + state->update(1 / 60.0f); + state->apply(skeleton); + skeleton.updateWorldTransform(Physics_Update); + } + printSkeletonFrameJson(skeleton, i); + } + } + + // Transition test: if a second animation is provided, play A for 10 frames, transition to B, + // then sample skeleton state at frames 5, 10, 15, 20 during the mix. + if (state != nullptr && animationName2 != nullptr) { + Animation *animation2 = skeletonData->findAnimation(animationName2); + if (!animation2) { + fprintf(stderr, "Animation not found: %s\n", animationName2); + delete state; + delete stateData; + delete skeletonData; + delete atlas; + return 1; + } + + // Reset skeleton and state + skeleton.setupPose(); + state->clearTracks(); + state->setAnimation(0, *skeletonData->findAnimation(animationName), true); + + // Run 10 frames of animation A + for (int i = 0; i < 10; i++) { + state->update(1 / 60.0f); + state->apply(skeleton); + skeleton.updateWorldTransform(Physics_Update); + } + + // Transition to animation B + state->setAnimation(0, *animation2, true); + + // Run 20 frames through the mix, serializing at frames 5, 10, 15, 20 + for (int i = 1; i <= 20; i++) { + state->update(1 / 60.0f); + state->apply(skeleton); + skeleton.updateWorldTransform(Physics_Update); + if (i == 5 || i == 10 || i == 15 || i == 20) { + SkeletonSerializer transSerializer; + printf("\n=== TRANSITION FRAME %d ===\n", i); + printf("%s", transSerializer.serializeSkeleton(&skeleton).buffer()); + } + } + } + + // Cleanup + if (state != nullptr) { + delete state; + } + if (stateData != nullptr) { + delete stateData; + } + delete skeletonData; + delete atlas; + + return 0; +} \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/JsonWriter.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/JsonWriter.h new file mode 100644 index 0000000..8044e02 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/JsonWriter.h @@ -0,0 +1,205 @@ +#ifndef Spine_JsonWriter_h +#define Spine_JsonWriter_h + +#include +#include + +namespace spine { + + class JsonWriter { + private: + String buffer; + int depth; + bool needsComma; + + public: + JsonWriter() : depth(0), needsComma(false) { + } + + void writeObjectStart() { + writeCommaIfNeeded(); + buffer.append("{"); + depth++; + needsComma = false; + } + + void writeObjectEnd() { + depth--; + if (needsComma) { + buffer.append("\n"); + writeIndent(); + } + buffer.append("}"); + needsComma = true; + } + + void writeArrayStart() { + writeCommaIfNeeded(); + buffer.append("["); + depth++; + needsComma = false; + } + + void writeArrayEnd() { + depth--; + if (needsComma) { + buffer.append("\n"); + writeIndent(); + } + buffer.append("]"); + needsComma = true; + } + + void writeName(const char *name) { + writeCommaIfNeeded(); + buffer.append("\n"); + writeIndent(); + buffer.append("\""); + buffer.append(name); + buffer.append("\": "); + needsComma = false; + } + + void writeValue(const String &value) { + writeCommaIfNeeded(); + if (value.buffer() == nullptr) { + buffer.append("null"); + } else { + buffer.append("\""); + buffer.append(escapeString(value)); + buffer.append("\""); + } + needsComma = true; + } + + void writeValue(const char *value) { + writeCommaIfNeeded(); + if (value == nullptr) { + buffer.append("null"); + } else { + buffer.append("\""); + buffer.append(escapeString(String(value))); + buffer.append("\""); + } + needsComma = true; + } + + void writeValue(float value) { + writeCommaIfNeeded(); + + // Format float with 6 decimal places + char temp[32]; + snprintf(temp, sizeof(temp), "%.6f", value); + + // Remove trailing zeros + char *end = temp + strlen(temp) - 1; + while (end > temp && *end == '0') { + end--; + } + if (*end == '.') { + end--; + } + *(end + 1) = '\0'; + + buffer.append(temp); + needsComma = true; + } + + void writeValue(int value) { + writeCommaIfNeeded(); + char temp[32]; + snprintf(temp, sizeof(temp), "%d", value); + buffer.append(temp); + needsComma = true; + } + + void writeValue(bool value) { + writeCommaIfNeeded(); + buffer.append(value ? "true" : "false"); + needsComma = true; + } + + void writeValue(size_t value) { + writeCommaIfNeeded(); + char temp[32]; + snprintf(temp, sizeof(temp), "%zu", value); + buffer.append(temp); + needsComma = true; + } + + void writeValue(PropertyId value) { + writeCommaIfNeeded(); + char temp[32]; + snprintf(temp, sizeof(temp), "%lld", (long long) value); + buffer.append(temp); + needsComma = true; + } + + void writeNull() { + writeCommaIfNeeded(); + buffer.append("null"); + needsComma = true; + } + + void close() { + buffer.append("\n"); + } + + String getString() const { + return buffer; + } + + private: + void writeCommaIfNeeded() { + if (needsComma) { + buffer.append(","); + } + } + + void writeIndent() { + for (int i = 0; i < depth; i++) { + buffer.append(" "); + } + } + + String escapeString(const String &str) { + String result(""); + const char *chars = str.buffer(); + if (chars) { + for (size_t i = 0; i < str.length(); i++) { + char c = chars[i]; + switch (c) { + case '"': + result.append("\\\""); + break; + case '\\': + result.append("\\\\"); + break; + case '\b': + result.append("\\b"); + break; + case '\f': + result.append("\\f"); + break; + case '\n': + result.append("\\n"); + break; + case '\r': + result.append("\\r"); + break; + case '\t': + result.append("\\t"); + break; + default: + result.append(c); + break; + } + } + } + return result; + } + }; + +}// namespace spine + +#endif \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/MapTest.cpp b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/MapTest.cpp new file mode 100644 index 0000000..ad3f223 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/MapTest.cpp @@ -0,0 +1,296 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + *****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace spine; + +namespace spine { + SpineExtension *getDefaultExtension() { + return new DefaultSpineExtension(); + } +} + +class TrackingExtension : public SpineExtension { +public: + TrackingExtension() : SpineExtension() { + } + + size_t activeAllocations() const { + return _allocations.size(); + } + + size_t activeBytes() const { + size_t total = 0; + for (std::unordered_map::const_iterator i = _allocations.begin(); i != _allocations.end(); ++i) total += i->second; + return total; + } + +protected: + virtual void *_alloc(size_t size, const char *file, int line) override { + SP_UNUSED(file); + SP_UNUSED(line); + if (size == 0) return NULL; + void *ptr = malloc(size); + assert(ptr); + _allocations[ptr] = size; + return ptr; + } + + virtual void *_calloc(size_t size, const char *file, int line) override { + void *ptr = _alloc(size, file, line); + if (ptr) memset(ptr, 0, size); + return ptr; + } + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) override { + SP_UNUSED(file); + SP_UNUSED(line); + if (ptr == NULL) return _alloc(size, file, line); + std::unordered_map::iterator existing = _allocations.find(ptr); + assert(existing != _allocations.end()); + _allocations.erase(existing); + if (size == 0) { + ::free(ptr); + return NULL; + } + void *newPtr = ::realloc(ptr, size); + assert(newPtr); + _allocations[newPtr] = size; + return newPtr; + } + + virtual void _free(void *mem, const char *file, int line) override { + SP_UNUSED(file); + SP_UNUSED(line); + if (!mem) return; + std::unordered_map::iterator existing = _allocations.find(mem); + assert(existing != _allocations.end()); + _allocations.erase(existing); + ::free(mem); + } + + virtual char *_readFile(const String &path, int *length) override { + SP_UNUSED(path); + SP_UNUSED(length); + return NULL; + } + +private: + std::unordered_map _allocations; +}; + +static int failures = 0; + +#define CHECK(condition) \ + do { \ + if (!(condition)) { \ + fprintf(stderr, "CHECK failed at %s:%d: %s\n", __FILE__, __LINE__, #condition); \ + failures++; \ + } \ + } while (false) + +class BadIntHash { +public: + size_t operator()(const int &key) const { + return (size_t) (key & 7); + } +}; + +static String makeString(const char *prefix, int value) { + char buffer[64]; + snprintf(buffer, sizeof(buffer), "%s%d", prefix, value); + return String(buffer); +} + +static void testBasicOperations() { + Map map; + CHECK(map.isEmpty()); + CHECK(map.size() == 0); + CHECK(map.get(123) == NULL); + CHECK(!map.containsKey(123)); + CHECK(!map.remove(123)); + + for (int i = 0; i < 1000; i++) map.put(i, i * 3); + CHECK(map.size() == 1000); + for (int i = 0; i < 1000; i++) { + int *value = map.get(i); + CHECK(value && *value == i * 3); + CHECK(map.containsKey(i)); + } + + for (int i = 0; i < 1000; i += 3) map.put(i, -i); + CHECK(map.size() == 1000); + for (int i = 0; i < 1000; i++) { + int expected = i % 3 == 0 ? -i : i * 3; + CHECK(map[i] == expected); + } + + for (int i = 0; i < 1000; i += 2) CHECK(map.remove(i)); + CHECK(map.size() == 500); + for (int i = 0; i < 1000; i++) { + int *value = map.get(i); + if (i % 2 == 0) + CHECK(value == NULL); + else + CHECK(value && *value == (i % 3 == 0 ? -i : i * 3)); + } + + for (int i = 0; i < 1000; i += 2) map.put(i, i + 7); + CHECK(map.size() == 1000); + for (int i = 0; i < 1000; i++) { + int expected = i % 2 == 0 ? i + 7 : (i % 3 == 0 ? -i : i * 3); + CHECK(map[i] == expected); + } +} + +static void testEntriesAndAddAll() { + Map map; + Array keys; + for (int i = 0; i < 100; i++) keys.add(i); + CHECK(map.addAll(keys, 42)); + CHECK(!map.addAll(keys, 42)); + CHECK(map.size() == 100); + + int count = 0; + int sum = 0; + Map::Entries entries = map.getEntries(); + while (entries.hasNext()) { + Map::Pair pair = entries.next(); + CHECK(pair.value == 42); + count++; + sum += pair.key; + } + CHECK(count == 100); + CHECK(sum == 4950); +} + +static void testPutMissing() { + int a = 1, b = 2; + Map map; + CHECK(map.putMissing(5, &a) == NULL); + CHECK(map.size() == 1); + CHECK(map.putMissing(5, &b) == &a); + CHECK(map.size() == 1); + CHECK(*map.get(5) == &a); +} + +static void testCopyAndAssignment() { + Map original; + original.put(1, String("one")); + original.put(2, String("two")); + + Map copy(original); + copy.put(1, String("changed")); + CHECK(*original.get(1) == String("one")); + CHECK(*copy.get(1) == String("changed")); + CHECK(*copy.get(2) == String("two")); + + Map assigned; + assigned.put(99, String("discard")); + assigned = original; + CHECK(assigned.get(99) == NULL); + CHECK(*assigned.get(1) == String("one")); + CHECK(*assigned.get(2) == String("two")); +} + +static void testStringMemory(TrackingExtension &extension) { + size_t baselineAllocations = extension.activeAllocations(); + { + Map map; + map.ensureCapacity(64); + size_t mapOnlyAllocations = extension.activeAllocations(); + CHECK(mapOnlyAllocations > baselineAllocations); + + for (int i = 0; i < 200; i++) map.put(makeString("key", i), makeString("value", i)); + CHECK(map.size() == 200); + CHECK(extension.activeAllocations() > mapOnlyAllocations); + + for (int i = 0; i < 100; i++) CHECK(map.remove(makeString("key", i))); + CHECK(map.size() == 100); + for (int i = 100; i < 200; i++) CHECK(*map.get(makeString("key", i)) == makeString("value", i)); + + map.clear(); + CHECK(map.size() == 0); + CHECK(extension.activeAllocations() == mapOnlyAllocations); + } + CHECK(extension.activeAllocations() == baselineAllocations); +} + +static void testStress() { + Map map; + bool present[257]; + int values[257]; + for (int i = 0; i < 257; i++) { + present[i] = false; + values[i] = 0; + } + + unsigned int seed = 0x12345678u; + for (int step = 0; step < 10000; step++) { + seed = seed * 1103515245u + 12345u; + int key = (int) ((seed >> 8) % 257); + int op = (int) ((seed >> 24) % 3); + if (op == 0) { + bool removed = map.remove(key); + CHECK(removed == present[key]); + present[key] = false; + } else { + int value = (int) seed; + map.put(key, value); + present[key] = true; + values[key] = value; + } + + if ((step & 127) == 0) { + size_t expectedSize = 0; + for (int i = 0; i < 257; i++) { + if (present[i]) { + expectedSize++; + CHECK(map.get(i) && *map.get(i) == values[i]); + } else + CHECK(map.get(i) == NULL); + } + CHECK(map.size() == expectedSize); + } + } +} + +int main() { + TrackingExtension extension; + SpineExtension::setInstance(&extension); + + size_t baselineAllocations = extension.activeAllocations(); + testBasicOperations(); + CHECK(extension.activeAllocations() == baselineAllocations); + testEntriesAndAddAll(); + CHECK(extension.activeAllocations() == baselineAllocations); + testPutMissing(); + CHECK(extension.activeAllocations() == baselineAllocations); + testCopyAndAssignment(); + CHECK(extension.activeAllocations() == baselineAllocations); + testStringMemory(extension); + CHECK(extension.activeAllocations() == baselineAllocations); + testStress(); + CHECK(extension.activeAllocations() == baselineAllocations); + + if (failures) { + fprintf(stderr, "MapTest failed: %d failure(s), %zu active allocation(s), %zu active byte(s)\n", failures, extension.activeAllocations(), + extension.activeBytes()); + return 1; + } + printf("MapTest passed\n"); + return 0; +} diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/SkeletonSerializer.h b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/SkeletonSerializer.h new file mode 100644 index 0000000..8a302de --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/SkeletonSerializer.h @@ -0,0 +1,4768 @@ +#ifndef Spine_SkeletonSerializer_h +#define Spine_SkeletonSerializer_h + +#include +#include "JsonWriter.h" +#include +#include + +namespace spine { + + class SkeletonSerializer { + private: + HashMap _visitedObjects; + HashMap _visitedSkinEntries; + int _nextId; + JsonWriter _json; + + public: + SkeletonSerializer() { + } + ~SkeletonSerializer() { + } + + String serializeSkeletonData(SkeletonData *data) { + _visitedObjects.clear(); + _visitedSkinEntries.clear(); + _nextId = 1; + _json = JsonWriter(); + writeSkeletonData(data); + return _json.getString(); + } + + String serializeSkeleton(Skeleton *skeleton) { + _visitedObjects.clear(); + _visitedSkinEntries.clear(); + _nextId = 1; + _json = JsonWriter(); + writeSkeleton(skeleton); + return _json.getString(); + } + + String serializeAnimationState(AnimationState *state) { + _visitedObjects.clear(); + _visitedSkinEntries.clear(); + _nextId = 1; + _json = JsonWriter(); + writeAnimationState(state); + return _json.getString(); + } + + private: + void writeAnimation(Animation *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("Animation"); + + _json.writeName("timelines"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getTimelines().size(); i++) { + writeTimeline(obj->getTimelines()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeName("color"); + writeColor(&obj->getColor()); + + _json.writeName("bones"); + writeIntArray(obj->getBones()); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeObjectEnd(); + } + + void writeAlphaTimeline(AlphaTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("AlphaTimeline"); + + _json.writeName("slotIndex"); + _json.writeValue(obj->getSlotIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeAttachmentTimeline(AttachmentTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("AttachmentTimeline"); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("slotIndex"); + _json.writeValue(obj->getSlotIndex()); + + _json.writeName("attachmentNames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getAttachmentNames().size(); i++) { + _json.writeValue(obj->getAttachmentNames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeDeformTimeline(DeformTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("DeformTimeline"); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("attachment"); + writeVertexAttachment(obj->getAttachment()); + + _json.writeName("vertices"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getVertices().size(); i++) { + Array &nestedArray = obj->getVertices()[i]; + _json.writeArrayStart(); + for (size_t j = 0; j < nestedArray.size(); j++) { + _json.writeValue(nestedArray[j]); + } + _json.writeArrayEnd(); + } + _json.writeArrayEnd(); + + _json.writeName("slotIndex"); + _json.writeValue(obj->getSlotIndex()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeDrawOrderTimeline(DrawOrderTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("DrawOrderTimeline"); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("drawOrders"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getDrawOrders().size(); i++) { + Array &nestedArray = obj->getDrawOrders()[i]; + _json.writeArrayStart(); + for (size_t j = 0; j < nestedArray.size(); j++) { + _json.writeValue(nestedArray[j]); + } + _json.writeArrayEnd(); + } + _json.writeArrayEnd(); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeEventTimeline(EventTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("EventTimeline"); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("events"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getEvents().size(); i++) { + writeEvent(obj->getEvents()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeIkConstraintTimeline(IkConstraintTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("IkConstraintTimeline"); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeInheritTimeline(InheritTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("InheritTimeline"); + + _json.writeName("boneIndex"); + _json.writeValue(obj->getBoneIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writePathConstraintMixTimeline(PathConstraintMixTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PathConstraintMixTimeline"); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writePathConstraintPositionTimeline(PathConstraintPositionTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PathConstraintPositionTimeline"); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writePathConstraintSpacingTimeline(PathConstraintSpacingTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PathConstraintSpacingTimeline"); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writePhysicsConstraintDampingTimeline(PhysicsConstraintDampingTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PhysicsConstraintDampingTimeline"); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writePhysicsConstraintGravityTimeline(PhysicsConstraintGravityTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PhysicsConstraintGravityTimeline"); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writePhysicsConstraintInertiaTimeline(PhysicsConstraintInertiaTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PhysicsConstraintInertiaTimeline"); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writePhysicsConstraintMassTimeline(PhysicsConstraintMassTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PhysicsConstraintMassTimeline"); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writePhysicsConstraintMixTimeline(PhysicsConstraintMixTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PhysicsConstraintMixTimeline"); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writePhysicsConstraintResetTimeline(PhysicsConstraintResetTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PhysicsConstraintResetTimeline"); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writePhysicsConstraintStrengthTimeline(PhysicsConstraintStrengthTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PhysicsConstraintStrengthTimeline"); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writePhysicsConstraintWindTimeline(PhysicsConstraintWindTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PhysicsConstraintWindTimeline"); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeRGB2Timeline(RGB2Timeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("RGB2Timeline"); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("slotIndex"); + _json.writeValue(obj->getSlotIndex()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeRGBA2Timeline(RGBA2Timeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("RGBA2Timeline"); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("slotIndex"); + _json.writeValue(obj->getSlotIndex()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeRGBATimeline(RGBATimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("RGBATimeline"); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("slotIndex"); + _json.writeValue(obj->getSlotIndex()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeRGBTimeline(RGBTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("RGBTimeline"); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("slotIndex"); + _json.writeValue(obj->getSlotIndex()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeRotateTimeline(RotateTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("RotateTimeline"); + + _json.writeName("boneIndex"); + _json.writeValue(obj->getBoneIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeScaleTimeline(ScaleTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("ScaleTimeline"); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("boneIndex"); + _json.writeValue(obj->getBoneIndex()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeScaleXTimeline(ScaleXTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("ScaleXTimeline"); + + _json.writeName("boneIndex"); + _json.writeValue(obj->getBoneIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeScaleYTimeline(ScaleYTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("ScaleYTimeline"); + + _json.writeName("boneIndex"); + _json.writeValue(obj->getBoneIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeSequenceTimeline(SequenceTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("SequenceTimeline"); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("slotIndex"); + _json.writeValue(obj->getSlotIndex()); + + _json.writeName("attachment"); + writeAttachment(obj->getAttachment()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeShearTimeline(ShearTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("ShearTimeline"); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("boneIndex"); + _json.writeValue(obj->getBoneIndex()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeShearXTimeline(ShearXTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("ShearXTimeline"); + + _json.writeName("boneIndex"); + _json.writeValue(obj->getBoneIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeShearYTimeline(ShearYTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("ShearYTimeline"); + + _json.writeName("boneIndex"); + _json.writeValue(obj->getBoneIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeSliderMixTimeline(SliderMixTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("SliderMixTimeline"); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeSliderTimeline(SliderTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("SliderTimeline"); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeTimeline(Timeline *obj) { + if (obj->getRTTI().instanceOf(AlphaTimeline::rtti)) { + writeAlphaTimeline((AlphaTimeline *) obj); + } else if (obj->getRTTI().instanceOf(AttachmentTimeline::rtti)) { + writeAttachmentTimeline((AttachmentTimeline *) obj); + } else if (obj->getRTTI().instanceOf(DeformTimeline::rtti)) { + writeDeformTimeline((DeformTimeline *) obj); + } else if (obj->getRTTI().instanceOf(DrawOrderTimeline::rtti)) { + writeDrawOrderTimeline((DrawOrderTimeline *) obj); + } else if (obj->getRTTI().instanceOf(EventTimeline::rtti)) { + writeEventTimeline((EventTimeline *) obj); + } else if (obj->getRTTI().instanceOf(IkConstraintTimeline::rtti)) { + writeIkConstraintTimeline((IkConstraintTimeline *) obj); + } else if (obj->getRTTI().instanceOf(InheritTimeline::rtti)) { + writeInheritTimeline((InheritTimeline *) obj); + } else if (obj->getRTTI().instanceOf(PathConstraintMixTimeline::rtti)) { + writePathConstraintMixTimeline((PathConstraintMixTimeline *) obj); + } else if (obj->getRTTI().instanceOf(PathConstraintPositionTimeline::rtti)) { + writePathConstraintPositionTimeline((PathConstraintPositionTimeline *) obj); + } else if (obj->getRTTI().instanceOf(PathConstraintSpacingTimeline::rtti)) { + writePathConstraintSpacingTimeline((PathConstraintSpacingTimeline *) obj); + } else if (obj->getRTTI().instanceOf(PhysicsConstraintDampingTimeline::rtti)) { + writePhysicsConstraintDampingTimeline((PhysicsConstraintDampingTimeline *) obj); + } else if (obj->getRTTI().instanceOf(PhysicsConstraintGravityTimeline::rtti)) { + writePhysicsConstraintGravityTimeline((PhysicsConstraintGravityTimeline *) obj); + } else if (obj->getRTTI().instanceOf(PhysicsConstraintInertiaTimeline::rtti)) { + writePhysicsConstraintInertiaTimeline((PhysicsConstraintInertiaTimeline *) obj); + } else if (obj->getRTTI().instanceOf(PhysicsConstraintMassTimeline::rtti)) { + writePhysicsConstraintMassTimeline((PhysicsConstraintMassTimeline *) obj); + } else if (obj->getRTTI().instanceOf(PhysicsConstraintMixTimeline::rtti)) { + writePhysicsConstraintMixTimeline((PhysicsConstraintMixTimeline *) obj); + } else if (obj->getRTTI().instanceOf(PhysicsConstraintResetTimeline::rtti)) { + writePhysicsConstraintResetTimeline((PhysicsConstraintResetTimeline *) obj); + } else if (obj->getRTTI().instanceOf(PhysicsConstraintStrengthTimeline::rtti)) { + writePhysicsConstraintStrengthTimeline((PhysicsConstraintStrengthTimeline *) obj); + } else if (obj->getRTTI().instanceOf(PhysicsConstraintWindTimeline::rtti)) { + writePhysicsConstraintWindTimeline((PhysicsConstraintWindTimeline *) obj); + } else if (obj->getRTTI().instanceOf(RGB2Timeline::rtti)) { + writeRGB2Timeline((RGB2Timeline *) obj); + } else if (obj->getRTTI().instanceOf(RGBA2Timeline::rtti)) { + writeRGBA2Timeline((RGBA2Timeline *) obj); + } else if (obj->getRTTI().instanceOf(RGBATimeline::rtti)) { + writeRGBATimeline((RGBATimeline *) obj); + } else if (obj->getRTTI().instanceOf(RGBTimeline::rtti)) { + writeRGBTimeline((RGBTimeline *) obj); + } else if (obj->getRTTI().instanceOf(RotateTimeline::rtti)) { + writeRotateTimeline((RotateTimeline *) obj); + } else if (obj->getRTTI().instanceOf(ScaleTimeline::rtti)) { + writeScaleTimeline((ScaleTimeline *) obj); + } else if (obj->getRTTI().instanceOf(ScaleXTimeline::rtti)) { + writeScaleXTimeline((ScaleXTimeline *) obj); + } else if (obj->getRTTI().instanceOf(ScaleYTimeline::rtti)) { + writeScaleYTimeline((ScaleYTimeline *) obj); + } else if (obj->getRTTI().instanceOf(SequenceTimeline::rtti)) { + writeSequenceTimeline((SequenceTimeline *) obj); + } else if (obj->getRTTI().instanceOf(ShearTimeline::rtti)) { + writeShearTimeline((ShearTimeline *) obj); + } else if (obj->getRTTI().instanceOf(ShearXTimeline::rtti)) { + writeShearXTimeline((ShearXTimeline *) obj); + } else if (obj->getRTTI().instanceOf(ShearYTimeline::rtti)) { + writeShearYTimeline((ShearYTimeline *) obj); + } else if (obj->getRTTI().instanceOf(SliderMixTimeline::rtti)) { + writeSliderMixTimeline((SliderMixTimeline *) obj); + } else if (obj->getRTTI().instanceOf(SliderTimeline::rtti)) { + writeSliderTimeline((SliderTimeline *) obj); + } else if (obj->getRTTI().instanceOf(TransformConstraintTimeline::rtti)) { + writeTransformConstraintTimeline((TransformConstraintTimeline *) obj); + } else if (obj->getRTTI().instanceOf(TranslateTimeline::rtti)) { + writeTranslateTimeline((TranslateTimeline *) obj); + } else if (obj->getRTTI().instanceOf(TranslateXTimeline::rtti)) { + writeTranslateXTimeline((TranslateXTimeline *) obj); + } else if (obj->getRTTI().instanceOf(TranslateYTimeline::rtti)) { + writeTranslateYTimeline((TranslateYTimeline *) obj); + } else { + fprintf(stderr, "Error: Unknown Timeline type\n"); + exit(1); + } + } + + void writeTransformConstraintTimeline(TransformConstraintTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("TransformConstraintTimeline"); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("constraintIndex"); + _json.writeValue(obj->getConstraintIndex()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeTranslateTimeline(TranslateTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("TranslateTimeline"); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("boneIndex"); + _json.writeValue(obj->getBoneIndex()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeTranslateXTimeline(TranslateXTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("TranslateXTimeline"); + + _json.writeName("boneIndex"); + _json.writeValue(obj->getBoneIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeTranslateYTimeline(TranslateYTimeline *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("TranslateYTimeline"); + + _json.writeName("boneIndex"); + _json.writeValue(obj->getBoneIndex()); + + _json.writeName("frameEntries"); + _json.writeValue(obj->getFrameEntries()); + + _json.writeName("propertyIds"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPropertyIds().size(); i++) { + _json.writeValue(obj->getPropertyIds()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frames"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getFrames().size(); i++) { + _json.writeValue(obj->getFrames()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("frameCount"); + _json.writeValue(obj->getFrameCount()); + + _json.writeName("duration"); + _json.writeValue(obj->getDuration()); + + _json.writeObjectEnd(); + } + + void writeAnimationState(AnimationState *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("AnimationState"); + + _json.writeName("timeScale"); + _json.writeValue(obj->getTimeScale()); + + _json.writeName("data"); + writeAnimationStateData(obj->getData()); + + _json.writeName("tracks"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getTracks().size(); i++) { + writeTrackEntry(obj->getTracks()[i]); + } + _json.writeArrayEnd(); + + _json.writeObjectEnd(); + } + + void writeTrackEntry(TrackEntry *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("TrackEntry"); + + _json.writeName("trackIndex"); + _json.writeValue(obj->getTrackIndex()); + + _json.writeName("animation"); + writeAnimation(obj->getAnimation()); + + _json.writeName("loop"); + _json.writeValue(obj->getLoop()); + + _json.writeName("delay"); + _json.writeValue(obj->getDelay()); + + _json.writeName("trackTime"); + _json.writeValue(obj->getTrackTime()); + + _json.writeName("trackEnd"); + _json.writeValue(obj->getTrackEnd()); + + _json.writeName("trackComplete"); + _json.writeValue(obj->getTrackComplete()); + + _json.writeName("animationStart"); + _json.writeValue(obj->getAnimationStart()); + + _json.writeName("animationEnd"); + _json.writeValue(obj->getAnimationEnd()); + + _json.writeName("animationLast"); + _json.writeValue(obj->getAnimationLast()); + + _json.writeName("animationTime"); + _json.writeValue(obj->getAnimationTime()); + + _json.writeName("timeScale"); + _json.writeValue(obj->getTimeScale()); + + _json.writeName("alpha"); + _json.writeValue(obj->getAlpha()); + + _json.writeName("eventThreshold"); + _json.writeValue(obj->getEventThreshold()); + + _json.writeName("alphaAttachmentThreshold"); + _json.writeValue(obj->getAlphaAttachmentThreshold()); + + _json.writeName("mixAttachmentThreshold"); + _json.writeValue(obj->getMixAttachmentThreshold()); + + _json.writeName("mixDrawOrderThreshold"); + _json.writeValue(obj->getMixDrawOrderThreshold()); + + _json.writeName("next"); + if (obj->getNext() == nullptr) { + _json.writeNull(); + } else { + writeTrackEntry(obj->getNext()); + } + + _json.writeName("previous"); + if (obj->getPrevious() == nullptr) { + _json.writeNull(); + } else { + writeTrackEntry(obj->getPrevious()); + } + + _json.writeName("mixTime"); + _json.writeValue(obj->getMixTime()); + + _json.writeName("mixDuration"); + _json.writeValue(obj->getMixDuration()); + + _json.writeName("additive"); + _json.writeValue(obj->getAdditive()); + + _json.writeName("mixingFrom"); + if (obj->getMixingFrom() == nullptr) { + _json.writeNull(); + } else { + writeTrackEntry(obj->getMixingFrom()); + } + + _json.writeName("mixingTo"); + if (obj->getMixingTo() == nullptr) { + _json.writeNull(); + } else { + writeTrackEntry(obj->getMixingTo()); + } + + + _json.writeName("shortestRotation"); + _json.writeValue(obj->getShortestRotation()); + + _json.writeName("reverse"); + _json.writeValue(obj->getReverse()); + + _json.writeObjectEnd(); + } + + void writeAnimationStateData(AnimationStateData *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("AnimationStateData"); + + _json.writeName("skeletonData"); + writeSkeletonData(obj->getSkeletonData()); + + _json.writeName("defaultMix"); + _json.writeValue(obj->getDefaultMix()); + + _json.writeObjectEnd(); + } + + void writeAttachment(Attachment *obj) { + if (obj->getRTTI().instanceOf(BoundingBoxAttachment::rtti)) { + writeBoundingBoxAttachment((BoundingBoxAttachment *) obj); + } else if (obj->getRTTI().instanceOf(ClippingAttachment::rtti)) { + writeClippingAttachment((ClippingAttachment *) obj); + } else if (obj->getRTTI().instanceOf(MeshAttachment::rtti)) { + writeMeshAttachment((MeshAttachment *) obj); + } else if (obj->getRTTI().instanceOf(PathAttachment::rtti)) { + writePathAttachment((PathAttachment *) obj); + } else if (obj->getRTTI().instanceOf(PointAttachment::rtti)) { + writePointAttachment((PointAttachment *) obj); + } else if (obj->getRTTI().instanceOf(RegionAttachment::rtti)) { + writeRegionAttachment((RegionAttachment *) obj); + } else { + fprintf(stderr, "Error: Unknown Attachment type\n"); + exit(1); + } + } + + void writeBone(Bone *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("Bone"); + + _json.writeName("parent"); + if (obj->getParent() == nullptr) { + _json.writeNull(); + } else { + writeBone(obj->getParent()); + } + + _json.writeName("children"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getChildren().size(); i++) { + writeBone(obj->getChildren()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("data"); + writeBoneData(obj->getData()); + + _json.writeName("pose"); + writeBonePose(obj->getPose()); + + _json.writeName("appliedPose"); + writeBonePose(obj->getAppliedPose()); + + _json.writeObjectEnd(); + } + + void writeBoneData(BoneData *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("BoneData"); + + _json.writeName("index"); + _json.writeValue(obj->getIndex()); + + _json.writeName("parent"); + if (obj->getParent() == nullptr) { + _json.writeNull(); + } else { + writeBoneData(obj->getParent()); + } + + _json.writeName("length"); + _json.writeValue(obj->getLength()); + + _json.writeName("color"); + writeColor(obj->getColor()); + + _json.writeName("icon"); + _json.writeValue(obj->getIcon()); + + _json.writeName("iconSize"); + _json.writeValue(obj->getIconSize()); + + _json.writeName("iconRotation"); + _json.writeValue(obj->getIconRotation()); + + _json.writeName("visible"); + _json.writeValue(obj->getVisible()); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeName("setupPose"); + writeBonePose(obj->getSetupPose()); + + _json.writeName("skinRequired"); + _json.writeValue(obj->getSkinRequired()); + + _json.writeObjectEnd(); + } + + void writeBoneLocal(BoneLocal *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("BoneLocal"); + + _json.writeName("x"); + _json.writeValue(obj->getX()); + + _json.writeName("y"); + _json.writeValue(obj->getY()); + + _json.writeName("rotation"); + _json.writeValue(obj->getRotation()); + + _json.writeName("scaleX"); + _json.writeValue(obj->getScaleX()); + + _json.writeName("scaleY"); + _json.writeValue(obj->getScaleY()); + + _json.writeName("shearX"); + _json.writeValue(obj->getShearX()); + + _json.writeName("shearY"); + _json.writeValue(obj->getShearY()); + + _json.writeName("inherit"); + _json.writeValue([&]() -> String { + switch (obj->getInherit()) { + case Inherit_Normal: + return "normal"; + case Inherit_OnlyTranslation: + return "onlyTranslation"; + case Inherit_NoRotationOrReflection: + return "noRotationOrReflection"; + case Inherit_NoScale: + return "noScale"; + case Inherit_NoScaleOrReflection: + return "noScaleOrReflection"; + default: + return "unknown"; + } + }()); + + _json.writeObjectEnd(); + } + + void writeBonePose(BonePose *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("BonePose"); + + _json.writeName("a"); + _json.writeValue(obj->getA()); + + _json.writeName("b"); + _json.writeValue(obj->getB()); + + _json.writeName("c"); + _json.writeValue(obj->getC()); + + _json.writeName("d"); + _json.writeValue(obj->getD()); + + _json.writeName("worldX"); + _json.writeValue(obj->getWorldX()); + + _json.writeName("worldY"); + _json.writeValue(obj->getWorldY()); + + _json.writeName("worldRotationX"); + _json.writeValue(obj->getWorldRotationX()); + + _json.writeName("worldRotationY"); + _json.writeValue(obj->getWorldRotationY()); + + _json.writeName("worldScaleX"); + _json.writeValue(obj->getWorldScaleX()); + + _json.writeName("worldScaleY"); + _json.writeValue(obj->getWorldScaleY()); + + _json.writeName("x"); + _json.writeValue(obj->getX()); + + _json.writeName("y"); + _json.writeValue(obj->getY()); + + _json.writeName("rotation"); + _json.writeValue(obj->getRotation()); + + _json.writeName("scaleX"); + _json.writeValue(obj->getScaleX()); + + _json.writeName("scaleY"); + _json.writeValue(obj->getScaleY()); + + _json.writeName("shearX"); + _json.writeValue(obj->getShearX()); + + _json.writeName("shearY"); + _json.writeValue(obj->getShearY()); + + _json.writeName("inherit"); + _json.writeValue([&]() -> String { + switch (obj->getInherit()) { + case Inherit_Normal: + return "normal"; + case Inherit_OnlyTranslation: + return "onlyTranslation"; + case Inherit_NoRotationOrReflection: + return "noRotationOrReflection"; + case Inherit_NoScale: + return "noScale"; + case Inherit_NoScaleOrReflection: + return "noScaleOrReflection"; + default: + return "unknown"; + } + }()); + + _json.writeObjectEnd(); + } + + void writeBoundingBoxAttachment(BoundingBoxAttachment *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("BoundingBoxAttachment"); + + _json.writeName("color"); + writeColor(obj->getColor()); + + _json.writeName("bones"); + if (obj->getBones().size() == 0) { + _json.writeNull(); + } else { + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getBones().size(); i++) { + _json.writeValue(obj->getBones()[i]); + } + _json.writeArrayEnd(); + } + + _json.writeName("vertices"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getVertices().size(); i++) { + _json.writeValue(obj->getVertices()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("worldVerticesLength"); + _json.writeValue(obj->getWorldVerticesLength()); + + _json.writeName("timelineAttachment"); + if (obj->getTimelineAttachment() == nullptr) { + _json.writeNull(); + } else { + writeAttachment(obj->getTimelineAttachment()); + } + + _json.writeName("timelineSlots"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getTimelineSlots().size(); i++) { + _json.writeValue(obj->getTimelineSlots()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("id"); + _json.writeValue(obj->getId()); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeObjectEnd(); + } + + void writeClippingAttachment(ClippingAttachment *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("ClippingAttachment"); + + _json.writeName("endSlot"); + if (obj->getEndSlot() == nullptr) { + _json.writeNull(); + } else { + writeSlotData(obj->getEndSlot()); + } + + _json.writeName("inverse"); + _json.writeValue(obj->getInverse()); + + _json.writeName("convex"); + _json.writeValue(obj->getConvex()); + + _json.writeName("color"); + writeColor(obj->getColor()); + + _json.writeName("bones"); + if (obj->getBones().size() == 0) { + _json.writeNull(); + } else { + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getBones().size(); i++) { + _json.writeValue(obj->getBones()[i]); + } + _json.writeArrayEnd(); + } + + _json.writeName("vertices"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getVertices().size(); i++) { + _json.writeValue(obj->getVertices()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("worldVerticesLength"); + _json.writeValue(obj->getWorldVerticesLength()); + + _json.writeName("timelineAttachment"); + if (obj->getTimelineAttachment() == nullptr) { + _json.writeNull(); + } else { + writeAttachment(obj->getTimelineAttachment()); + } + + _json.writeName("timelineSlots"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getTimelineSlots().size(); i++) { + _json.writeValue(obj->getTimelineSlots()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("id"); + _json.writeValue(obj->getId()); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeObjectEnd(); + } + + void writeConstraint(Constraint *obj) { + if (obj->getRTTI().instanceOf(IkConstraint::rtti)) { + writeIkConstraint((IkConstraint *) obj); + } else if (obj->getRTTI().instanceOf(PathConstraint::rtti)) { + writePathConstraint((PathConstraint *) obj); + } else if (obj->getRTTI().instanceOf(PhysicsConstraint::rtti)) { + writePhysicsConstraint((PhysicsConstraint *) obj); + } else if (obj->getRTTI().instanceOf(Slider::rtti)) { + writeSlider((Slider *) obj); + } else if (obj->getRTTI().instanceOf(TransformConstraint::rtti)) { + writeTransformConstraint((TransformConstraint *) obj); + } else { + fprintf(stderr, "Error: Unknown Constraint type\n"); + exit(1); + } + } + + void writeConstraintData(ConstraintData *obj) { + if (obj->getRTTI().instanceOf(IkConstraintData::rtti)) { + writeIkConstraintData((IkConstraintData *) obj); + } else if (obj->getRTTI().instanceOf(PathConstraintData::rtti)) { + writePathConstraintData((PathConstraintData *) obj); + } else if (obj->getRTTI().instanceOf(PhysicsConstraintData::rtti)) { + writePhysicsConstraintData((PhysicsConstraintData *) obj); + } else if (obj->getRTTI().instanceOf(SliderData::rtti)) { + writeSliderData((SliderData *) obj); + } else if (obj->getRTTI().instanceOf(TransformConstraintData::rtti)) { + writeTransformConstraintData((TransformConstraintData *) obj); + } else { + fprintf(stderr, "Error: Unknown ConstraintData type\n"); + exit(1); + } + } + + void writeEvent(Event *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("Event"); + + _json.writeName("int"); + _json.writeValue(obj->getInt()); + + _json.writeName("float"); + _json.writeValue(obj->getFloat()); + + _json.writeName("string"); + _json.writeValue(obj->getString()); + + _json.writeName("volume"); + _json.writeValue(obj->getVolume()); + + _json.writeName("balance"); + _json.writeValue(obj->getBalance()); + + _json.writeName("time"); + _json.writeValue(obj->getTime()); + + _json.writeName("data"); + writeEventData(obj->getData()); + + _json.writeObjectEnd(); + } + + void writeEventData(EventData *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("EventData"); + + Event &setup = obj->getSetupPose(); + _json.writeName("int"); + _json.writeValue(setup.getInt()); + + _json.writeName("float"); + _json.writeValue(setup.getFloat()); + + _json.writeName("string"); + _json.writeValue(setup.getString()); + + _json.writeName("audioPath"); + _json.writeValue(obj->getAudioPath()); + + _json.writeName("volume"); + _json.writeValue(setup.getVolume()); + + _json.writeName("balance"); + _json.writeValue(setup.getBalance()); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeObjectEnd(); + } + + void writeIkConstraint(IkConstraint *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("IkConstraint"); + + _json.writeName("bones"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getBones().size(); i++) { + writeBonePose(obj->getBones()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("target"); + writeBone(obj->getTarget()); + + _json.writeName("data"); + writeIkConstraintData(obj->getData()); + + _json.writeName("pose"); + writeIkConstraintPose(obj->getPose()); + + _json.writeName("appliedPose"); + writeIkConstraintPose(obj->getAppliedPose()); + + _json.writeObjectEnd(); + } + + void writeIkConstraintData(IkConstraintData *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("IkConstraintData"); + + _json.writeName("bones"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getBones().size(); i++) { + writeBoneData(obj->getBones()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("target"); + writeBoneData(obj->getTarget()); + + _json.writeName("scaleY"); + _json.writeValue(ScaleYMode_toString(obj->getScaleYMode())); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeName("setupPose"); + writeIkConstraintPose(obj->getSetupPose()); + + _json.writeName("skinRequired"); + _json.writeValue(obj->getSkinRequired()); + + _json.writeObjectEnd(); + } + + void writeIkConstraintPose(IkConstraintPose *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("IkConstraintPose"); + + _json.writeName("mix"); + _json.writeValue(obj->getMix()); + + _json.writeName("softness"); + _json.writeValue(obj->getSoftness()); + + _json.writeName("bendDirection"); + _json.writeValue(obj->getBendDirection()); + + _json.writeName("compress"); + _json.writeValue(obj->getCompress()); + + _json.writeName("stretch"); + _json.writeValue(obj->getStretch()); + + _json.writeObjectEnd(); + } + + void writeMeshAttachment(MeshAttachment *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("MeshAttachment"); + + Sequence &sequence = obj->getSequence(); + int setupIndex = sequence.getSetupIndex(); + _json.writeName("region"); + if (sequence.getRegion(setupIndex) == nullptr) { + _json.writeNull(); + } else { + writeTextureRegion(sequence.getRegion(setupIndex)); + } + + _json.writeName("triangles"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getTriangles().size(); i++) { + _json.writeValue(obj->getTriangles()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("regionUVs"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getRegionUVs().size(); i++) { + _json.writeValue(obj->getRegionUVs()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("uVs"); + _json.writeArrayStart(); + for (size_t i = 0; i < sequence.getUVs(setupIndex).size(); i++) { + _json.writeValue(sequence.getUVs(setupIndex)[i]); + } + _json.writeArrayEnd(); + + _json.writeName("color"); + writeColor(obj->getColor()); + + _json.writeName("path"); + _json.writeValue(obj->getPath()); + + _json.writeName("hullLength"); + _json.writeValue(obj->getHullLength()); + + _json.writeName("edges"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getEdges().size(); i++) { + _json.writeValue(obj->getEdges()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("width"); + _json.writeValue(obj->getWidth()); + + _json.writeName("height"); + _json.writeValue(obj->getHeight()); + + _json.writeName("sequence"); + writeSequence(&obj->getSequence()); + + _json.writeName("sourceMesh"); + if (obj->getSourceMesh() == nullptr) { + _json.writeNull(); + } else { + writeMeshAttachment(obj->getSourceMesh()); + } + + _json.writeName("bones"); + if (obj->getBones().size() == 0) { + _json.writeNull(); + } else { + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getBones().size(); i++) { + _json.writeValue(obj->getBones()[i]); + } + _json.writeArrayEnd(); + } + + _json.writeName("vertices"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getVertices().size(); i++) { + _json.writeValue(obj->getVertices()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("worldVerticesLength"); + _json.writeValue(obj->getWorldVerticesLength()); + + _json.writeName("timelineAttachment"); + if (obj->getTimelineAttachment() == nullptr) { + _json.writeNull(); + } else { + writeAttachment(obj->getTimelineAttachment()); + } + + _json.writeName("timelineSlots"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getTimelineSlots().size(); i++) { + _json.writeValue(obj->getTimelineSlots()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("id"); + _json.writeValue(obj->getId()); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeObjectEnd(); + } + + void writePathAttachment(PathAttachment *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PathAttachment"); + + _json.writeName("closed"); + _json.writeValue(obj->getClosed()); + + _json.writeName("constantSpeed"); + _json.writeValue(obj->getConstantSpeed()); + + _json.writeName("lengths"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getLengths().size(); i++) { + _json.writeValue(obj->getLengths()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("color"); + writeColor(obj->getColor()); + + _json.writeName("bones"); + if (obj->getBones().size() == 0) { + _json.writeNull(); + } else { + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getBones().size(); i++) { + _json.writeValue(obj->getBones()[i]); + } + _json.writeArrayEnd(); + } + + _json.writeName("vertices"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getVertices().size(); i++) { + _json.writeValue(obj->getVertices()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("worldVerticesLength"); + _json.writeValue(obj->getWorldVerticesLength()); + + _json.writeName("timelineAttachment"); + if (obj->getTimelineAttachment() == nullptr) { + _json.writeNull(); + } else { + writeAttachment(obj->getTimelineAttachment()); + } + + _json.writeName("timelineSlots"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getTimelineSlots().size(); i++) { + _json.writeValue(obj->getTimelineSlots()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("id"); + _json.writeValue(obj->getId()); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeObjectEnd(); + } + + void writePathConstraint(PathConstraint *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PathConstraint"); + + _json.writeName("bones"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getBones().size(); i++) { + writeBonePose(obj->getBones()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("slot"); + writeSlot(obj->getSlot()); + + _json.writeName("data"); + writePathConstraintData(obj->getData()); + + _json.writeName("pose"); + writePathConstraintPose(obj->getPose()); + + _json.writeName("appliedPose"); + writePathConstraintPose(obj->getAppliedPose()); + + _json.writeObjectEnd(); + } + + void writePathConstraintData(PathConstraintData *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PathConstraintData"); + + _json.writeName("bones"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getBones().size(); i++) { + writeBoneData(obj->getBones()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("slot"); + writeSlotData(obj->getSlot()); + + _json.writeName("positionMode"); + _json.writeValue([&]() -> String { + switch (obj->getPositionMode()) { + case PositionMode_Fixed: + return "fixed"; + case PositionMode_Percent: + return "percent"; + default: + return "unknown"; + } + }()); + + _json.writeName("spacingMode"); + _json.writeValue([&]() -> String { + switch (obj->getSpacingMode()) { + case SpacingMode_Length: + return "length"; + case SpacingMode_Fixed: + return "fixed"; + case SpacingMode_Percent: + return "percent"; + case SpacingMode_Proportional: + return "proportional"; + default: + return "unknown"; + } + }()); + + _json.writeName("rotateMode"); + _json.writeValue([&]() -> String { + switch (obj->getRotateMode()) { + case RotateMode_Tangent: + return "tangent"; + case RotateMode_Chain: + return "chain"; + case RotateMode_ChainScale: + return "chainScale"; + default: + return "unknown"; + } + }()); + + _json.writeName("offsetRotation"); + _json.writeValue(obj->getOffsetRotation()); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeName("setupPose"); + writePathConstraintPose(obj->getSetupPose()); + + _json.writeName("skinRequired"); + _json.writeValue(obj->getSkinRequired()); + + _json.writeObjectEnd(); + } + + void writePathConstraintPose(PathConstraintPose *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PathConstraintPose"); + + _json.writeName("position"); + _json.writeValue(obj->getPosition()); + + _json.writeName("spacing"); + _json.writeValue(obj->getSpacing()); + + _json.writeName("mixRotate"); + _json.writeValue(obj->getMixRotate()); + + _json.writeName("mixX"); + _json.writeValue(obj->getMixX()); + + _json.writeName("mixY"); + _json.writeValue(obj->getMixY()); + + _json.writeObjectEnd(); + } + + void writePhysicsConstraint(PhysicsConstraint *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PhysicsConstraint"); + + _json.writeName("bone"); + writeBonePose(obj->getBone()); + + _json.writeName("data"); + writePhysicsConstraintData(obj->getData()); + + _json.writeName("pose"); + writePhysicsConstraintPose(obj->getPose()); + + _json.writeName("appliedPose"); + writePhysicsConstraintPose(obj->getAppliedPose()); + + _json.writeObjectEnd(); + } + + void writePhysicsConstraintData(PhysicsConstraintData *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PhysicsConstraintData"); + + _json.writeName("bone"); + writeBoneData(obj->getBone()); + + _json.writeName("step"); + _json.writeValue(obj->getStep()); + + _json.writeName("x"); + _json.writeValue(obj->getX()); + + _json.writeName("y"); + _json.writeValue(obj->getY()); + + _json.writeName("rotate"); + _json.writeValue(obj->getRotate()); + + _json.writeName("scaleX"); + _json.writeValue(obj->getScaleX()); + + _json.writeName("shearX"); + _json.writeValue(obj->getShearX()); + + _json.writeName("limit"); + _json.writeValue(obj->getLimit()); + + _json.writeName("inertiaGlobal"); + _json.writeValue(obj->getInertiaGlobal()); + + _json.writeName("strengthGlobal"); + _json.writeValue(obj->getStrengthGlobal()); + + _json.writeName("dampingGlobal"); + _json.writeValue(obj->getDampingGlobal()); + + _json.writeName("massGlobal"); + _json.writeValue(obj->getMassGlobal()); + + _json.writeName("windGlobal"); + _json.writeValue(obj->getWindGlobal()); + + _json.writeName("gravityGlobal"); + _json.writeValue(obj->getGravityGlobal()); + + _json.writeName("mixGlobal"); + _json.writeValue(obj->getMixGlobal()); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeName("setupPose"); + writePhysicsConstraintPose(obj->getSetupPose()); + + _json.writeName("skinRequired"); + _json.writeValue(obj->getSkinRequired()); + + _json.writeObjectEnd(); + } + + void writePhysicsConstraintPose(PhysicsConstraintPose *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PhysicsConstraintPose"); + + _json.writeName("inertia"); + _json.writeValue(obj->getInertia()); + + _json.writeName("strength"); + _json.writeValue(obj->getStrength()); + + _json.writeName("damping"); + _json.writeValue(obj->getDamping()); + + _json.writeName("massInverse"); + _json.writeValue(obj->getMassInverse()); + + _json.writeName("wind"); + _json.writeValue(obj->getWind()); + + _json.writeName("gravity"); + _json.writeValue(obj->getGravity()); + + _json.writeName("mix"); + _json.writeValue(obj->getMix()); + + _json.writeObjectEnd(); + } + + void writePointAttachment(PointAttachment *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("PointAttachment"); + + _json.writeName("x"); + _json.writeValue(obj->getX()); + + _json.writeName("y"); + _json.writeValue(obj->getY()); + + _json.writeName("rotation"); + _json.writeValue(obj->getRotation()); + + _json.writeName("color"); + writeColor(obj->getColor()); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeObjectEnd(); + } + + void writeRegionAttachment(RegionAttachment *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("RegionAttachment"); + + Sequence &sequence = obj->getSequence(); + int setupIndex = sequence.getSetupIndex(); + _json.writeName("region"); + if (sequence.getRegion(setupIndex) == nullptr) { + _json.writeNull(); + } else { + writeTextureRegion(sequence.getRegion(setupIndex)); + } + + _json.writeName("offset"); + _json.writeArrayStart(); + for (size_t i = 0; i < sequence.getOffsets(setupIndex).size(); i++) { + _json.writeValue(sequence.getOffsets(setupIndex)[i]); + } + _json.writeArrayEnd(); + + _json.writeName("uVs"); + _json.writeArrayStart(); + for (size_t i = 0; i < sequence.getUVs(setupIndex).size(); i++) { + _json.writeValue(sequence.getUVs(setupIndex)[i]); + } + _json.writeArrayEnd(); + + _json.writeName("x"); + _json.writeValue(obj->getX()); + + _json.writeName("y"); + _json.writeValue(obj->getY()); + + _json.writeName("scaleX"); + _json.writeValue(obj->getScaleX()); + + _json.writeName("scaleY"); + _json.writeValue(obj->getScaleY()); + + _json.writeName("rotation"); + _json.writeValue(obj->getRotation()); + + _json.writeName("width"); + _json.writeValue(obj->getWidth()); + + _json.writeName("height"); + _json.writeValue(obj->getHeight()); + + _json.writeName("color"); + writeColor(obj->getColor()); + + _json.writeName("path"); + _json.writeValue(obj->getPath()); + + _json.writeName("sequence"); + writeSequence(&obj->getSequence()); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeObjectEnd(); + } + + void writeSequence(Sequence *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("Sequence"); + + _json.writeName("start"); + _json.writeValue(obj->getStart()); + + _json.writeName("digits"); + _json.writeValue(obj->getDigits()); + + _json.writeName("setupIndex"); + _json.writeValue(obj->getSetupIndex()); + + _json.writeName("regions"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getRegions().size(); i++) { + writeTextureRegion(obj->getRegions()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("id"); + _json.writeValue(obj->getId()); + + _json.writeObjectEnd(); + } + + void writeSkeleton(Skeleton *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("Skeleton"); + + _json.writeName("data"); + writeSkeletonData(obj->getData()); + + _json.writeName("bones"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getBones().size(); i++) { + writeBone(obj->getBones()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("updateCache"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getUpdateCache().size(); i++) { + writeUpdate(obj->getUpdateCache()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("rootBone"); + writeBone(obj->getRootBone()); + + _json.writeName("slots"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getSlots().size(); i++) { + writeSlot(obj->getSlots()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("drawOrderPose"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getDrawOrder().getPose().size(); i++) { + writeSlot(obj->getDrawOrder().getPose()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("drawOrderApplied"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getDrawOrder().getAppliedPose().size(); i++) { + writeSlot(obj->getDrawOrder().getAppliedPose()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("skin"); + if (obj->getSkin() == nullptr) { + _json.writeNull(); + } else { + writeSkin(obj->getSkin()); + } + + _json.writeName("constraints"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getConstraints().size(); i++) { + writeConstraint(obj->getConstraints()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("physicsConstraints"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getPhysicsConstraints().size(); i++) { + writePhysicsConstraint(obj->getPhysicsConstraints()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("color"); + writeColor(obj->getColor()); + + _json.writeName("scaleX"); + _json.writeValue(obj->getScaleX()); + + _json.writeName("scaleY"); + _json.writeValue(obj->getScaleY()); + + _json.writeName("x"); + _json.writeValue(obj->getX()); + + _json.writeName("y"); + _json.writeValue(obj->getY()); + + _json.writeName("windX"); + _json.writeValue(obj->getWindX()); + + _json.writeName("windY"); + _json.writeValue(obj->getWindY()); + + _json.writeName("gravityX"); + _json.writeValue(obj->getGravityX()); + + _json.writeName("gravityY"); + _json.writeValue(obj->getGravityY()); + + _json.writeName("time"); + _json.writeValue(obj->getTime()); + + _json.writeObjectEnd(); + } + + void writeSkeletonData(SkeletonData *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("SkeletonData"); + + _json.writeName("bones"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getBones().size(); i++) { + writeBoneData(obj->getBones()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("slots"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getSlots().size(); i++) { + writeSlotData(obj->getSlots()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("defaultSkin"); + if (obj->getDefaultSkin() == nullptr) { + _json.writeNull(); + } else { + writeSkin(obj->getDefaultSkin()); + } + + _json.writeName("skins"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getSkins().size(); i++) { + writeSkin(obj->getSkins()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("events"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getEvents().size(); i++) { + writeEventData(obj->getEvents()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("animations"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getAnimations().size(); i++) { + writeAnimation(obj->getAnimations()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("constraints"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getConstraints().size(); i++) { + writeConstraintData(obj->getConstraints()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeName("x"); + _json.writeValue(obj->getX()); + + _json.writeName("y"); + _json.writeValue(obj->getY()); + + _json.writeName("width"); + _json.writeValue(obj->getWidth()); + + _json.writeName("height"); + _json.writeValue(obj->getHeight()); + + _json.writeName("referenceScale"); + _json.writeValue(obj->getReferenceScale()); + + _json.writeName("version"); + _json.writeValue(obj->getVersion()); + + _json.writeName("hash"); + _json.writeValue(obj->getHash()); + + _json.writeName("imagesPath"); + _json.writeValue(obj->getImagesPath()); + + _json.writeName("audioPath"); + _json.writeValue(obj->getAudioPath()); + + _json.writeName("fps"); + _json.writeValue(obj->getFps()); + + _json.writeObjectEnd(); + } + + void writeSkin(Skin *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("Skin"); + + _json.writeName("attachments"); + _json.writeArrayStart(); + Skin::AttachmentMap::Entries entries = obj->getAttachments(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + writeSkinEntry(&entry); + } + _json.writeArrayEnd(); + + _json.writeName("bones"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getBones().size(); i++) { + BoneData *item = obj->getBones()[i]; + writeBoneData(item); + } + _json.writeArrayEnd(); + + _json.writeName("constraints"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getConstraints().size(); i++) { + ConstraintData *item = obj->getConstraints()[i]; + writeConstraintData(item); + } + _json.writeArrayEnd(); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeName("color"); + writeColor(&obj->getColor()); + + _json.writeObjectEnd(); + } + + void writeSkinEntry(Skin::AttachmentMap::Entry *obj) { + String placeholder = obj->_placeholder; + String key = String().append((int) obj->_slotIndex).append(":").append(placeholder); + if (_visitedSkinEntries.containsKey(key)) { + _json.writeValue(_visitedSkinEntries[key]); + return; + } + String refString; + if (!placeholder.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedSkinEntries.put(key, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("SkinEntry"); + _json.writeName("slotIndex"); + _json.writeValue((int) obj->_slotIndex); + _json.writeName("name"); + _json.writeValue(obj->_placeholder); + _json.writeName("attachment"); + writeAttachment(obj->_attachment); + _json.writeObjectEnd(); + } + + void writeSlider(Slider *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("Slider"); + + _json.writeName("bone"); + writeBone(obj->getBone()); + + _json.writeName("data"); + writeSliderData(obj->getData()); + + _json.writeName("pose"); + writeSliderPose(obj->getPose()); + + _json.writeName("appliedPose"); + writeSliderPose(obj->getAppliedPose()); + + _json.writeObjectEnd(); + } + + void writeSliderData(SliderData *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("SliderData"); + + _json.writeName("animation"); + writeAnimation(obj->getAnimation()); + + _json.writeName("additive"); + _json.writeValue(obj->getAdditive()); + + _json.writeName("loop"); + _json.writeValue(obj->getLoop()); + + _json.writeName("bone"); + if (obj->getBone() == nullptr) { + _json.writeNull(); + } else { + writeBoneData(obj->getBone()); + } + + _json.writeName("property"); + if (obj->getProperty() == nullptr) { + _json.writeNull(); + } else { + writeFromProperty(obj->getProperty()); + } + + _json.writeName("offset"); + _json.writeValue(obj->getOffset()); + + _json.writeName("scale"); + _json.writeValue(obj->getScale()); + + _json.writeName("max"); + _json.writeValue(obj->getMax()); + + _json.writeName("local"); + _json.writeValue(obj->getLocal()); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeName("setupPose"); + writeSliderPose(obj->getSetupPose()); + + _json.writeName("skinRequired"); + _json.writeValue(obj->getSkinRequired()); + + _json.writeObjectEnd(); + } + + void writeSliderPose(SliderPose *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("SliderPose"); + + _json.writeName("time"); + _json.writeValue(obj->getTime()); + + _json.writeName("mix"); + _json.writeValue(obj->getMix()); + + _json.writeObjectEnd(); + } + + void writeSlot(Slot *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("Slot"); + + _json.writeName("bone"); + writeBone(obj->getBone()); + + _json.writeName("data"); + writeSlotData(obj->getData()); + + _json.writeName("pose"); + writeSlotPose(obj->getPose()); + + _json.writeName("appliedPose"); + writeSlotPose(obj->getAppliedPose()); + + _json.writeObjectEnd(); + } + + void writeSlotData(SlotData *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("SlotData"); + + _json.writeName("index"); + _json.writeValue(obj->getIndex()); + + _json.writeName("boneData"); + writeBoneData(obj->getBoneData()); + + _json.writeName("attachmentName"); + _json.writeValue(obj->getAttachmentName()); + + _json.writeName("blendMode"); + _json.writeValue([&]() -> String { + switch (obj->getBlendMode()) { + case BlendMode_Normal: + return "normal"; + case BlendMode_Additive: + return "additive"; + case BlendMode_Multiply: + return "multiply"; + case BlendMode_Screen: + return "screen"; + default: + return "unknown"; + } + }()); + + _json.writeName("visible"); + _json.writeValue(obj->getVisible()); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeName("setupPose"); + writeSlotPose(obj->getSetupPose()); + + _json.writeName("skinRequired"); + _json.writeValue(obj->getSkinRequired()); + + _json.writeObjectEnd(); + } + + void writeSlotPose(SlotPose *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("SlotPose"); + + _json.writeName("color"); + writeColor(obj->getColor()); + + _json.writeName("darkColor"); + if (obj->hasDarkColor()) { + writeColor(&obj->getDarkColor()); + } else { + _json.writeNull(); + } + + _json.writeName("attachment"); + if (obj->getAttachment() == nullptr) { + _json.writeNull(); + } else { + writeAttachment(obj->getAttachment()); + } + + _json.writeName("sequenceIndex"); + _json.writeValue(obj->getSequenceIndex()); + + _json.writeName("deform"); + writeFloatArray(obj->getDeform()); + + _json.writeObjectEnd(); + } + + void writeTransformConstraint(TransformConstraint *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("TransformConstraint"); + + _json.writeName("bones"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getBones().size(); i++) { + writeBonePose(obj->getBones()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("source"); + writeBone(obj->getSource()); + + _json.writeName("data"); + writeTransformConstraintData(obj->getData()); + + _json.writeName("pose"); + writeTransformConstraintPose(obj->getPose()); + + _json.writeName("appliedPose"); + writeTransformConstraintPose(obj->getAppliedPose()); + + _json.writeObjectEnd(); + } + + void writeTransformConstraintData(TransformConstraintData *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String name = obj->getName(); + String refString; + if (!name.isEmpty()) { + refString.append(""); + } else { + refString.append(""); + } + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("TransformConstraintData"); + + _json.writeName("bones"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getBones().size(); i++) { + writeBoneData(obj->getBones()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("source"); + writeBoneData(obj->getSource()); + + _json.writeName("offsetRotation"); + _json.writeValue(obj->getOffsetRotation()); + + _json.writeName("offsetX"); + _json.writeValue(obj->getOffsetX()); + + _json.writeName("offsetY"); + _json.writeValue(obj->getOffsetY()); + + _json.writeName("offsetScaleX"); + _json.writeValue(obj->getOffsetScaleX()); + + _json.writeName("offsetScaleY"); + _json.writeValue(obj->getOffsetScaleY()); + + _json.writeName("offsetShearY"); + _json.writeValue(obj->getOffsetShearY()); + + _json.writeName("localSource"); + _json.writeValue(obj->getLocalSource()); + + _json.writeName("localTarget"); + _json.writeValue(obj->getLocalTarget()); + + _json.writeName("additive"); + _json.writeValue(obj->getAdditive()); + + _json.writeName("clamp"); + _json.writeValue(obj->getClamp()); + + _json.writeName("properties"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->getProperties().size(); i++) { + writeFromProperty(obj->getProperties()[i]); + } + _json.writeArrayEnd(); + + _json.writeName("name"); + _json.writeValue(obj->getName()); + + _json.writeName("setupPose"); + writeTransformConstraintPose(obj->getSetupPose()); + + _json.writeName("skinRequired"); + _json.writeValue(obj->getSkinRequired()); + + _json.writeObjectEnd(); + } + + void writeFromProperty(FromProperty *obj) { + if (obj->getRTTI().instanceOf(FromRotate::rtti)) { + writeFromRotate((FromRotate *) obj); + } else if (obj->getRTTI().instanceOf(FromScaleX::rtti)) { + writeFromScaleX((FromScaleX *) obj); + } else if (obj->getRTTI().instanceOf(FromScaleY::rtti)) { + writeFromScaleY((FromScaleY *) obj); + } else if (obj->getRTTI().instanceOf(FromShearY::rtti)) { + writeFromShearY((FromShearY *) obj); + } else if (obj->getRTTI().instanceOf(FromX::rtti)) { + writeFromX((FromX *) obj); + } else if (obj->getRTTI().instanceOf(FromY::rtti)) { + writeFromY((FromY *) obj); + } else { + fprintf(stderr, "Error: Unknown FromProperty type\n"); + exit(1); + } + } + + void writeFromRotate(FromRotate *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("FromRotate"); + + _json.writeName("offset"); + _json.writeValue(obj->_offset); + + _json.writeName("to"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->_to.size(); i++) { + writeToProperty(obj->_to[i]); + } + _json.writeArrayEnd(); + + _json.writeObjectEnd(); + } + + void writeFromScaleX(FromScaleX *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("FromScaleX"); + + _json.writeName("offset"); + _json.writeValue(obj->_offset); + + _json.writeName("to"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->_to.size(); i++) { + writeToProperty(obj->_to[i]); + } + _json.writeArrayEnd(); + + _json.writeObjectEnd(); + } + + void writeFromScaleY(FromScaleY *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("FromScaleY"); + + _json.writeName("offset"); + _json.writeValue(obj->_offset); + + _json.writeName("to"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->_to.size(); i++) { + writeToProperty(obj->_to[i]); + } + _json.writeArrayEnd(); + + _json.writeObjectEnd(); + } + + void writeFromShearY(FromShearY *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("FromShearY"); + + _json.writeName("offset"); + _json.writeValue(obj->_offset); + + _json.writeName("to"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->_to.size(); i++) { + writeToProperty(obj->_to[i]); + } + _json.writeArrayEnd(); + + _json.writeObjectEnd(); + } + + void writeFromX(FromX *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("FromX"); + + _json.writeName("offset"); + _json.writeValue(obj->_offset); + + _json.writeName("to"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->_to.size(); i++) { + writeToProperty(obj->_to[i]); + } + _json.writeArrayEnd(); + + _json.writeObjectEnd(); + } + + void writeFromY(FromY *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("FromY"); + + _json.writeName("offset"); + _json.writeValue(obj->_offset); + + _json.writeName("to"); + _json.writeArrayStart(); + for (size_t i = 0; i < obj->_to.size(); i++) { + writeToProperty(obj->_to[i]); + } + _json.writeArrayEnd(); + + _json.writeObjectEnd(); + } + + void writeToProperty(ToProperty *obj) { + if (obj->getRTTI().instanceOf(ToRotate::rtti)) { + writeToRotate((ToRotate *) obj); + } else if (obj->getRTTI().instanceOf(ToScaleX::rtti)) { + writeToScaleX((ToScaleX *) obj); + } else if (obj->getRTTI().instanceOf(ToScaleY::rtti)) { + writeToScaleY((ToScaleY *) obj); + } else if (obj->getRTTI().instanceOf(ToShearY::rtti)) { + writeToShearY((ToShearY *) obj); + } else if (obj->getRTTI().instanceOf(ToX::rtti)) { + writeToX((ToX *) obj); + } else if (obj->getRTTI().instanceOf(ToY::rtti)) { + writeToY((ToY *) obj); + } else { + fprintf(stderr, "Error: Unknown ToProperty type\n"); + exit(1); + } + } + + void writeToRotate(ToRotate *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("ToRotate"); + + _json.writeName("offset"); + _json.writeValue(obj->_offset); + + _json.writeName("max"); + _json.writeValue(obj->_max); + + _json.writeName("scale"); + _json.writeValue(obj->_scale); + + _json.writeObjectEnd(); + } + + void writeToScaleX(ToScaleX *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("ToScaleX"); + + _json.writeName("offset"); + _json.writeValue(obj->_offset); + + _json.writeName("max"); + _json.writeValue(obj->_max); + + _json.writeName("scale"); + _json.writeValue(obj->_scale); + + _json.writeObjectEnd(); + } + + void writeToScaleY(ToScaleY *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("ToScaleY"); + + _json.writeName("offset"); + _json.writeValue(obj->_offset); + + _json.writeName("max"); + _json.writeValue(obj->_max); + + _json.writeName("scale"); + _json.writeValue(obj->_scale); + + _json.writeObjectEnd(); + } + + void writeToShearY(ToShearY *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("ToShearY"); + + _json.writeName("offset"); + _json.writeValue(obj->_offset); + + _json.writeName("max"); + _json.writeValue(obj->_max); + + _json.writeName("scale"); + _json.writeValue(obj->_scale); + + _json.writeObjectEnd(); + } + + void writeToX(ToX *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("ToX"); + + _json.writeName("offset"); + _json.writeValue(obj->_offset); + + _json.writeName("max"); + _json.writeValue(obj->_max); + + _json.writeName("scale"); + _json.writeValue(obj->_scale); + + _json.writeObjectEnd(); + } + + void writeToY(ToY *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("ToY"); + + _json.writeName("offset"); + _json.writeValue(obj->_offset); + + _json.writeName("max"); + _json.writeValue(obj->_max); + + _json.writeName("scale"); + _json.writeValue(obj->_scale); + + _json.writeObjectEnd(); + } + + void writeTransformConstraintPose(TransformConstraintPose *obj) { + if (_visitedObjects.containsKey(obj)) { + _json.writeValue(_visitedObjects[obj]); + return; + } + String refString = String(""); + _visitedObjects.put(obj, refString); + + _json.writeObjectStart(); + _json.writeName("refString"); + _json.writeValue(refString); + _json.writeName("type"); + _json.writeValue("TransformConstraintPose"); + + _json.writeName("mixRotate"); + _json.writeValue(obj->getMixRotate()); + + _json.writeName("mixX"); + _json.writeValue(obj->getMixX()); + + _json.writeName("mixY"); + _json.writeValue(obj->getMixY()); + + _json.writeName("mixScaleX"); + _json.writeValue(obj->getMixScaleX()); + + _json.writeName("mixScaleY"); + _json.writeValue(obj->getMixScaleY()); + + _json.writeName("mixShearY"); + _json.writeValue(obj->getMixShearY()); + + _json.writeObjectEnd(); + } + + void writeUpdate(Update *obj) { + if (obj->getRTTI().instanceOf(BonePose::rtti)) { + writeBonePose((BonePose *) obj); + } else if (obj->getRTTI().instanceOf(IkConstraint::rtti)) { + writeIkConstraint((IkConstraint *) obj); + } else if (obj->getRTTI().instanceOf(PathConstraint::rtti)) { + writePathConstraint((PathConstraint *) obj); + } else if (obj->getRTTI().instanceOf(PhysicsConstraint::rtti)) { + writePhysicsConstraint((PhysicsConstraint *) obj); + } else if (obj->getRTTI().instanceOf(Slider::rtti)) { + writeSlider((Slider *) obj); + } else if (obj->getRTTI().instanceOf(TransformConstraint::rtti)) { + writeTransformConstraint((TransformConstraint *) obj); + } else { + fprintf(stderr, "Error: Unknown Update type\n"); + exit(1); + } + } + + void writeVertexAttachment(VertexAttachment *obj) { + if (obj->getRTTI().instanceOf(BoundingBoxAttachment::rtti)) { + writeBoundingBoxAttachment((BoundingBoxAttachment *) obj); + } else if (obj->getRTTI().instanceOf(ClippingAttachment::rtti)) { + writeClippingAttachment((ClippingAttachment *) obj); + } else if (obj->getRTTI().instanceOf(MeshAttachment::rtti)) { + writeMeshAttachment((MeshAttachment *) obj); + } else if (obj->getRTTI().instanceOf(PathAttachment::rtti)) { + writePathAttachment((PathAttachment *) obj); + } else { + fprintf(stderr, "Error: Unknown VertexAttachment type\n"); + exit(1); + } + } + + // Custom helper methods + void writeColor(Color *obj) { + if (obj == nullptr) { + _json.writeNull(); + } else { + _json.writeObjectStart(); + _json.writeName("r"); + _json.writeValue(obj->r); + _json.writeName("g"); + _json.writeValue(obj->g); + _json.writeName("b"); + _json.writeValue(obj->b); + _json.writeName("a"); + _json.writeValue(obj->a); + _json.writeObjectEnd(); + } + } + + void writeColor(const Color &obj) { + _json.writeObjectStart(); + _json.writeName("r"); + _json.writeValue(obj.r); + _json.writeName("g"); + _json.writeValue(obj.g); + _json.writeName("b"); + _json.writeValue(obj.b); + _json.writeName("a"); + _json.writeValue(obj.a); + _json.writeObjectEnd(); + } + + void writeTextureRegion(TextureRegion *obj) { + if (obj == nullptr) { + _json.writeNull(); + } else { + _json.writeObjectStart(); + _json.writeName("u"); + _json.writeValue(obj->getU()); + _json.writeName("v"); + _json.writeValue(obj->getV()); + _json.writeName("u2"); + _json.writeValue(obj->getU2()); + _json.writeName("v2"); + _json.writeValue(obj->getV2()); + _json.writeName("width"); + _json.writeValue(obj->getRegionWidth()); + _json.writeName("height"); + _json.writeValue(obj->getRegionHeight()); + _json.writeObjectEnd(); + } + } + + void writeTextureRegion(const TextureRegion &obj) { + _json.writeObjectStart(); + _json.writeName("u"); + _json.writeValue(obj.getU()); + _json.writeName("v"); + _json.writeValue(obj.getV()); + _json.writeName("u2"); + _json.writeValue(obj.getU2()); + _json.writeName("v2"); + _json.writeValue(obj.getV2()); + _json.writeName("width"); + _json.writeValue(obj.getRegionWidth()); + _json.writeName("height"); + _json.writeValue(obj.getRegionHeight()); + _json.writeObjectEnd(); + } + + void writeIntArray(const Array &obj) { + _json.writeArrayStart(); + for (size_t i = 0; i < obj.size(); i++) { + _json.writeValue(obj[i]); + } + _json.writeArrayEnd(); + } + + void writeFloatArray(const Array &obj) { + _json.writeArrayStart(); + for (size_t i = 0; i < obj.size(); i++) { + _json.writeValue(obj[i]); + } + _json.writeArrayEnd(); + } + + // Reference versions of write methods + void writeAnimation(const Animation &obj) { + writeAnimation(const_cast(&obj)); + } + + void writeAlphaTimeline(const AlphaTimeline &obj) { + writeAlphaTimeline(const_cast(&obj)); + } + + void writeAttachmentTimeline(const AttachmentTimeline &obj) { + writeAttachmentTimeline(const_cast(&obj)); + } + + void writeDeformTimeline(const DeformTimeline &obj) { + writeDeformTimeline(const_cast(&obj)); + } + + void writeDrawOrderTimeline(const DrawOrderTimeline &obj) { + writeDrawOrderTimeline(const_cast(&obj)); + } + + void writeEventTimeline(const EventTimeline &obj) { + writeEventTimeline(const_cast(&obj)); + } + + void writeIkConstraintTimeline(const IkConstraintTimeline &obj) { + writeIkConstraintTimeline(const_cast(&obj)); + } + + void writeInheritTimeline(const InheritTimeline &obj) { + writeInheritTimeline(const_cast(&obj)); + } + + void writePathConstraintMixTimeline(const PathConstraintMixTimeline &obj) { + writePathConstraintMixTimeline(const_cast(&obj)); + } + + void writePathConstraintPositionTimeline(const PathConstraintPositionTimeline &obj) { + writePathConstraintPositionTimeline(const_cast(&obj)); + } + + void writePathConstraintSpacingTimeline(const PathConstraintSpacingTimeline &obj) { + writePathConstraintSpacingTimeline(const_cast(&obj)); + } + + void writePhysicsConstraintDampingTimeline(const PhysicsConstraintDampingTimeline &obj) { + writePhysicsConstraintDampingTimeline(const_cast(&obj)); + } + + void writePhysicsConstraintGravityTimeline(const PhysicsConstraintGravityTimeline &obj) { + writePhysicsConstraintGravityTimeline(const_cast(&obj)); + } + + void writePhysicsConstraintInertiaTimeline(const PhysicsConstraintInertiaTimeline &obj) { + writePhysicsConstraintInertiaTimeline(const_cast(&obj)); + } + + void writePhysicsConstraintMassTimeline(const PhysicsConstraintMassTimeline &obj) { + writePhysicsConstraintMassTimeline(const_cast(&obj)); + } + + void writePhysicsConstraintMixTimeline(const PhysicsConstraintMixTimeline &obj) { + writePhysicsConstraintMixTimeline(const_cast(&obj)); + } + + void writePhysicsConstraintResetTimeline(const PhysicsConstraintResetTimeline &obj) { + writePhysicsConstraintResetTimeline(const_cast(&obj)); + } + + void writePhysicsConstraintStrengthTimeline(const PhysicsConstraintStrengthTimeline &obj) { + writePhysicsConstraintStrengthTimeline(const_cast(&obj)); + } + + void writePhysicsConstraintWindTimeline(const PhysicsConstraintWindTimeline &obj) { + writePhysicsConstraintWindTimeline(const_cast(&obj)); + } + + void writeRGB2Timeline(const RGB2Timeline &obj) { + writeRGB2Timeline(const_cast(&obj)); + } + + void writeRGBA2Timeline(const RGBA2Timeline &obj) { + writeRGBA2Timeline(const_cast(&obj)); + } + + void writeRGBATimeline(const RGBATimeline &obj) { + writeRGBATimeline(const_cast(&obj)); + } + + void writeRGBTimeline(const RGBTimeline &obj) { + writeRGBTimeline(const_cast(&obj)); + } + + void writeRotateTimeline(const RotateTimeline &obj) { + writeRotateTimeline(const_cast(&obj)); + } + + void writeScaleTimeline(const ScaleTimeline &obj) { + writeScaleTimeline(const_cast(&obj)); + } + + void writeScaleXTimeline(const ScaleXTimeline &obj) { + writeScaleXTimeline(const_cast(&obj)); + } + + void writeScaleYTimeline(const ScaleYTimeline &obj) { + writeScaleYTimeline(const_cast(&obj)); + } + + void writeSequenceTimeline(const SequenceTimeline &obj) { + writeSequenceTimeline(const_cast(&obj)); + } + + void writeShearTimeline(const ShearTimeline &obj) { + writeShearTimeline(const_cast(&obj)); + } + + void writeShearXTimeline(const ShearXTimeline &obj) { + writeShearXTimeline(const_cast(&obj)); + } + + void writeShearYTimeline(const ShearYTimeline &obj) { + writeShearYTimeline(const_cast(&obj)); + } + + void writeSliderMixTimeline(const SliderMixTimeline &obj) { + writeSliderMixTimeline(const_cast(&obj)); + } + + void writeSliderTimeline(const SliderTimeline &obj) { + writeSliderTimeline(const_cast(&obj)); + } + + void writeTransformConstraintTimeline(const TransformConstraintTimeline &obj) { + writeTransformConstraintTimeline(const_cast(&obj)); + } + + void writeTranslateTimeline(const TranslateTimeline &obj) { + writeTranslateTimeline(const_cast(&obj)); + } + + void writeTranslateXTimeline(const TranslateXTimeline &obj) { + writeTranslateXTimeline(const_cast(&obj)); + } + + void writeTranslateYTimeline(const TranslateYTimeline &obj) { + writeTranslateYTimeline(const_cast(&obj)); + } + + void writeAnimationState(const AnimationState &obj) { + writeAnimationState(const_cast(&obj)); + } + + void writeTrackEntry(const TrackEntry &obj) { + writeTrackEntry(const_cast(&obj)); + } + + void writeAnimationStateData(const AnimationStateData &obj) { + writeAnimationStateData(const_cast(&obj)); + } + + void writeBone(const Bone &obj) { + writeBone(const_cast(&obj)); + } + + void writeBoneData(const BoneData &obj) { + writeBoneData(const_cast(&obj)); + } + + void writeBoneLocal(const BoneLocal &obj) { + writeBoneLocal(const_cast(&obj)); + } + + void writeBonePose(const BonePose &obj) { + writeBonePose(const_cast(&obj)); + } + + void writeBoundingBoxAttachment(const BoundingBoxAttachment &obj) { + writeBoundingBoxAttachment(const_cast(&obj)); + } + + void writeClippingAttachment(const ClippingAttachment &obj) { + writeClippingAttachment(const_cast(&obj)); + } + + void writeEvent(const Event &obj) { + writeEvent(const_cast(&obj)); + } + + void writeEventData(const EventData &obj) { + writeEventData(const_cast(&obj)); + } + + void writeIkConstraint(const IkConstraint &obj) { + writeIkConstraint(const_cast(&obj)); + } + + void writeIkConstraintData(const IkConstraintData &obj) { + writeIkConstraintData(const_cast(&obj)); + } + + void writeIkConstraintPose(const IkConstraintPose &obj) { + writeIkConstraintPose(const_cast(&obj)); + } + + void writeMeshAttachment(const MeshAttachment &obj) { + writeMeshAttachment(const_cast(&obj)); + } + + void writePathAttachment(const PathAttachment &obj) { + writePathAttachment(const_cast(&obj)); + } + + void writePathConstraint(const PathConstraint &obj) { + writePathConstraint(const_cast(&obj)); + } + + void writePathConstraintData(const PathConstraintData &obj) { + writePathConstraintData(const_cast(&obj)); + } + + void writePathConstraintPose(const PathConstraintPose &obj) { + writePathConstraintPose(const_cast(&obj)); + } + + void writePhysicsConstraint(const PhysicsConstraint &obj) { + writePhysicsConstraint(const_cast(&obj)); + } + + void writePhysicsConstraintData(const PhysicsConstraintData &obj) { + writePhysicsConstraintData(const_cast(&obj)); + } + + void writePhysicsConstraintPose(const PhysicsConstraintPose &obj) { + writePhysicsConstraintPose(const_cast(&obj)); + } + + void writePointAttachment(const PointAttachment &obj) { + writePointAttachment(const_cast(&obj)); + } + + void writeRegionAttachment(const RegionAttachment &obj) { + writeRegionAttachment(const_cast(&obj)); + } + + void writeSequence(const Sequence &obj) { + writeSequence(const_cast(&obj)); + } + + void writeSkeleton(const Skeleton &obj) { + writeSkeleton(const_cast(&obj)); + } + + void writeSkeletonData(const SkeletonData &obj) { + writeSkeletonData(const_cast(&obj)); + } + + void writeSlider(const Slider &obj) { + writeSlider(const_cast(&obj)); + } + + void writeSliderData(const SliderData &obj) { + writeSliderData(const_cast(&obj)); + } + + void writeSliderPose(const SliderPose &obj) { + writeSliderPose(const_cast(&obj)); + } + + void writeSlot(const Slot &obj) { + writeSlot(const_cast(&obj)); + } + + void writeSlotData(const SlotData &obj) { + writeSlotData(const_cast(&obj)); + } + + void writeSlotPose(const SlotPose &obj) { + writeSlotPose(const_cast(&obj)); + } + + void writeTransformConstraint(const TransformConstraint &obj) { + writeTransformConstraint(const_cast(&obj)); + } + + void writeTransformConstraintData(const TransformConstraintData &obj) { + writeTransformConstraintData(const_cast(&obj)); + } + + void writeFromRotate(const FromRotate &obj) { + writeFromRotate(const_cast(&obj)); + } + + void writeFromScaleX(const FromScaleX &obj) { + writeFromScaleX(const_cast(&obj)); + } + + void writeFromScaleY(const FromScaleY &obj) { + writeFromScaleY(const_cast(&obj)); + } + + void writeFromShearY(const FromShearY &obj) { + writeFromShearY(const_cast(&obj)); + } + + void writeFromX(const FromX &obj) { + writeFromX(const_cast(&obj)); + } + + void writeFromY(const FromY &obj) { + writeFromY(const_cast(&obj)); + } + + void writeToRotate(const ToRotate &obj) { + writeToRotate(const_cast(&obj)); + } + + void writeToScaleX(const ToScaleX &obj) { + writeToScaleX(const_cast(&obj)); + } + + void writeToScaleY(const ToScaleY &obj) { + writeToScaleY(const_cast(&obj)); + } + + void writeToShearY(const ToShearY &obj) { + writeToShearY(const_cast(&obj)); + } + + void writeToX(const ToX &obj) { + writeToX(const_cast(&obj)); + } + + void writeToY(const ToY &obj) { + writeToY(const_cast(&obj)); + } + + void writeTransformConstraintPose(const TransformConstraintPose &obj) { + writeTransformConstraintPose(const_cast(&obj)); + } + + // Reference versions of abstract type write methods + void writeTimeline(const Timeline &obj) { + writeTimeline(const_cast(&obj)); + } + + void writeAttachment(const Attachment &obj) { + writeAttachment(const_cast(&obj)); + } + + void writeConstraint(const Constraint &obj) { + writeConstraint(const_cast(&obj)); + } + + void writeConstraintData(const ConstraintData &obj) { + writeConstraintData(const_cast(&obj)); + } + + void writeFromProperty(const FromProperty &obj) { + writeFromProperty(const_cast(&obj)); + } + + void writeToProperty(const ToProperty &obj) { + writeToProperty(const_cast(&obj)); + } + + void writeUpdate(const Update &obj) { + writeUpdate(const_cast(&obj)); + } + + void writeVertexAttachment(const VertexAttachment &obj) { + writeVertexAttachment(const_cast(&obj)); + } + }; + +}// namespace spine + +#endif \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/test-linux-docker.sh b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/test-linux-docker.sh new file mode 100755 index 0000000..45ab4e9 --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/test-linux-docker.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# Spine-C++ Docker Test Runner +# +# Runs the full spine-cpp test suite inside a Linux Docker container. +# This ensures consistent testing across different host environments. + +set -e + +# Change to spine-runtimes root directory (parent of spine-cpp) +cd "$(dirname "$0")/../.." + +# Source logging utilities +source formatters/logging/logging.sh + +log_title "Spine-C++ Docker Test" +log_detail "Running tests in Linux container" + +# Detect existing build type +BUILD_TYPE="" +cd spine-cpp +if [ -f "build/CMakeCache.txt" ]; then + if grep -q "CMAKE_BUILD_TYPE:STRING=Release" build/CMakeCache.txt 2>/dev/null; then + BUILD_TYPE="release" + elif grep -q "CMAKE_BUILD_TYPE:STRING=Debug" build/CMakeCache.txt 2>/dev/null; then + BUILD_TYPE="debug" + fi + log_detail "Detected existing build type: ${BUILD_TYPE:-unknown}" +fi +cd .. + +# Use a lightweight Linux image with build tools +DOCKER_IMAGE="gcc:12" + +log_action "Pulling Docker image" +if docker pull "$DOCKER_IMAGE" > /dev/null 2>&1; then + log_ok +else + log_fail "Failed to pull Docker image" + exit 1 +fi + +log_action "Running tests in container" +if DOCKER_OUTPUT=$(docker run --rm \ + -v "$(pwd)":/workspace \ + -w /workspace/spine-cpp \ + "$DOCKER_IMAGE" \ + bash -c "apt-get update -qq && apt-get install -y -qq cmake ninja-build && ./tests/test.sh" 2>&1); then + log_ok + + log_action "Analyzing executables" + if ANALYSIS_OUTPUT=$(docker run --rm \ + -v "$(pwd)":/workspace \ + -w /workspace/spine-cpp \ + "$DOCKER_IMAGE" \ + bash -c "echo '=== EXECUTABLE ANALYSIS ==='; for exe in build/headless-test*; do if [ -f \"\$exe\" ] && [ -x \"\$exe\" ]; then echo; echo \"--- \$(basename \"\$exe\") ---\"; echo \"Size: \$(du -h \"\$exe\" | cut -f1)\"; echo \"Dependencies:\"; ldd \"\$exe\" 2>/dev/null || echo 'No dynamic dependencies'; fi; done" 2>&1); then + log_ok + log_detail "$ANALYSIS_OUTPUT" + else + log_fail + log_error_output "$ANALYSIS_OUTPUT" + fi + + log_action "Restoring local build directory" + cd spine-cpp + if rm -rf build; then + if [ -n "$BUILD_TYPE" ]; then + log_detail "Rebuilding $BUILD_TYPE configuration" + if ./build.sh clean "$BUILD_TYPE" > /dev/null 2>&1; then + log_ok "Local build directory restored ($BUILD_TYPE)" + else + log_detail "Warning: Could not restore $BUILD_TYPE build" + fi + else + log_detail "No previous build detected, leaving clean" + log_ok "Build directory cleaned" + fi + else + log_detail "Warning: Could not remove build directory" + fi +else + log_fail + log_error_output "$DOCKER_OUTPUT" + exit 1 +fi \ No newline at end of file diff --git a/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/test.sh b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/test.sh new file mode 100755 index 0000000..6e9ba2b --- /dev/null +++ b/DateToSpine/third_party/spine-runtimes/4.3/spine-cpp/tests/test.sh @@ -0,0 +1,97 @@ +#!/bin/bash +# Spine-C++ Smoke Test +# +# Tests all spine-cpp build variants with spineboy example data: +# - headless-test (regular dynamic) +# - headless-test-no-cpprt (no-cpprt dynamic) +# - headless-test-static (regular static, Linux only) +# - headless-test-no-cpprt-static (no-cpprt static, Linux only) + +set -e + +# Change to spine-cpp root directory +cd "$(dirname "$0")/.." + +# Source logging utilities +source ../formatters/logging/logging.sh + +# Test configuration - spineboy example files and animation +SPINEBOY_SKEL="../examples/spineboy/export/spineboy-pro.skel" +SPINEBOY_ATLAS="../examples/spineboy/export/spineboy-pma.atlas" +SPINEBOY_ANIM="idle" + +# Expected output pattern - first 10 lines of skeleton JSON data +EXPECTED_OUTPUT="=== SKELETON DATA === +{ + \"refString\": \"\", + \"type\": \"SkeletonData\", + \"bones\": [{ + \"refString\": \"\", + \"type\": \"BoneData\", + \"index\": 0, + \"parent\": null, + \"length\": 0," + +log_title "Spine-C++ Test" +log_detail "Platform: $(uname)" + +log_action "Building all variants" +if BUILD_OUTPUT=$(./build.sh clean release 2>&1); then + log_ok +else + log_fail "Build failed" + log_detail "$BUILD_OUTPUT" + exit 1 +fi + +test_count=0 +pass_count=0 + +log_action "Testing map-test" +test_count=$((test_count + 1)) +if OUTPUT=$(build/map-test 2>&1); then + log_ok + pass_count=$((pass_count + 1)) +else + log_fail "map-test - execution failed" + log_detail "$OUTPUT" + echo "" +fi + +for exe in build/headless-test*; do + if [ -f "$exe" ] && [ -x "$exe" ]; then + exe_name=$(basename "$exe") + log_action "Testing $exe_name" + + test_count=$((test_count + 1)) + + if OUTPUT=$("$exe" $SPINEBOY_SKEL $SPINEBOY_ATLAS $SPINEBOY_ANIM 2>&1); then + actual_output=$(echo "$OUTPUT" | head -10) + + if [ "$actual_output" = "$EXPECTED_OUTPUT" ]; then + log_ok + pass_count=$((pass_count + 1)) + else + log_fail "$exe_name - output mismatch" + log_detail "Expected:" + log_detail "$EXPECTED_OUTPUT" + log_detail "" + log_detail "Actual:" + log_detail "$actual_output" + echo "" + fi + else + log_fail "$exe_name - execution failed" + log_detail "$OUTPUT" + echo "" + fi + fi +done + +if [ $pass_count -eq $test_count ] && [ $test_count -gt 0 ]; then + log_summary "✓ All tests passed ($pass_count/$test_count)" + exit 0 +else + log_summary "✗ Tests failed ($pass_count/$test_count)" + exit 1 +fi \ No newline at end of file